久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Canny邊緣檢測(cè)算法原理及其VC實(shí)現(xiàn)詳解(二)

 杰杰梅梅一生一世 2013-05-31

3,、  Canny算法的實(shí)現(xiàn)流程

       由于本文主要目的在于學(xué)習(xí)和實(shí)現(xiàn)算法,,而對(duì)于圖像讀取,、視頻獲取等內(nèi)容不進(jìn)行闡述。因此選用OpenCV算法庫(kù)作為其他功能的實(shí)現(xiàn)途徑(關(guān)于OpenCV的使用,,作者將另文表述),。首先展現(xiàn)本文將要處理的彩色圖片。


圖2 待處理的圖像

3.1 圖像讀取和灰度化

       編程時(shí)采用上文所描述的第二種方法來(lái)實(shí)現(xiàn)圖像的灰度化。其中ptr數(shù)組中保存的灰度化后的圖像數(shù)據(jù),。具體的灰度化后的效果如圖3所示,。

  1. IplImage* ColorImage = cvLoadImage( "12.jpg", -1 );   //讀入圖像,獲取彩圖指針   
  2. IplImage* OpenCvGrayImage;                            //定義變換后的灰度圖指針   
  3. unsigned char* ptr;                                   //指向圖像的數(shù)據(jù)首地址   
  4. if (ColorImage == NULL)  
  5.      return;        
  6. int i = ColorImage->width * ColorImage->height;         
  7. BYTE data1;       //中間過(guò)程變量   
  8. BYTE data2;  
  9. BYTE data3;  
  10. ptr = new unsigned char[i];  
  11. for(intj=0; j<ColorImage->height; j++)                 //對(duì)RGB加權(quán)平均,,權(quán)值參考OpenCV   
  12. {  
  13.      for(intx=0; x<ColorImage->width; x++)  
  14.      {  
  15.          data1 = (BYTE)ColorImage->imageData[j*ColorImage->widthStep + i*3];     //B分量   
  16.      data2 = (BYTE)ColorImage->imageData[j*ColorImage->widthStep + i*3 + 1]; //G分量   
  17.      data3 = (BYTE)ColorImage->imageData[j*ColorImage->widthStep + i*3 + 2]; //R分量   
  18.          ptr[j*ColorImage->width+x]=(BYTE)(0.072169*data1 + 0.715160*data2 + 0.212671*data3);  
  19.      }  
  20. }  
  21. OpenCvGrayImage=cvCreateImageHeader(cvGetSize(ColorImage), ColorImage->depth, 1);    
  22. cvSetData(GrayImage,ptr, GrayImage->widthStep);         //根據(jù)數(shù)據(jù)生成灰度圖   
  23. cvNamedWindow("GrayImage",CV_WINDOW_AUTOSIZE);  
  24. cvShowImage("GrayImage",OpenCvGrayImage);               //顯示灰度圖   
  25. cvWaitKey(0);  
  26. cvDestroyWindow("GrayImage");  


圖3 灰度化后的圖像

3.2 圖像的高斯濾波

       根據(jù)上面所講的邊緣檢測(cè)過(guò)程,,下一個(gè)步驟就是對(duì)圖像進(jìn)行高斯濾波??筛鶕?jù)之前博文描述的方法獲取一維或者二維的高斯濾波核。因此進(jìn)行圖像高斯濾波可有兩種實(shí)現(xiàn)方式,,以下具體進(jìn)行介紹。

       首先定義該部分的通用變量:

  1. double nSigma = 0.4;                            //定義高斯函數(shù)的標(biāo)準(zhǔn)差   
  2. int nWidowSize = 1+2*ceil(3*nSigma);            //定義濾波窗口的大小   
  3. int nCenter = (nWidowSize)/2;                   //定義濾波窗口中心的索引  

       兩種方法都需要用到的變量:

  1. int nWidth = OpenCvGrayImage->width;                             //獲取圖像的像素寬度   
  2. int nHeight = OpenCvGrayImage->height;                           //獲取圖像的像素高度   
  3. unsigned char* nImageData = new unsigned char[nWidth*nHeight];   //暫時(shí)保存圖像中的數(shù)據(jù)   
  4. unsigned char*pCanny = new unsigned char[nWidth*nHeight];        //為平滑后的圖像數(shù)據(jù)分配內(nèi)存   
  5. double* nData = new double[nWidth*nHeight];                      //兩次平滑的中間數(shù)據(jù)   
  6. for(int j=0; j<nHeight; j++)                                     //獲取數(shù)據(jù)   
  7. {  
  8.     for(i=0; i<nWidth; i++)  
  9.              nImageData[j*nWidth+i] = (unsigned char)OpenCvGrayImage->imageData[j*nWidth+i];  
  10. }  

