opencv(10)图像变换之边缘检测

1.sobel算子



sobel算子利用多项式计算导数的近似值,其计算公式和3*3模版如下,sobel算子结合了一些滤波的效果,对噪声有一定的鲁棒性。

1 2

opencv提供了进行sobel算子的函数,函数如下:

void cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 );

src :输入图像. 单通道,8位或者浮点
dst: 输出图像. 单通道,如果是8位图像,为了防止溢出,输出必须是IPL_DEPTH_16S类型

xorder:  x 方向上的差分阶数
yorder : y 方向上的差分阶数  可以是0 1 2
aperture_size  :扩展 Sobel 核的大小,必须是 1, 3, 5 或 7。 除了尺寸为 1, 其它情况下, aperture_size ×aperture_size 可分离内核将用来计算差分。对 aperture_size=1的情况, 使用 3x1 或 1x3 内核 (不进行高斯平滑操作)。这里有一个特殊变量 CV_SCHARR (=-1),对应 3x3 Scharr 滤波器,可以给出比 3x3 Sobel 滤波更精确的结果。

3

 

sobel算子使用大核计算到导数更加的逼近,小核对噪声更加敏感,当计算X,Y方向的梯度的时候,精确度还可以,但是使用Y/X计算图像梯度方向的时候,精度就很差,尤其是小核的时候。所以opencv提供了scharr滤波器来解决这个问题,计算梯度的准确率会比sobel 3*3的效果好。

 

2.拉普拉斯算子

拉普拉斯算子的是对拉普拉斯函数的离散模拟,函数形式如下,opencv中利用二次sobel算子来实现,先利用sobel算子计算X Y方向的差分,然后再求和。

 

4

opencv中的实现函数:

void cvLaplace( const CvArr* src, CvArr* dst, int aperture_size=3 );参数和cvsobel函数类似。注意的拉普莱斯中对过零问题做了处理,将二阶差分为0 ,一阶差分算子响应低的边缘点滤除掉。3.CANNY算子void cvCanny( const CvArr* image, CvArr* edges, double threshold1,double threshold2, int aperture_size=3 );canny的步骤如下step1:用高斯滤波器平滑图象;step2:用一阶偏导的有限差分来计算梯度的幅值和方向;step3:对梯度幅值进行非极大值抑制;
step4:用双阈值算法检测和连接边缘。
image:canny只接受单通道图像double threshold1,double threshold2为canny算子中采用的两个最大阈值和最小阈值,一个像素的梯度大于最大阈值被认定为边缘,如果小于最小阈值则被抛弃,如果介于二者之间,主要当期与高于上限阈值的连接时才会被认定为接受。也可以采用自适应的阈值算法,可以参考:自适应阈值算法aperture:计算一阶偏导的时候opencv采用sobel算子,这个参数为sobel的内核大小。默认为3*3

 
 

测试代码:

   1: IplImage *Image1;
   2: Image1 = cvLoadImage("7.jpg");
   3: IplImage *ImageGray = cvCreateImage(cvGetSize(Image1),IPL_DEPTH_8U,1);
   4: IplImage *SobelDstImg= cvCreateImage(cvGetSize(Image1),IPL_DEPTH_16S,1);
   5: IplImage *ImageGray2 = cvCreateImage(cvGetSize(Image1),IPL_DEPTH_8U,1);
   6: cvCvtColor(Image1,ImageGray,CV_BGR2GRAY);
   7:  
   8: cvNamedWindow("src");
   9: cvShowImage("src",ImageGray);
  10:  
  11: cvSobel(ImageGray,SobelDstImg,1,1,3 );
  12: cvConvertScaleAbs(SobelDstImg,ImageGray2);
  13:  
  14: cvNamedWindow("sobel");
  15: cvShowImage("sobel",ImageGray2);
  16:  
  17: cvLaplace(ImageGray,SobelDstImg,3);
  18: cvConvertScaleAbs(SobelDstImg,ImageGray2);
  19:  
  20: cvNamedWindow("Laplace");
  21: cvShowImage("Laplace",ImageGray2);
  22:  
  23: cvCanny(ImageGray,ImageGray2,50,100,3);
  24:  
  25: cvNamedWindow("Canny");
  26: cvShowImage("Canny",ImageGray2);
  27:  
  28: cvCanny(ImageGray,ImageGray2,100,150,3);
  29:  
  30: cvNamedWindow("Canny2");
  31: cvShowImage("Canny2",ImageGray2);
  32:  
  33: cvWaitKey();

测试图像:

5

 

6

 

sobel检测效果没有canny好,拉普拉斯产生了双边缘,canny不同的阈值得到的结果也有很大的差别。

posted @ 2012-06-19 02:33  RubbyZhang  阅读(2779)  评论(0编辑  收藏  举报