第六章 - 圖像變換 -梯度和Sobel導數(cvSobel)

該文章轉載於:http://blog.csdn.net/hitwengqi/article/details/6877638

cvSobel可用於邊緣檢測,即簡單的梯度算法(邊緣提取算法)。

(以下兩段摘自網絡)

        首先,我們來開一下計算機是如何檢測邊緣的。以灰度圖像爲例,它的理論基礎是這樣的,如果出現一個邊緣,那麼圖像的灰度就會有一定的變化,爲了方便假設由黑漸變爲白代表一個邊界,那麼對其灰度分析,在邊緣的灰度函數就是一個一次函數y=kx,對其求一階導數就是其斜率k,就是說邊緣的一階導數是一個常數,而由於非邊緣的一階導數爲零,這樣通過求一階導數就能初步判斷圖像的邊緣了。通常是X方向和Y方向的導數,也就是梯度。理論上計算機就是通過這種方式來獲得圖像的邊緣。

        但是,具體應用到圖像中你會發現這個導數是求不了的,因爲沒一個準確的函數讓你去求導,而且計算機在求解析解要比求數值解麻煩得多,所以就想到了一種替代的方式來求導數。就是用一個3×3的窗口來對圖像進行近似求導。拿對X方向求導爲例,某一點的導數爲第三行的元素之和減去第一行元素之和,這樣就求得了某一點的近似導數。其實也很好理解爲什麼它就近似代表導數,導數就代表一個變化率,從第一行變爲第三行,灰度值相減,當然就是一個變化率了。這就是所謂的Prewitt算子。這樣近似X方向導數就求出來了。Y方向導數與X方向導數求法相似,只不過是用第三列元素之和減去第一列元素之和。X方向和Y方向導數有了,那麼梯度也就出來了。這樣就可以找出一幅圖中的邊緣了。 還有一個問題,由於求的是3×3中心點的導數,所以給第二列加了一個權重,它的權重爲2,第一列和第三列的權重爲1,好了,這就是Sobel算子了。相比Prewitt算子,Sobel的抗噪能力更強。如圖所示:Sobel算子及cvSobel這樣,中心點的X方向導數就求出來了。

舉個例子吧。Sobel算子及cvSobel,X點以Sobel方式求導數ΔX=1×50+2×30+1×50-(1×50+2×30+1×50)=0。這樣可以看出這個點不是邊界。

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

該函數如下:

Sobel

使用擴展 Sobel 算子計算一階、二階、三階或混合圖像差分

void cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 );
src
輸入圖像.
dst
輸出圖像.
xorder
x 方向上的差分階數
yorder
y 方向上的差分階數
aperture_size
擴展 Sobel 核的大小,必須是 1, 3, 5 或 7。 除了尺寸爲 1, 其它情況下, aperture_size ×aperture_size 可分離內核將用來計算差分。對 aperture_size=1的情況, 使用 3x1 或 1x3 內核 (不進行高斯平滑操作)。這裏有一個特殊變量 CV_SCHARR (=-1),對應 3x3 Scharr 濾波器,可以給出比 3x3 Sobel 濾波更精確的結果。Scharr 濾波器係數是:

\begin{bmatrix}     -3 & 0 & 3 \\     -10 & 0 & 10 \\     -3 & 0 & 3  \end{bmatrix}

對 x-方向 或矩陣轉置後對 y-方向。

函數 cvSobel 通過對圖像用相應的內核進行卷積操作來計算圖像差分:

dst(x,y) = \frac{d^{xorder+yorder}src} {dx^{xorder} dy^{yorder}} |(x,y)

由於Sobel 算子結合了 Gaussian 平滑和微分,所以,其結果或多或少對噪聲有一定的魯棒性。通常情況,函數調用採用如下參數 (xorder=1, yorder=0, aperture_size=3) 或 (xorder=0, yorder=1, aperture_size=3) 來計算一階 x- 或 y- 方向的圖像差分。第一種情況對應:

\begin{bmatrix}     -1 & 0 & 1 \\     -2 & 0 & 2 \\     -1 & 0 & 1  \end{bmatrix} 核。

第二種對應:

\begin{bmatrix}     -1 & -2 & -1 \\     0 & 0 & 0 \\     1 & 2 & 1  \end{bmatrix}

或者

\begin{bmatrix}     1 & 2 & 1 \\     0 & 0 & 0 \\     -1 & -2 & -1  \end{bmatrix}

核的選則依賴於圖像原點的定義 (origin 來自 IplImage 結構的定義)。由於該函數不進行圖像尺度變換,所以和輸入圖像(數組)相比,輸出圖像(數組)的元素通常具有更大的絕對數值(譯者注:即像素的位深)。爲防止溢出,當輸入圖像是 8 位的,要求輸出圖像是 16 位的。當然可以用函數 cvConvertScale 或 cvConvertScaleAbs 把運算結果(dst)轉換爲 8 位的。除了8-位圖像,函數也接受 32-位 浮點數圖像。所有輸入和輸出圖像都必須是單通道的,並且具有相同的圖像尺寸或者ROI尺寸。

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

/*code*/

  1. #include <highgui.h>  
  2. #include <cv.h>  
  3.   
  4. int main(int argc, char ** argv)  
  5. {  
  6.     IplImage* src, *dst;  
  7.   
  8.     src = cvLoadImage( argv[1] );  
  9.     dst = cvCreateImage( cvGetSize( src ), IPL_DEPTH_16S, 3 );  
  10.     //這裏有錯誤,應該再將dst轉爲灰度,再送去sobel處理  
  11.     cvNamedWindow( "src", 0 );  
  12.     cvShowImage( "src", src );  
  13.     cvNamedWindow( "sobel", 0 );  
  14.   
  15.     cvSobel( src, dst, 0, 1, 7 );  //sobel  
  16.     cvShowImage( "sobel", dst );  
  17.     cvWaitKey(0);  
  18.     cvReleaseImage( &src );  
  19.     cvReleaseImage( &dst );  
  20.   
  21.     return 0;  
  22. }  

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

/*result*/

after sobel

aperture_size == 7.

更多0
上一篇:第六章 - 圖像變換 - 卷積邊界(cvCopyMakeBorder) 下一篇:第六章 - 圖像變換 -拉普拉斯變換(cvLaplace)

發佈了2 篇原創文章 · 獲贊 11 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章