3.2.1 根據(jù)一維高斯核進(jìn)行兩次濾波

       1)生成一維高斯濾波系數(shù)

  1. //////////////////////生成一維高斯濾波系數(shù)/////////////////////////////   
  2. double* pdKernal_1 = new double[nWidowSize];    //定義一維高斯核數(shù)組   
  3. double  dSum_1 = 0.0;                           //求和,,用于進(jìn)行歸一化           
  4. ////////////////////////一維高斯函數(shù)公式//////////////////////////////        
  5. ////                   x*x                           /////////////////   
  6. ////          -1*----------------                    /////////////////   
  7. ////         1     2*Sigma*Sigma                     /////////////////   
  8. ////   ------------ e                                /////////////////   
  9. ////                                                 /////////////////   
  10. ////   \/2*pi*Sigma                                  /////////////////   
  11. //////////////////////////////////////////////////////////////////////   
  12. for(int i=0; i<nWidowSize; i++)  
  13. {  
  14.         double nDis = (double)(i-nCenter);  
  15.     pdKernal_1[i] = exp(-(0.5)*nDis*nDis/(nSigma*nSigma))/(sqrt(2*3.14159)*nSigma);  
  16.     dSum_1 += pdKernal_1[i];  
  17. }  
  18. for(i=0; i<nWidowSize; i++)  
  19. {  
  20.     pdKernal_1[i] /= dSum_1;                 //進(jìn)行歸一化   
  21. }  

       2)分別進(jìn)行x向和y向的一維加權(quán)濾波,濾波后的數(shù)據(jù)保存在矩陣pCanny中 

  1. for(i=0; i<nHeight; i++)                               //進(jìn)行x向的高斯濾波(加權(quán)平均)   
  2. {  
  3.     for(j=0; j<nWidth; j++)  
  4.     {  
  5.         double dSum = 0;  
  6.         double dFilter=0;                                       //濾波中間值   
  7.         for(int nLimit=(-nCenter); nLimit<=nCenter; nLimit++)  
  8.         {  
  9.             if((j+nLimit)>=0 && (j+nLimit) < nWidth )       //圖像不能超出邊界   
  10.             {  
  11.                 dFilter += (double)nImageData[i*nWidth+j+nLimit] * pdKernal_1[nCenter+nLimit];  
  12.                 dSum += pdKernal_1[nCenter+nLimit];  
  13.             }  
  14.         }  
  15.         nData[i*nWidth+j] = dFilter/dSum;  
  16.     }  
  17. }  
  18.   
  19. for(i=0; i<nWidth; i++)                                //進(jìn)行y向的高斯濾波(加權(quán)平均)   
  20. {  
  21.     for(j=0; j<nHeight; j++)  
  22.     {  
  23.         double dSum = 0.0;  
  24.         double dFilter=0;  
  25.         for(int nLimit=(-nCenter); nLimit<=nCenter; nLimit++)  
  26.         {  
  27.             if((j+nLimit)>=0 && (j+nLimit) < nHeight)       //圖像不能超出邊界   
  28.             {  
  29.                 dFilter += (double)nData[(j+nLimit)*nWidth+i] * pdKernal_1[nCenter+nLimit];  
  30.                 dSum += pdKernal_1[nCenter+nLimit];  
  31.             }  
  32.         }  
  33.         pCanny[j*nWidth+i] = (unsigned char)(int)dFilter/dSum;  
  34.     }  
  35. }  

