Canny边缘检测算法原理及其VC实现详解(二)

转载自:http://blog.csdn.net/likezhaobin/article/details/6892629

 

3、  Canny算法的实现流程

       由于本文主要目的在于学习和实现算法,而对于图像读取、视频获取等内容不进行阐述。因此选用OpenCV算法库作为其他功能的实现途径(关于OpenCV的使用,作者将另文表述)。首先展现本文将要处理的彩色图片。


图2 待处理的图像

3.1 图像读取和灰度化

       编程时采用上文所描述的第二种方法来实现图像的灰度化。其中ptr数组中保存的灰度化后的图像数据。具体的灰度化后的效果如图3所示。

 

  1. IplImage* ColorImage cvLoadImage( "12.jpg"-1 );   //读入图像,获取彩图指针  
  2. IplImage* OpenCvGrayImage;                            //定义变换后的灰度图指针  
  3. unsigned charptr;                                   //指向图像的数据首地址  
  4. if (ColorImage == NULL)  
  5.      return       
  6. int ColorImage->width ColorImage->height;         
  7. BYTE data1;       //中间过程变量  
  8. BYTE data2;  
  9. BYTE data3;  
  10. ptr new unsigned char[i];  
  11. for(intj=0; j<ColorImage->height; j++)                 //对RGB加权平均,权值参考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);         //根据数据生成灰度图  
  23. cvNamedWindow("GrayImage",CV_WINDOW_AUTOSIZE);  
  24. cvShowImage("GrayImage",OpenCvGrayImage);               //显示灰度图  
  25. cvWaitKey(0);  
  26. cvDestroyWindow("GrayImage");  


 

图3 灰度化后的图像

 

3.2 图像的高斯滤波

       根据上面所讲的边缘检测过程,下一个步骤就是对图像进行高斯滤波。可根据之前博文描述的方法获取一维或者二维的高斯滤波核。因此进行图像高斯滤波可有两种实现方式,以下具体进行介绍。

       首先定义该部分的通用变量:

 

  1. double nSigma 0.4;                            //定义高斯函数的标准差  
  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 charnImageData new unsigned char[nWidth*nHeight];   //暂时保存图像中的数据  
  4. unsigned char*pCanny new unsigned char[nWidth*nHeight];        //为平滑后的图像数据分配内存  
  5. doublenData new double[nWidth*nHeight];                      //两次平滑的中间数据  
  6. for(int j=0; j<nHeight; 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 根据一维高斯核进行两次滤波

       1)生成一维高斯滤波系数

 

  1. //生成一维高斯滤波系数/  
  2. doublepdKernal_1 new double[nWidowSize];    //定义一维高斯核数组  
  3. double  dSum_1 0.0;                           //求和,用于进行归一化          
  4. 一维高斯函数公式//       
  5.                    x*x                           /  
  6.           -1*----------------                    /  
  7.              2*Sigma*Sigma                     /  
  8.    ------------                                /  
  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;                 //进行归一化  
  21.  


 

 

       2)分别进行x向和y向的一维加权滤波,滤波后的数据保存在矩阵pCanny中

  1. for(i=0; i<nHeight; i++)                               //进行x向的高斯滤波(加权平均)  
  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++)                                //进行y向的高斯滤波(加权平均)  
  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 根据二维高斯核进行滤波

      1)生成二维高斯滤波系数

  1. //生成一维高斯滤波系数//    
  2. doublepdKernal_2 new double[nWidowSize*nWidowSize]; //定义一维高斯核数组  
  3. double  dSum_2 0.0;                                   //求和,进行归一化        
  4. ///二维高斯函数公式      
  5.                          x*x+y*y                        ///  
  6.                    -1*--------------                ///  
  7.                      2*Sigma*Sigma                ///  
  8.    ----------------                                   ///  
  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++)                 //进行归一化  
  25.          
  26.         pdKernal_2[i+j*nWidowSize] /= dSum_2;  
  27.      
  28.  


      2)采用高斯核进行高斯滤波,滤波后的数据保存在矩阵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.  


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值