opencv sobel导数
- 如何使用OpenCV函數?Sobel?對圖像求導。
- 如何使用OpenCV函數?Scharr?更準確地計算??核的導數。
原理
Note
?以下內容來自于Bradski和Kaehler的大作:?Learning OpenCV?.
上面兩節我們已經學習了卷積操作。一個最重要的卷積運算就是導數的計算(或者近似計算).
為什么對圖像進行求導是重要的呢? 假設我們需要檢測圖像中的?邊緣?,如下圖:
你可以看到在?邊緣?,相素值顯著的?改變?了。表示這一?改變?的一個方法是使用?導數?。 梯度值的大變預示著圖像中內容的顯著變化。
用更加形象的圖像來解釋,假設我們有一張一維圖形。下圖中灰度值的”躍升”表示邊緣的存在:
使用一階微分求導我們可以更加清晰的看到邊緣”躍升”的存在(這里顯示為高峰值)
從上例中我們可以推論檢測邊緣可以通過定位梯度值大于鄰域的相素的方法找到(或者推廣到大于一個閥值).
更加詳細的解釋,請參考Bradski 和 Kaehler的?Learning OpenCV?。
Sobel算子
計算
假設被作用圖像為?:
在兩個方向求導:
水平變化: 將??與一個奇數大小的內核??進行卷積。比如,當內核大小為3時,??的計算結果為:
垂直變化: 將:math:I?與一個奇數大小的內核??進行卷積。比如,當內核大小為3時,??的計算結果為:
在圖像的每一點,結合以上兩個結果求出近似?梯度:
有時也用下面更簡單公式代替:
Note
當內核大小為??時, 以上Sobel內核可能產生比較明顯的誤差(畢竟,Sobel算子只是求取了導數的近似值)。 為解決這一問題,OpenCV提供了?Scharr?函數,但該函數僅作用于大小為3的內核。該函數的運算與Sobel函數一樣快,但結果卻更加精確,其內核為:
關于(?Scharr?)的更多信息請參考OpenCV文檔。在下面的示例代碼中,你會發現在?Sobel?函數調用的上面有被注釋掉的?Scharr?函數調用。 反注釋Scharr調用 (當然也要相應的注釋掉Sobel調用),看看該函數是如何工作的。
源碼
- 使用?Sobel算子?產生的輸出圖像上,檢測到的亮起的?邊緣?相素散布在更暗的背景中。
解釋
首先申明變量:
Mat src, src_gray; Mat grad; char* window_name = "Sobel Demo - Simple Edge Detector"; int scale = 1; int delta = 0; int ddepth = CV_16S;裝載原圖像?src:
src = imread( argv[1] );if( !src.data ) { return -1; }第一步對原圖像使用?GaussianBlur?降噪 ( 內核大小 = 3 )
GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );將降噪后的圖像轉換為灰度圖:
cvtColor( src, src_gray, CV_RGB2GRAY );第二步,在?x?和?y?方向分別”求導“。 為此,我們使用函數?Sobel?:
Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y;/// 求 X方向梯度 Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT ); /// 求 Y方向梯度 Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );該函數接受了以下參數:
- src_gray: 在本例中為輸入圖像,元素類型?CV_8U
- grad_x/grad_y: 輸出圖像.
- ddepth: 輸出圖像的深度,設定為?CV_16S?避免外溢。
- x_order:?x?方向求導的階數。
- y_order:?y?方向求導的階數。
- scale,?delta?和?BORDER_DEFAULT: 使用默認值
注意為了在?x?方向求導我們使用:??,?. 采用同樣方法在?y?方向求導。
將中間結果轉換到?CV_8U:
convertScaleAbs( grad_x, abs_grad_x ); convertScaleAbs( grad_y, abs_grad_y );將兩個方向的梯度相加來求取近似?梯度?(注意這里沒有準確的計算,但是對我們來講已經足夠了)。
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );最后,顯示結果:
imshow( window_name, grad );結果
這里是將Sobel算子作用于?lena.jpg?的結果:
總結
以上是生活随笔為你收集整理的opencv sobel导数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: opencv图像边界的填充
- 下一篇: OpenCV函数 Laplacian 算