3.2.2 根據(jù)二維高斯核進(jìn)行濾波

      1)生成二維高斯濾波系數(shù)

  1. //////////////////////生成一維高斯濾波系數(shù)//////////////////////////////////     
  2. double* pdKernal_2 = new double[nWidowSize*nWidowSize]; //定義一維高斯核數(shù)組   
  3. double  dSum_2 = 0.0;                                   //求和,,進(jìn)行歸一化         
  4. ///////////////////////二維高斯函數(shù)公式////////////////////////////////////       
  5. ////                         x*x+y*y                        ///////////////   
  6. ////                   -1*--------------                ///////////////   
  7. ////         1             2*Sigma*Sigma                ///////////////   
  8. ////   ---------------- e                                   ///////////////   
  9. ////   2*pi*Sigma*Sigma                                     ///////////////   
  10. ///////////////////////////////////////////////////////////////////////////   
  11. for(i=0; i<nWidowSize; i++)  
  12. {  
  13.     for(int j=0; j<nWidowSize; j++)  
  14.     {  
  15.         int nDis_x = i-nCenter;  
  16.         int nDis_y = j-nCenter;  
  17.         pdKernal_2[i+j*nWidowSize]=exp(-(1/2)*(nDis_x*nDis_x+nDis_y*nDis_y)  
  18.             /(nSigma*nSigma))/(2*3.1415926*nSigma*nSigma);  
  19.         dSum_2 += pdKernal_2[i+j*nWidowSize];  
  20.     }  
  21. }  
  22. for(i=0; i<nWidowSize; i++)  
  23. {  
  24.     for(int j=0; j<nWidowSize; j++)                 //進(jìn)行歸一化   
  25.         {  
  26.         pdKernal_2[i+j*nWidowSize] /= dSum_2;  
  27.     }  
  28. }  

      2)采用高斯核進(jìn)行高斯濾波,,濾波后的數(shù)據(jù)保存在矩陣pCanny中

  1. int x;  
  2. int y;  
  3. for(i=0; i<nHeight; i++)  
  4. {  
  5.     for(j=0; j<nWidth; j++)  
  6.     {  
  7.         double dFilter=0.0;  
  8.         double dSum = 0.0;  
  9.         for(x=(-nCenter); x<=nCenter; x++)                     //行   
  10.         {  
  11.                         for(y=(-nCenter); y<=nCenter; y++)             //列   
  12.             {  
  13.                 if( (j+x)>=0 && (j+x)<nWidth && (i+y)>=0 && (i+y)<nHeight) //判斷邊緣   
  14.                 {  
  15.                     dFilter += (double)nImageData [(i+y)*nWidth + (j+x)]  
  16.                         * pdKernal_2[(y+nCenter)*nWidowSize+(x+nCenter)];  
  17.                     dSum += pdKernal_2[(y+nCenter)*nWidowSize+(x+nCenter)];  
  18.                 }  
  19.             }  
  20.         }  
  21.         pCanny[i*nWidth+j] = (unsigned char)dFilter/dSum;  
  22.     }  
  23. }  

