opencv 邊緣檢測(reberts,sobel,prewitt,kirsch)

來源:互聯網
上載者:User

經典的邊緣檢測方法是對原始映像中像素的某小鄰域來構造邊緣檢測運算元。常用的邊緣檢測方法有Roberts運算元、Sobe l運算元、Prew itt運算元、K irsch運算元、Laplacian運算元、LOG 運算元、C anny運算元等。

一、基於一階微分的邊緣檢測方法

1、最簡單的梯度運算元是Roberts運算元, 它是一個2 * 2模板, 利用局部差分檢測比較陡峭的邊緣, 但對於雜訊較敏感, 經常會出現孤立點 。

//roberts運算元求映像梯度提取邊緣,輸入源映像,輸出梯度圖,此方法不常用void roberts(IplImage *src,IplImage *dst){ //為roberts映像申請空間,因為要利用源映像指標中的imageData,因此使用複製方式 dst=cvCloneImage(src); int x,y,i,w,h; int temp,temp1; uchar* ptr=(uchar*) (dst->imageData ); int ptr1[4]={0}; int indexx[4]={0,1,1,0}; int indexy[4]={0,0,1,1};    w=dst->width; h=dst->height; for(y=0;y<h-1;y++)  for(x=0;x<w-1;x++)  {   for(i=0;i<4;i++)    //取每個2*2矩陣元素的指標      0 | 1   {                   //                             3 | 2    ptr1[i]= *(ptr+(y+indexy[i])*dst->widthStep+x+indexx[i]);       }   temp=abs(ptr1[0]-ptr1[2]);    //計算2*2矩陣中0和2位置的差,取絕對值temp   temp1=abs(ptr1[1]-ptr1[3]);   //計算2*2矩陣中1和3位置的差,取絕對值temp1   temp=(temp>temp1?temp:temp1); //若temp1>temp,則以temp1的值替換temp      temp= (int)sqrt(float(temp*temp)+float(temp1*temp1));  //輸出值  /* if (temp>100)    temp=255;   else temp=0;  */   *(ptr+y*dst->widthStep+x)=temp;    //將輸出值存放於dst像素的對應位置  } double min_val = 0,max_val = 0;//取圖並顯示像中的最大最小像素值 cvMinMaxLoc(dst,&min_val,&max_val);    printf("max_val = %f\nmin_val = %f\n",max_val,min_val); cvSaveImage("RobertsImg.jpg", dst);//把映像存入檔案 cvNamedWindow("robert",1); cvShowImage("robert",dst);}

 

2、Prewitt運算元和Sobe l運算元。這兩種運算元在求梯度之前, 首先進行鄰域平均或加權平均, 然後進行微分, 就抑制了雜訊, 但容易出現邊緣模糊現象。

 

