Opencv2系列学习笔记9(使用Canny算子检测轮廓)

来源:互联网 发布:湖南拼车软件 编辑:程序博客网 时间:2024/05/17 08:30

前面我们用sobel算子和拉普拉斯变换也可以进行边缘检测,见我的上一篇blog:

http://blog.csdn.net/lu597203933/article/details/17252285

但这样得到的二值边缘图像有两大缺点。第一:检测到的边缘过粗,这意味着难以实现物体的精确定位。第二:难以找到这样的阀值,即能足够低检测到所有重要的边缘,同时也不至于包含过多次要的边缘。

这个正是canny算子要解决的。

Canny算子通常基于sobel算子,有两个阀值,这样可以得到两幅边缘图;canny算法组合这两幅边缘图以生成一副“最优”的轮廓图。如果存在连续的边缘点,则将低阀值图像中的边缘点与高阀值图像中的边缘相连接,那么就保留低阀值图像中的边缘点。这种使用双阀值以得到二值图像的策略被称为磁滞阀值化。

代码:

[cpp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. int main()  
  2. {  
  3.     Mat image = imread("F:\\lena.png", 0);    // 这里也可以是BGR 但是想想提取轮廓 效果是一样的  
  4.     if(!image.data)  
  5.     {  
  6.         cout << "Fail to load image" << endl;  
  7.         return 0;  
  8.     }  
  9.     Mat result;  
  10.     Canny(image, result, 150, 220);  
  11.     namedWindow("cannyResult");  
  12.     imshow("cannyResult", result);  
  13.     waitKey(0);  
  14.     return 0;  
  15. }  

结果:


当然你也可以将其与上篇博客中的结果进行比对,发现效果会好很多。

另附上:

Matlab的Canny算子

BW =edge(I,'canny')  

用canny算子实现边缘检测

BW =edge(I,'canny',thresh)

为canny算法指定sensitivitythresholds(阈值)。

指定两个阈值(二维矢量):第一个元素为低阈值,第二个元素为高阈值。

指定一个阈值(单个数值):用作高阈值,低阈值为0.4*高阈值。

未指定阈值(或用[]代替):自动根据图像的梯度直方图计算高低阈值。

BW =edge(I,'canny',thresh,sigma)

sigma 表示高斯滤波器的标准差,默认值为sqrt(2)。滤波器大小根据sigma值自动计算。

[BW,thresh] =edge(I,'canny',...)

用thresh返回两个阈值。

 

OpenCV的Canny算子

cvCanny函数头:

void cvCanny(
const CvArr* img,
CvArr* edges,
double lowThresh,
double highThresh,
int apertureSize = 3
);

image            单通道输入图像
edges            单通道图像,保存图像边缘
threshold1     阈值1
threshold2     阈值2
apertureSize  Sobel算子的孔径参数 (参见 cvSobel 函数)

------------------------------

来自:http://hi.baidu.com/windroc/item/2c3afac341a6542cee4665ca



作者:小村长  出处:http://blog.csdn.net/lu597203933 欢迎转载或分享,但请务必声明文章出处。 (新浪微博:小村长zack, 欢迎交流!

0 0
原创粉丝点击