3.3 圖像增強(qiáng)——計(jì)算圖像梯度及其方向

      根據(jù)上文分析可知,實(shí)現(xiàn)代碼如下
  1. //////////////////同樣可以用不同的檢測(cè)器/////////////////////////   
  2. /////    P[i,j]=(S[i,j+1]-S[i,j]+S[i+1,j+1]-S[i+1,j])/2     /////   
  3. /////    Q[i,j]=(S[i,j]-S[i+1,j]+S[i,j+1]-S[i+1,j+1])/2     /////   
  4. /////////////////////////////////////////////////////////////////   
  5. double* P = new double[nWidth*nHeight];                 //x向偏導(dǎo)數(shù)   
  6. double* Q = new double[nWidth*nHeight];                 //y向偏導(dǎo)數(shù)   
  7. int* M = new int[nWidth*nHeight];                       //梯度幅值   
  8. double* Theta = new double[nWidth*nHeight];             //梯度方向   
  9. //計(jì)算x,y方向的偏導(dǎo)數(shù)   
  10. for(i=0; i<(nHeight-1); i++)  
  11. {  
  12.         for(j=0; j<(nWidth-1); j++)  
  13.         {  
  14.               P[i*nWidth+j] = (double)(pCanny[i*nWidth + min(j+1, nWidth-1)] - pCanny[i*nWidth+j] + pCanny[min(i+1, nHeight-1)*nWidth+min(j+1, nWidth-1)] - pCanny[min(i+1, nHeight-1)*nWidth+j])/2;  
  15.               Q[i*nWidth+j] = (double)(pCanny[i*nWidth+j] - pCanny[min(i+1, nHeight-1)*nWidth+j] + pCanny[i*nWidth+min(j+1, nWidth-1)] - pCanny[min(i+1, nHeight-1)*nWidth+min(j+1, nWidth-1)])/2;  
  16.     }  
  17. }  
  18. //計(jì)算梯度幅值和梯度的方向   
  19. for(i=0; i<nHeight; i++)  
  20. {  
  21.         for(j=0; j<nWidth; j++)  
  22.         {  
  23.               M[i*nWidth+j] = (int)(sqrt(P[i*nWidth+j]*P[i*nWidth+j] + Q[i*nWidth+j]*Q[i*nWidth+j])+0.5);  
  24.               Theta[i*nWidth+j] = atan2(Q[i*nWidth+j], P[i*nWidth+j]) * 57.3;  
  25.               if(Theta[i*nWidth+j] < 0)  
  26.                     Theta[i*nWidth+j] += 360;              //將這個(gè)角度轉(zhuǎn)換到0~360范圍   
  27.     }  
  28. }  


