轉自:http://blog.csdn.net/likezhaobin/article/details/6892176算法
圖象的邊緣是指圖象局部區域亮度變化顯著的部分,該區域的灰度剖面通常能夠看做是一個階躍,既從一個灰度值在很小的緩衝區域內急劇變化到另外一個灰度相差較大的灰度值。圖象的邊緣部分集中了圖象的大部分信息,圖象邊緣的肯定與提取對於整個圖象場景的識別與理解是很是重要的,同時也是圖象分割所依賴的重要特徵,邊緣檢測主要是圖象的灰度變化的度量、檢測和定位,自從1959提出邊緣檢測以來,通過五十多年的發展,已有許多中不一樣的邊緣檢測方法。根據做者的理解和實踐,本文對邊緣檢測的原理進行了描述,在此基礎上着重對Canny檢測算法的實現進行詳述。編程
本文所述內容均由編程驗證而來,在實現過程當中,有任何錯誤或者不足之處你們共同討論(本文不講述枯燥的理論證實和數學推導,僅僅從算法的實現以及改進上進行原理性和工程化的描述)。數據結構
在以前的博文中,做者從一維函數的躍變檢測開始,按部就班的對二維圖像邊緣檢測的基本原理進行了通俗化的描述。結論是:實現圖像的邊緣檢測,就是要用離散化梯度逼近函數根據二維灰度矩陣梯度向量來尋找圖像灰度矩陣的灰度躍變位置,而後在圖像中將這些位置的點連起來就構成了所謂的圖像邊緣(圖像邊緣在這裏是一個統稱,包括了二維圖像上的邊緣、角點、紋理等基元圖)。函數
在實際狀況中理想的灰度階躍及其線條邊緣圖像是不多見到的,同時大多數的傳感器件具備低頻濾波特性,這樣會使得階躍邊緣變爲斜坡性邊緣,看起來其中的強度變化不是瞬間的,而是跨越了必定的距離。這就使得在邊緣檢測中首先要進行的工做是濾波。性能
1)濾波:邊緣檢測的算法主要是基於圖像強度的一階和二階導數,但導數一般對噪聲很敏感,所以必須採用濾波器來改善與噪聲有關的邊緣檢測器的性能。常見的濾波方法主要有高斯濾波,即採用離散化的高斯函數產生一組歸一化的高斯核(具體見「高斯濾波原理及其編程離散化實現方法」一文),而後基於高斯核函數對圖像灰度矩陣的每一點進行加權求和(具體程序實現見下文)。測試
2)加強:加強邊緣的基礎是肯定圖像各點鄰域強度的變化值。加強算法能夠將圖像灰度點鄰域強度值有顯著變化的點凸顯出來。在具體編程實現時,可經過計算梯度幅值來肯定。.net
3)檢測:通過加強的圖像,每每鄰域中有不少點的梯度值比較大,而在特定的應用中,這些點並非咱們要找的邊緣點,因此應該採用某種方法來對這些點進行取捨。實際工程中,經常使用的方法是經過閾值化方法來檢測。blog
JohnCanny於1986年提出Canny算子,它與Marr(LoG)邊緣檢測方法相似,也屬因而先平滑後求導數的方法。本節對根據上述的邊緣檢測過程對Canny檢測算法的原理進行介紹。get
Canny算法一般處理的圖像爲灰度圖,所以若是攝像機獲取的是彩色圖像,那首先就得進行灰度化。對一幅彩色圖進行灰度化,就是根據圖像各個通道的採樣值進行加權平均。以RGB格式的彩圖爲例,一般灰度化採用的方法主要有:數學
方法1:Gray=(R+G+B)/3;
方法2:Gray=0.299R+0.587G+0.114B;(這種參數考慮到了人眼的生理特色)
注意1:至於其餘格式的彩色圖像,能夠根據相應的轉換關係轉爲RGB而後再進行灰度化;
注意2:在編程時要注意圖像格式中RGB的順序一般爲BGR。
圖像高斯濾波的實現能夠用兩個一維高斯核分別兩次加權實現,也能夠經過一個二維高斯核一次卷積實現。
1)高斯覈實現
上式爲離散化的一維高斯函數,肯定參數就能夠獲得一維核向量。
上式爲離散化的二維高斯函數,肯定參數就能夠獲得二維核向量。
注意1:關於參數Sigma的取值詳見上篇博文。
注意2:在求的高斯核後,要對整個核進行歸一化處理。
2)圖像高斯濾波
對圖像進行高斯濾波,聽起來很玄乎,其實就是根據待濾波的像素點及其鄰域點的灰度值按照必定的參數規則進行加權平均。這樣能夠有效濾去理想圖像中疊加的高頻噪聲。
一般濾波和邊緣檢測是矛盾的概念,抑制了噪聲會使得圖像邊緣模糊,這回增長邊緣定位的不肯定性;而若是要提升邊緣檢測的靈敏度,同時對噪聲也提升了靈敏度。實際工程經驗代表,高斯函數肯定的核能夠在抗噪聲干擾和邊緣檢測精肯定位之間提供較好的折衷方案。這就是所謂的高斯圖像濾波,具體實現代碼見下文。
關於圖像灰度值得梯度可以使用一階有限差分來進行近似,這樣就能夠得圖像在x和y方向上偏導數的兩個矩陣。經常使用的梯度算子有以下幾種:
1)Roberts算子
上式爲其x和y方向偏導數計算模板,可用數學公式表達其每一個點的梯度幅值爲:
2)Sobel算子
上式三個矩陣分別爲該算子的x向卷積模板、y向卷積模板以及待處理點的鄰域點標記矩陣,據此可用數學公式表達其每一個點的梯度幅值爲:
3)Prewitt算子
和Sobel算子原理同樣,在此僅給出其卷積模板。
4)Canny算法所採用的方法
在本文實現的Canny算法中所採用的卷積算子比較簡單,表達以下:
其x向、y向的一階偏導數矩陣,梯度幅值以及梯度方向的數學表達式爲:
求出這幾個矩陣後,就能夠進行下一步的檢測過程。
圖1 非極大值抑制原理
根據圖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。根據下文的具體測試圖像能夠看出,這樣一個檢測結果仍是包含了不少由噪聲及其餘緣由形成的假邊緣。所以還須要進一步的處理。