OpenCV函数 Canny 检测边缘
- OpenCV函數?Canny?檢測邊緣.
原理
- 低錯誤率:?標識出盡可能多的實際邊緣,同時盡可能的減少噪聲產生的誤報。
- 高定位性:?標識出的邊緣要與圖像中的實際邊緣盡可能接近。
- 最小響應:?圖像中的邊緣只能標識一次。
步驟
消除噪聲。 使用高斯平滑濾波器卷積降噪。 下面顯示了一個??的高斯內核示例:
計算梯度幅值和方向。 此處,按照Sobel濾波器的步驟:
運用一對卷積陣列 (分別作用于??和??方向):
使用下列公式計算梯度幅值和方向:
梯度方向近似到四個可能角度之一(一般 0, 45, 90, 135)
非極大值?抑制。 這一步排除非邊緣像素, 僅僅保留了一些細線條(候選邊緣)。
滯后閾值: 最后一步,Canny 使用了滯后閾值,滯后閾值需要兩個閾值(高閾值和低閾值):
Canny 推薦的?高:低?閾值比在 2:1 到3:1之間。
想要了解更多細節,你可以參考任何你喜歡的計算機視覺書籍。
源碼
- 要求使用者輸入一個數字,設置?Canny Edge Detector?的低閾值 (通過trackbar)
- 使用?Canny 邊緣檢測?產生一個?mask?(白線代表邊緣,黑色代表背景)。
- 使用?mask?作為掩碼顯示原圖像。
解釋
創建程序中要用到的變量:
Mat src, src_gray;Mat dst, detected_edges;int edgeThresh = 1;int lowThreshold;int const max_lowThreshold = 100;int ratio = 3;int kernel_size = 3;char* window_name = "Edge Map";注意:a. 我們首先設定高:低閾值比為 3:1 (通過變量 *ratio* ) b. 設定內核尺寸為 :math:`3` (Canny函數內部調用Sobel操作) c. 將低閾值的上限設定為 :math:`100`.裝載原圖像:
/// 裝載圖像 src = imread( argv[1] );if( !src.data ){ return -1; }創建與?src?同類型和大小的矩陣(dst)
dst.create( src.size(), src.type() );將輸入圖像轉換到灰度空間 (使用函數?cvtColor):
cvtColor( src, src_gray, CV_BGR2GRAY );創建顯示窗口
namedWindow( window_name, CV_WINDOW_AUTOSIZE );創建trackbar,來獲取用戶交互輸入的低閾值:
createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold );注意:
讓我們一步一步的來觀察?CannyThreshold?函數:
首先, 使用 3x3的內核平滑圖像:
blur( src_gray, detected_edges, Size(3,3) );其次,運用?Canny?尋找邊緣:
Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );輸入參數:
- detected_edges: 原灰度圖像
- detected_edges: 輸出圖像 (支持原地計算,可為輸入圖像)
- lowThreshold: 用戶通過 trackbar設定的值。
- highThreshold: 設定為低閾值的3倍 (根據Canny算法的推薦)
- kernel_size: 設定為 3 (Sobel內核大小,內部使用)
填充?dst?圖像,填充值為0 (圖像全黑).
dst = Scalar::all(0);最后, 使用函數?copyTo?標識被檢測到的邊緣部分 (背景為黑色).
src.copyTo( dst, detected_edges);copyTo?將?src?圖像拷貝到?dst?. 但是,僅僅拷貝掩碼不為0的像素。既然Canny邊緣檢測的輸出是鑲嵌在黑色背景中的邊緣像素,因此其結果?dst圖像除了被檢測的邊緣像素,其余部分都為黑色。
顯示結果:
imshow( window_name, dst );結果
-
在編譯上面的代碼之后, 我們可以運行結果,將圖片路徑輸入,如下圖:
-
滑動標尺, 嘗試不同的閾值,我們得到如下結果:
-
仔細觀察邊緣像素是如何疊加在黑色背景之上的。
總結
以上是生活随笔為你收集整理的OpenCV函数 Canny 检测边缘的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV函数 Laplacian 算
- 下一篇: opencv copyto函数