3.4 非極大值抑制

      根據(jù)上文所述的工作原理,,這部分首先需要求解每個(gè)像素點(diǎn)在其鄰域內(nèi)的梯度方向的兩個(gè)灰度值,,然后判斷是否為潛在的邊緣,如果不是則將該點(diǎn)灰度值設(shè)置為0.

      首先定義相關(guān)的參數(shù)如下:

  1. unsigned char* N = new unsigned char[nWidth*nHeight];  //非極大值抑制結(jié)果   
  2. int g1=0, g2=0, g3=0, g4=0;                            //用于進(jìn)行插值,,得到亞像素點(diǎn)坐標(biāo)值   
  3. double dTmp1=0.0, dTmp2=0.0;                           //保存兩個(gè)亞像素點(diǎn)插值得到的灰度數(shù)據(jù)   
  4. double dWeight=0.0;                                    //插值的權(quán)重  
      其次,,對(duì)邊界進(jìn)行初始化:

  1. for(i=0; i<nWidth; i++)  
  2. {  
  3.         N[i] = 0;  
  4.         N[(nHeight-1)*nWidth+i] = 0;  
  5. }  
  6. for(j=0; j<nHeight; j++)  
  7. {  
  8.         N[j*nWidth] = 0;  
  9.         N[j*nWidth+(nWidth-1)] = 0;  
  10. }  
      進(jìn)行局部最大值尋找,根據(jù)上文圖1所述的方案進(jìn)行插值,,然后判優(yōu),,實(shí)現(xiàn)代碼如下:
  1. for(i=1; i<(nWidth-1); i++)  
  2. {  
  3.     for(j=1; j<(nHeight-1); j++)  
  4.     {  
  5.         int nPointIdx = i+j*nWidth;       //當(dāng)前點(diǎn)在圖像數(shù)組中的索引值   
  6.         if(M[nPointIdx] == 0)  
  7.             N[nPointIdx] = 0;         //如果當(dāng)前梯度幅值為0,,則不是局部最大對(duì)該點(diǎn)賦為0   
  8.         else  
  9.         {  
  10.         ////////首先判斷屬于那種情況,,然后根據(jù)情況插值///////   
  11.         ////////////////////第一種情況///////////////////////   
  12.         /////////       g1  g2                  /////////////   
  13.         /////////           C                   /////////////   
  14.         /////////           g3  g4              /////////////   
  15.         /////////////////////////////////////////////////////   
  16.         if( ((Theta[nPointIdx]>=90)&&(Theta[nPointIdx]<135)) ||   
  17.                 ((Theta[nPointIdx]>=270)&&(Theta[nPointIdx]<315)))  
  18.             {  
  19.                 //////根據(jù)斜率和四個(gè)中間值進(jìn)行插值求解   
  20.                 g1 = M[nPointIdx-nWidth-1];  
  21.                 g2 = M[nPointIdx-nWidth];  
  22.                 g3 = M[nPointIdx+nWidth];  
  23.                 g4 = M[nPointIdx+nWidth+1];  
  24.                 dWeight = fabs(P[nPointIdx])/fabs(Q[nPointIdx]);   //反正切   
  25.                 dTmp1 = g1*dWeight+g2*(1-dWeight);  
  26.                 dTmp2 = g4*dWeight+g3*(1-dWeight);  
  27.             }  
  28.         ////////////////////第二種情況///////////////////////   
  29.         /////////       g1                      /////////////   
  30.         /////////       g2  C   g3              /////////////   
  31.         /////////               g4              /////////////   
  32.         /////////////////////////////////////////////////////   
  33.             else if( ((Theta[nPointIdx]>=135)&&(Theta[nPointIdx]<180)) ||   
  34.                 ((Theta[nPointIdx]>=315)&&(Theta[nPointIdx]<360)))  
  35.             {  
  36.                 g1 = M[nPointIdx-nWidth-1];  
  37.                 g2 = M[nPointIdx-1];  
  38.                 g3 = M[nPointIdx+1];  
  39.                 g4 = M[nPointIdx+nWidth+1];  
  40.                 dWeight = fabs(Q[nPointIdx])/fabs(P[nPointIdx]);   //正切   
  41.                 dTmp1 = g2*dWeight+g1*(1-dWeight);  
  42.                 dTmp2 = g4*dWeight+g3*(1-dWeight);  
  43.             }  
  44.         ////////////////////第三種情況///////////////////////   
  45.         /////////           g1  g2              /////////////   
  46.         /////////           C                   /////////////   
  47.         /////////       g4  g3                  /////////////   
  48.         /////////////////////////////////////////////////////   
  49.             else if( ((Theta[nPointIdx]>=45)&&(Theta[nPointIdx]<90)) ||   
  50.                 ((Theta[nPointIdx]>=225)&&(Theta[nPointIdx]<270)))  
  51.             {  
  52.                 g1 = M[nPointIdx-nWidth];  
  53.                 g2 = M[nPointIdx-nWidth+1];  
  54.                 g3 = M[nPointIdx+nWidth];  
  55.                 g4 = M[nPointIdx+nWidth-1];  
  56.                 dWeight = fabs(P[nPointIdx])/fabs(Q[nPointIdx]);   //反正切   
  57.                 dTmp1 = g2*dWeight+g1*(1-dWeight);  
  58.                 dTmp2 = g3*dWeight+g4*(1-dWeight);  
  59.             }  
  60.             ////////////////////第四種情況///////////////////////   
  61.             /////////               g1              /////////////   
  62.             /////////       g4  C   g2              /////////////   
  63.             /////////       g3                      /////////////   
  64.             /////////////////////////////////////////////////////   
  65.             else if( ((Theta[nPointIdx]>=0)&&(Theta[nPointIdx]<45)) ||   
  66.                 ((Theta[nPointIdx]>=180)&&(Theta[nPointIdx]<225)))  
  67.             {  
  68.                 g1 = M[nPointIdx-nWidth+1];  
  69.                 g2 = M[nPointIdx+1];  
  70.                 g3 = M[nPointIdx+nWidth-1];  
  71.                 g4 = M[nPointIdx-1];  
  72.                 dWeight = fabs(Q[nPointIdx])/fabs(P[nPointIdx]);   //正切   
  73.                 dTmp1 = g1*dWeight+g2*(1-dWeight);  
  74.                 dTmp2 = g3*dWeight+g4*(1-dWeight);  
  75.             }  
  76.         }         
  77.         //////////進(jìn)行局部最大值判斷,,并寫(xiě)入檢測(cè)結(jié)果////////////////   
  78.         if((M[nPointIdx]>=dTmp1) && (M[nPointIdx]>=dTmp2))  
  79.             N[nPointIdx] = 128;  
  80.         else  
  81.             N[nPointIdx] = 0;  
  82.         }  
  83. }  

