ESTABLISHED 2015
TAKASHI

void cvCanny( const CvArr* image,CvArr* edges,double threshold1,double threshold2, int aperture_size=3 );
image輸入單通道圖像(可以是彩色圖像)對於多通道的圖像可以用cvCvtColor()修改。
---------------------------------------------------------------------------------
edges 輸出的邊緣圖像,也是單通道的,但是是黑白的
---------------------------------------------------------------------------------
threshold1第一個閾值
---------------------------------------------------------------------------------
threshold2 第二個閾值
---------------------------------------------------------------------------------
aperture_size Sobel 算子內核大小
小叮嚀:cvCanny只接受單通道圖像作為輸入
Canny邊緣檢測算法原理
屬於是先平滑後求導數的方法
Step.1 對原始圖像進行灰度化
Canny算法通常處理的圖像為灰度圖,因此如果攝像機獲取的是彩色圖像,那首先就得進行灰度化。對一幅彩色圖進行灰度化,就是根據圖像各個通道的採樣值進行加權平均。以RGB格式的彩圖為例,通常灰度化採用的方法主要有:
方法1:Gray=(R+G+B)/3;
方法2:Gray=0.299R+0.587G+0.114B;(這種參數考慮到了人眼的生理特點)
注意1:至於其他格式的彩色圖像,可以根據相應的轉換關係轉為RGB然後再進行灰度化;
注意2:在編程時要注意圖像格式中R->G->B的順序通常為B->G->R。
Step.2 對圖像進行高斯濾波
圖像高斯濾波的實現可以用兩個一維高斯核分別兩次加權實現,也可以通過一個二維高斯核一次卷積實現。
Step.3 用一階偏導的有限差分來計算梯度的幅值和方向
Canny算法所採用的方法
在本文實現的Canny算法中所採用的捲積算子比較簡單,表達如下:
其x向、y向的一階偏導數矩陣,梯度幅值以及梯度方向的數學表達式為:
求出這幾個矩陣後,就可以進行下一步的檢測過程。
Step.4 對梯度幅值進行非極大值抑制
圖像梯度幅值矩陣中的元素值越大,說明圖像中該點的梯度值越大,但這不不能說明該點就是邊緣(這僅僅是屬於圖像增強的過程)。在Canny算法中,非極大值抑制是進行邊緣檢測的重要步驟,通俗意義上是指尋找像素點局部最大值,將非極大值點所對應的灰度值置為0,這樣可以剔除掉一大部分非邊緣的點(這是本人的理解)。
根據圖1 可知,要進行非極大值抑制,就首先要確定像素點C的灰度值在其8值鄰域內是否為最大。
圖1中藍色的線條方向為C點的梯度方向,這樣就可以確定其局部的最大值肯定分佈在這條線上,
也即出了C點外,梯度方向的交點dTmp1和dTmp2這兩個點的值也可能會是局部最大值。
因此,判斷C點灰度與這兩個點灰度大小即可判斷C點是否為其鄰域內的局部最大灰度點。
如果經過判斷,C點灰度值小於這兩個點中的任一個,那就說明C點不是局部極大值,那麼則可以排除C點為邊緣。
這就是非極大值抑制的工作原理。
作者認為,在理解的過程中需要注意以下兩點:
(1)中非最大抑制是回答這樣一個問題:"當前的梯度值在梯度方向上是一個局部最大值嗎?"
所以,要把當前位置的梯度值與梯度方向上兩側的梯度值進行比較;
(2)梯度方向垂直於邊緣方向。
但實際上,我們只能得到C點鄰域的8個點的值,而dTmp1和dTmp2並不在其中,
要得到這兩個值就需要對該兩個點兩端的已知灰度進行線性插值,也即根據圖1中的g1和g2對dTmp1進行插值,
根據g3和g4對dTmp2進行插值,這要用到其梯度方向,這是上文Canny算法中要求解梯度方向矩陣Thita的原因。
完成非極大值抑制後,會得到一個二值圖像,非邊緣的點灰度值均為0,可能為邊緣的局部灰度極大值點可設置其灰度為128。 根據下文的具體測試圖像可以看出,這樣一個檢測結果還是包含了很多由噪聲及其他原因造成的假邊緣。
因此還需要進一步的處理。
Step.5 用雙閾值算法檢測和連接邊緣
Canny算法中減少假邊緣數量的方法是採用雙閾值法。
選擇兩個閾值(關於閾值的選取方法在擴展中進行討論),根據高閾值得到一個邊緣圖像,
這樣一個圖像含有很少的假邊緣,但是由於閾值較高,產生的圖像邊緣可能不閉合,
未解決這樣一個問題採用了另外一個低閾值。
在高閾值圖像中把邊緣鏈接成輪廓,當到達輪廓的端點時,該算法會在斷點的8鄰域點中尋找滿足低閾值的點,
再根據此點收集新的邊緣,直到整個圖像邊緣閉合。



