爲什麼opencv的canny函數檢測邊緣的效果和matlab的不同

先上兩張經過處理後的圖片進行對比

 

1、opencv

2、matlab

 可以明顯的看出matlab的邊緣更爲細膩。

 

首先回顧一下傳統的canny算法的主要步驟:

1、使用sobel差分算子求出灰度圖像的x和y方向導數;

2、求出圖像各點梯度大小及其方向;

3、設置高低兩個閾值,梯度大於高閾值爲強邊像素點,大於低閾值爲潛在可能是較弱的邊緣點;

4、在經過一次篩選剩下的強邊緣點中沿着梯度方向進行非極大值抑制;

5、順着二次篩選後的強邊點尋找鄰近的弱邊點得到最終的邊緣。


opencv和matlab都基本按照以上步驟得到各自的canny函數,但一般來說處理之前都先對圖像進行模糊平滑,這樣得到的效果更好。opencv更注重實時性,所以連平滑都作爲可選項放在函數外,而matlab則更注重質量,除了加入平滑操作外,還有其他一系列的優化操作,以下逐項比較。

 
1、模糊平滑

這一項其實對生成的邊緣效果影響十分大,平滑的越流暢則生成的邊緣越圓滑,一般使用高斯低通濾波;那麼濾波器的大小以及高斯分佈的方差是兩個關鍵的參數,通過實驗確定取什麼值最優,但一般用5×5和方差爲2的就可以了,opencv的cvSmooth函數可以進行平滑,一般都是使用輸入和輸出都是8位深的圖像,而matlab是把圖像轉換爲浮點類型後進行平滑操作,這樣一來從精度上說matlab就已經更勝一籌了,因爲這直接決定後面的求導運算得到的兩個方向導數的精度。

 
2、梯度

在sobel的運用上兩者是一致的,但是求梯度的方向的算法兩者是截然不同的,但本質一樣,效果經過筆者測試基本相同。在梯度的大小方面,opencv提供了歐式距離和哈密頓距離兩種度量方式,前者是平方和後開方,後者是直接絕對值的加和,opencv默認使用後者,我們知道((x2+y2)/2)1/2>=(|x|+|y|)/2,以及|x|+|y|>=(x2+y2)1/2 所以理論上使用哈密頓距離也基本符合真實數值,但總歸是有精度上的差別,這也是爲什麼有人說opencv的canny不如matlab好的第二個原因了,在cv.h裏面可以通過修改CV_CANNY_L2_GRADIENT來進行切換。


3、閾值

這裏的閾值是梯度大小是否能夠通過的開關,opencv的閾值都採用手工設置的方式,而matlab是把所有點的強度作出直方圖,保留一定百分比的強邊緣,這個步驟的差別不會影響結果的質量,但是在速度上當然會有差別,這是速度和方便程度的矛盾。


4、薄邊效果

經過非極大值抑制後的邊緣基本上是一到兩個像素點的寬度,最終希望得到一個線寬的邊緣,opencv只是通過簡單的判斷來防止並行或者並列出現兩個強邊像素,這種簡單的薄邊手法會導致邊緣的斷裂,而matlab採用了Louisa Lam, Seong-Whan Lee, and Ching Y. Wuen, "Thinning Methodologies-A Comprehensive Survey," IEEE TrPAMI, vol. 14, no. 9, pp. 869-885, 1992.  這邊文章的方法進行兩次薄邊處理,效果相當好,所得的邊緣十分圓滑。


綜上所述,要想opencv的效果和matlab的差不多就必須在平滑上下功夫,梯度的大小要用歐式距離度量,另外要加入matlab的薄邊算法,這樣一來處理時間大概會增加一倍,但也基本可以滿足實時處理。另外在一般視覺應用中可以把算法修改爲一個閾值,去掉強弱邊連接這一步驟以提高速度。

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