3.5雙閾值檢測(cè)實(shí)現(xiàn)

      1)定義相應(yīng)參數(shù)如下

  1. int nHist[1024];   
  2. int nEdgeNum;             //可能邊界數(shù)   
  3. int nMaxMag = 0;          //最大梯度數(shù)   
  4. int nHighCount;  

      2)構(gòu)造灰度圖的統(tǒng)計(jì)直方圖,根據(jù)上文梯度幅值的計(jì)算公式可知,,最大的梯度幅值為:
      因此設(shè)置nHist為1024足夠,。以下實(shí)現(xiàn)統(tǒng)計(jì)直方圖:
  1. for(i=0;i<1024;i++)  
  2.         nHist[i] = 0;  
  3. for(i=0; i<nHeight; i++)  
  4. {  
  5.         for(j=0; j<nWidth; j++)  
  6.         {  
  7.               if(N[i*nWidth+j]==128)  
  8.                    nHist[M[i*nWidth+j]]++;  
  9.         }  
  10. }  

      3)獲取最大梯度幅值及潛在邊緣點(diǎn)個(gè)數(shù)

  1. nEdgeNum = nHist[0];  
  2. nMaxMag = 0;                    //獲取最大的梯度值         
  3. for(i=1; i<1024; i++)           //統(tǒng)計(jì)經(jīng)過(guò)“非最大值抑制”后有多少像素   
  4. {  
  5.     if(nHist[i] != 0)       //梯度為0的點(diǎn)是不可能為邊界點(diǎn)的   
  6.     {  
  7.         nMaxMag = i;  
  8.     }     
  9.     nEdgeNum += nHist[i];   //經(jīng)過(guò)non-maximum suppression后有多少像素   
  10. }  

      4)計(jì)算兩個(gè)閾值

  1. double  dRatHigh = 0.79;  
  2. double  dThrHigh;  
  3. double  dThrLow;  
  4. double  dRatLow = 0.5;  
  5. nHighCount = (int)(dRatHigh * nEdgeNum + 0.5);  
  6. j=1;  
  7. nEdgeNum = nHist[1];  
  8. while((j<(nMaxMag-1)) && (nEdgeNum < nHighCount))  
  9. {  
  10.        j++;  
  11.        nEdgeNum += nHist[j];  
  12. }  
  13. dThrHigh = j;                                   //高閾值   
  14. dThrLow = (int)((dThrHigh) * dRatLow + 0.5);    //低閾值  

      這段代碼的意思是,按照灰度值從低到高的順序,,選取前79%個(gè)灰度值中的最大的灰度值為高閾值,低閾值大約為高閾值的一半。這是根據(jù)經(jīng)驗(yàn)數(shù)據(jù)的來(lái)的,,至于更好地參數(shù)選取方法,,作者后面會(huì)另文研究。
      5)進(jìn)行邊緣檢測(cè)
  1. SIZE sz;  
  2. sz.cx = nWidth;  
  3. sz.cy = nHeight;  
  4. for(i=0; i<nHeight; i++)  
  5. {  
  6.     for(j=0; j<nWidth; j++)  
  7.     {  
  8.         if((N[i*nWidth+j]==128) && (M[i*nWidth+j] >= dThrHigh))  
  9.         {  
  10.             N[i*nWidth+j] = 255;  
  11.             TraceEdge(i, j, dThrLow, N, M, sz);  
  12.         }  
  13.     }  
  14. }  

        以上代碼在非極大值抑制產(chǎn)生的二值灰度矩陣的潛在點(diǎn)中按照高閾值尋找邊緣,,并以所找到的點(diǎn)為中心尋找鄰域內(nèi)滿足低閾值的點(diǎn),從而形成一個(gè)閉合的輪廓,。然后對(duì)于不滿足條件的點(diǎn),,可用如下代碼直接刪除掉,。
  1. //將還沒(méi)有設(shè)置為邊界的點(diǎn)設(shè)置為非邊界點(diǎn)   
  2. for(i=0; i<nHeight; i++)  
  3. {  
  4.     for(j=0; j<nWidth; j++)  
  5.     {  
  6.         if(N[i*nWidth+j] != 255)  
  7.         {  
  8.             N[i*nWidth+j]  = 0 ;   // 設(shè)置為非邊界點(diǎn)   
  9.         }  
  10.     }  
  11. }  

       其中TraceEdge函數(shù)為一個(gè)嵌套函數(shù),用于在每個(gè)像素點(diǎn)的鄰域內(nèi)尋找滿足條件的點(diǎn),。其實(shí)現(xiàn)代碼如下:

  1. void TraceEdge(int y, int x, int nThrLow, LPBYTE pResult, int *pMag, SIZE sz)  
  2. {  
  3.     //對(duì)8鄰域像素進(jìn)行查詢   
  4.     int xNum[8] = {1,1,0,-1,-1,-1,0,1};  
  5.     int yNum[8] = {0,1,1,1,0,-1,-1,-1};  
  6.         LONG yy,xx,k;  
  7.     for(k=0;k<8;k++)  
  8.     {  
  9.         yy = y+yNum[k];  
  10.         xx = x+xNum[k];  
  11.         if(pResult[yy*sz.cx+xx]==128 && pMag[yy*sz.cx+xx]>=nThrLow )  
  12.         {  
  13.             //該點(diǎn)設(shè)為邊界點(diǎn)   
  14.             pResult[yy*sz.cx+xx] = 255;  
  15.             //以該點(diǎn)為中心再進(jìn)行跟蹤   
  16.             TraceEdge(yy,xx,nThrLow,pResult,pMag,sz);  
  17.         }  
  18.     }  
  19. }  

