Opencv2系列學習筆記9(使用Canny算子檢測輪廓)

前面我們用sobel算子和拉普拉斯變換也可以進行邊緣檢測,見我的上一篇blog:

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

但這樣得到的二值邊緣圖像有兩大缺點。第一:檢測到的邊緣過粗,這意味着難以實現物體的精確定位。第二:難以找到這樣的閥值,即能足夠低檢測到所有重要的邊緣,同時也不至於包含過多次要的邊緣。

這個正是canny算子要解決的。

Canny算子通常基於sobel算子,有兩個閥值,這樣可以得到兩幅邊緣圖;canny算法組合這兩幅邊緣圖以生成一副“最優”的輪廓圖。如果存在連續的邊緣點,則將低閥值圖像中的邊緣點與高閥值圖像中的邊緣相連接,那麼就保留低閥值圖像中的邊緣點。這種使用雙閥值以得到二值圖像的策略被稱爲磁滯閥值化。

代碼:

  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, 歡迎交流!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章