傳統的Canny邊緣檢測算法是一種有效而又相對簡單的算法,可以得到很好的結果(可以參考上一篇Canny邊緣檢測算法的實現)。但是Canny算法本身也有一些缺陷,可以有改進的地方。
1. Canny邊緣檢測第一步用高斯模糊來去掉噪聲,但是同時也會平滑邊緣,使得邊緣信息減弱,有可能使得在后面的步驟中漏掉一些需要的邊緣,特別是弱邊緣和孤立的邊緣,可能在雙閥值和聯通計算中被剔除。很自然地可以預見,如果加大高斯模糊的半徑,對噪聲的平滑力度加大,但也會使得最后得到的邊緣圖中的邊緣明顯減少。這里依然用Lena圖為例,保持Canny算法中高閥值100,低閥值50不變,高斯半徑分別為2,3,5的Canny邊緣二值圖像如下。可知高斯模糊把很多有用的邊緣信息也模糊掉了,因此如何精確的選擇高斯半徑就相當重要。
高斯半徑2 高斯半徑3 高斯半徑5
2. 在最初的Canny算法中是使用的最小的2x2領域來計算梯度幅值的。這種方法對噪聲很敏感,比較容易檢測到偽邊緣或漏掉真是邊緣。在上一篇算法實現中,實際上使用的是3x3的Sobel梯度算子,是一種比較好的選擇。
3. 傳統Canny算法的雙閥值是全局固定的,因此雙閥值大小的選取對最終的結果影響很大,也有一些經驗,比如選擇低閥值是高閥值的0.4或0.5。然而這畢竟是一種經驗選擇,閥值的確定仍然很難決定一個最優值。而且一個圖像的不同局部區域可能需要各不相同的閥值來精確地找到真實邊緣,因此全局閥值就不太合適了。
4. 傳統算法仍然可能產生一條寬度大於1的邊緣,達不到滿意的高精度單點響應。也就是需要繼續細化邊緣。
下面就一些可以改進的地方做一些討論。
代替高斯模糊
噪聲是高頻信號,邊緣信號也屬於高頻信號。既然高斯模糊不加區分的對所有的高頻信息進行了模糊,效果自然不盡如人意。那么自然就想到了帶有保留邊緣功能的各種選擇性平滑方法,似乎在這里比高斯模糊會更加合適,那我們就來試一試。帶有保留邊緣功能的平滑方法的基本思想不是讓領域范圍內的所有像素都參與該種平滑方法的計算,而是設定一個閥值,僅僅讓和中心像素灰度的差值小於這個閥值的像素參與計算。這樣和中心像素相差過大的像素被認為是帶有有效的信息,而不是噪聲,不會參與平滑計算,從而保留了這些有用的高頻信號,那么邊緣信號自然也在保留的范圍。具體的算法可以參考這篇文章http://www.cnblogs.com/Imageshop/p/4694540.html,已經講得很清楚了。無論是均值平滑,中值平滑,表面模糊,都可以參考這種算法來實現選擇性模糊。
應用有保留邊緣的選擇性模糊來代替高斯模糊后,可以發現,模糊領域的半徑值基本影響不了Canny檢測的結果,最后的結果只跟選擇模糊設定的閥值有關。下面以均值模糊為例,Canny檢測的高閥值100低閥值50不變,均值模糊閥值30,不同模糊半徑的結果。在均值模糊閥值不變的情況下,不同領域半徑下,最后的結果差別不大。
均值模糊半徑2,閥值30 均值模糊半徑5,閥值30 均值模糊半徑15,閥值30
而保持模糊半徑5不變的話,使用不同模糊門限閥值,閥值越大,也就是有越多的領域像素參與模糊計算,最后保留的邊緣就越少了。
均值模糊半徑5,閥值40 均值模糊半徑5,閥值50
相對於高斯模糊,在相同半徑下,可以看出應用有保留邊緣功能的選擇性模糊,明顯能保留了更多的邊緣細節,使得很多相對較弱的邊緣得意保留下來了。我另外還實驗了選擇性的中值模糊,表面模糊,他們和選擇性的均值模糊都能達到類似的效果。這里就不一一列舉結果了。其中選擇性的表面模糊,因為中心像素的權重高,最后Canny檢測結果在參數相同的情況下,保留的邊緣相對較多一些。總的來說,應用有保留邊緣功能的選擇性模糊來代替高斯模糊,參數的選擇(領域半徑和閥值門限)不像高斯模糊半徑參數選擇那么嚴格,所以檢測結果更穩定一些。但是參數要多了一個。
梯度算子選擇
對於算法中梯度的計算,梯度算子可以有多種選擇。我試了一下,如果用一階梯度算子,Robert交叉算子,他們都是2x2的算子,來代替Sobel,保持高斯模糊半徑2,高閥值100低閥值50不變,結果如下。要注意的是,由於一階梯度算子和Robert算子都是2x2的算子,他們算出來的梯度在幅度上都要小於Sobel算子。即使用同樣的高低閥值,最后的結果也不具有可比性。因此,參照Sobel算子的幅度,2x2算子的x,y方向梯度都乘以相應地倍數(4倍),最后進行比較。
一階差分Canny二值圖 Robert交叉梯度Canny二值圖 Sobel算子Canny二值圖
可以看到,一階差分最后的結果在邊緣的連通性上是最差的,Robert算子要好一些,Sobel算子最好。在這幾種選擇當中,似乎Sobel算子是最好的選擇。另外還可以使用Prewitt算子和5x5Sobel算子。Prewitt算子也是3x3的,僅僅參數不同,在平滑性能上略微不如Sobel算子。一般來說,比如在Lena圖上,Canny邊緣結果和用Sobel算子的結果差別不大。5x5Sobel算子在平滑性能上要更強一些。