//如果源映像是8位的,為避免溢出,靶心圖表像深度必須是16S,或32位
void sobel(IplImage *src,IplImage *dst){//為soble微分映像申請空間,建立圖片函數IplImage *pSobelImg_dx = cvCreateImage(cvGetSize(src),32,1);IplImage *pSobelImg_dy = cvCreateImage(cvGetSize(src),32,1);IplImage *pSobelImg_dxdy = cvCreateImage(cvGetSize(src), 32,1);//用sobel運算元計算兩個方向的微分cvSobel(src , pSobelImg_dx, 1, 0, 3);cvSobel(src , pSobelImg_dy, 0, 1, 3);     //total gradient = sqrt(horizontal*horizontal+vertical*vertical)     int i,j;     double v1,v2,v;     for (i=0;i<src->height;i++)     {          for (j=0;j<src->width;j++)           {                    v1 = cvGetReal2D(pSobelImg_dx,i,j);                    v2 = cvGetReal2D(pSobelImg_dy,i,j);                    v = sqrt(v1*v1+v2*v2);/*if(v>100) v = 255;else v = 0;*/                    cvSetReal2D(pSobelImg_dxdy,i,j,v);           }     }cvConvertScale(pSobelImg_dxdy,dst);   //將映像轉化為8位double min_val = 0,max_val = 0;//取圖並顯示像中的最大最小像素值cvMinMaxLoc(pSobelImg_dxdy,&min_val,&max_val);   printf("max_val = %f\nmin_val = %f\n",max_val,min_val);    //歸一化    cvNormalize(dst,dst,0,255,CV_MINMAX,0);

//prewitt運算元,模板卷積公式編寫,常用方法

void prewitt(IplImage *src,IplImage *dst){ //定義prewitt運算元的模板 float prewittx[9] =          {  -1,0,1,  -1,0,1,  -1,0,1 }; float prewitty[9] =  {  1,1,1,  0,0,0,  -1,-1,-1 }; CvMat px;    px = cvMat(3,3,CV_32F,prewittx);    CvMat py; py = cvMat(3,3,CV_32F,prewitty);

 //為輸出映像申請空間 IplImage *dstx = cvCreateImage(cvGetSize(src),8,1);  IplImage *dsty = cvCreateImage(cvGetSize(src),8,1);

 //對映像使用模板,自動填滿邊界 cvFilter2D(src,dstx,&px,cvPoint(-1,-1));  cvFilter2D(src,dsty,&py,cvPoint(-1,-1));

 //計算梯度,範數為2,注意學習指標的使用方法 int i,j,temp; float tempx,tempy;  //定義為浮點型是為了避免sqrt函數引起歧義 uchar* ptrx = (uchar*) dstx->imageData; uchar* ptry = (uchar*) dsty->imageData; for(i = 0;i<src->width;i++) {  for(j = 0;j<src->height;j++)  {   tempx = ptrx[i+j*dstx->widthStep];   //tempx,tempy表示的是指標所指向的像素   tempy = ptry[i+j*dsty->widthStep];    temp = (int) sqrt(tempx*tempx+tempy*tempy);   /*if(temp>100) temp = 255;   else temp = 0;*/   dst->imageData[i+j*dstx->widthStep] = temp;  } }  double min_val = 0, max_val = 0;//取圖並顯示像中的最大最小像素值 cvMinMaxLoc(dst,&min_val,&max_val);    printf("max_val = %f\nmin_val = %f\n",max_val,min_val);  //計算梯度,範數為1 //cvAdd(dstx,dsty,dst); cvSaveImage("PrewittImg.jpg", dst);//把映像存入檔案 cvReleaseImage(&dstx); cvReleaseImage(&dsty); cvNamedWindow("prewitt",1); cvShowImage("prewitt",dst);}

 
//Kirsch運算元,根據方向的對稱性,可以只對前面4個模板進行處理,求最大值。採用求中心像素周圍像素梯度,此方法是最好用的方法。void kirsch(IplImage *src,IplImage *dst){dst = cvCloneImage(src);//cvConvert(src,srcMat); //將映像轉化成矩陣處理int x,y;float a,b,c,d;float p1,p2,p3,p4,p5,p6,p7,p8,p9; uchar* ps = (uchar*)src->imageData ; //ps為指向輸入圖片資料的指標uchar* pd = (uchar*)dst->imageData ; //pd為指向輸出圖片資料的指標int w = dst->width;int h = dst->height;int step = dst->widthStep;for(x = 0;x<w-2;x++)      //取以(x+1,y+1)為中心的9個鄰域像素  1 4 7{                                                            // 2 5 8for(y = 0;y<h-2;y++)                                     // 3 6 9{  p1=ps[y*step+x];p2=ps[y*step+(x+1)];p3=ps[y*step+(x+2)];p4=ps[(y+1)*step+x];p5=ps[(y+1)*step+(x+1)];p6=ps[(y+1)*step+(x+2)];p7=ps[(y+2)*step+x];p8=ps[(y+2)*step+(x+1)];p9=ps[(y+2)*step+(x+2)];//得到(i+1,j+1)周圍九個點的灰階值a = fabs(float(-5*p1-5*p2-5*p3+3*p4+3*p6+3*p7+3*p8+3*p9));    //計算4個方向的梯度值b = fabs(float(3*p1-5*p2-5*p3+3*p4-5*p6+3*p7+3*p8+3*p9));c = fabs(float(3*p1+3*p2-5*p3+3*p4-5*p6+3*p7+3*p8-5*p9));d = fabs(float(3*p1+3*p2+3*p3+3*p4-5*p6+3*p7-5*p8-5*p9));a = max(a,b);                                         //取各個方向上的最大值作為邊緣強度a = max(a,c);a = max(a,d);pd[(y+1)*step+(x+1)] = a;/*if(a>100){pd[(y+1)*step+(x+1)]=255;}else pd[(y+1)*step+(x+1)]=0;*/}}double min_val = 0, max_val = 0;//取圖並顯示像中的最大最小像素值cvMinMaxLoc(dst,&min_val,&max_val);   printf("max_val = %f\nmin_val = %f\n",max_val,min_val);cvNormalize(dst,dst,0,255,CV_MINMAX); //歸一化處理cvSaveImage("KirschImg.jpg", dst);//把映像存入檔案cvNamedWindow("kirsch",1);cvShowImage("kirsch",dst);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.