以上就從原理上實(shí)現(xiàn)了整個(gè)Canny算法,。其檢測(cè)效果如圖4所示。注意:以上代碼僅為作者理解所為,,目的是驗(yàn)證本人對(duì)算法的理解,,暫時(shí)沒(méi)有考慮到代碼的執(zhí)行效率的問(wèn)題。

圖4 邊緣檢測(cè)結(jié)果

4,、擴(kuò)展

首先看一下OpenCV中cvCanny函數(shù)對(duì)該圖像的處理結(jié)果,,如圖5所示。

圖5 OpenCV中的Canny邊緣檢測(cè)結(jié)果

     對(duì)比圖4和圖5可以發(fā)現(xiàn),,作者自己實(shí)現(xiàn)的邊緣檢測(cè)效果沒(méi)有OpenCV的好,,具體體現(xiàn)在:1)丟失了一些真的邊緣;2)增加了一些假的邊緣,。

      經(jīng)過(guò)對(duì)整個(gè)算法的來(lái)回檢查,,初步推斷主要的問(wèn)題可能在于在進(jìn)行灰度矩陣梯度幅值計(jì)算式所采用的模板算子性能不是太好,還有就是關(guān)于兩個(gè)閾值的選取方法,。關(guān)于這兩個(gè)方面的改進(jìn)研究,,后文闡述。

5,、總結(jié)

         本文是過(guò)去一段時(shí)間,,對(duì)圖像邊緣檢測(cè)方法學(xué)習(xí)的總結(jié)。主要闡述了Canny算法的工作原理,,實(shí)現(xiàn)過(guò)程,,在此基礎(chǔ)上基于VC6.0實(shí)現(xiàn)了該算法,并給出了效果圖,。最后,,通過(guò)對(duì)比發(fā)現(xiàn)本文的實(shí)現(xiàn)方法雖然能夠?qū)崿F(xiàn)邊緣檢測(cè),但效果還不是很理想,今后將在閾值選取原則和梯度幅值算子兩個(gè)方面進(jìn)行改進(jìn),。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多