在圖像處理和計算機視覺領域中,如何從當前的圖像中提取所需要的特征信息是圖像識別的關鍵所在。在許多應用場合中需要快速准確地檢測出直線或者圓。其中一種非常有效的解決問題的方法是霍夫(Hough)變換,其為圖像處理中從圖像中識別幾何形狀的基本方法之一,應用很廣泛,也有很多改進算法。最基本的霍夫變換是從黑白圖像中檢測直線(線段)。
1、霍夫變換
⑴霍夫變換概述
霍夫變換(Hough Transform)是圖像處理中的一種特征提取技術,該過程在一個參數空間中通過計算累計結果的局部最大值得到一個符合該特定形狀的集合作為霍夫變換結果。
霍夫變換於1962年由PaulHough首次提出,最初的Hough變換是設計用來檢測直線和曲線,起初的方法要求知道物體邊界線的解析方程,但不需要有關區域位置的先驗知識。這種方法的一個突出優點是分割結果的Robustness,即對數據的不完全或噪聲不是非常敏感。然而,要獲得描述邊界的解析表達常常是不可能的。后於1972年由Richard Duda & Peter Hart推廣使用,經典霍夫變換用來檢測圖像中的直線,后來霍夫變換擴展到任意形狀物體的識別,多為圓和橢圓。霍夫變換運用兩個坐標空間之間的變換將在一個空間中具有相同形狀的曲線或直線映射到另一個坐標空間的一個點上形成峰值,從而把檢測任意形狀的問題轉化為統計峰值問題。
⑵霍夫線變換
我們知道,霍夫線變換是一種用來尋找直線的方法. 在使用霍夫線變換之前, 首先要對圖像進行邊緣檢測的處理,也即霍夫線變換的直接輸入只能是邊緣二值圖像.
OpenCV支持三種不同的霍夫線變換,它們分別是:
●標准霍夫變換(Standard Hough Transform,SHT)
●多尺度霍夫變換(Multi-Scale Hough Transform,MSHT)
●累計概率霍夫變換(Progressive Probabilistic Hough Transform ,PPHT)。
其中,多尺度霍夫變換(MSHT)為經典霍夫變換(SHT)在多尺度下的一個變種。累計概率霍夫變換(PPHT)算法是標准霍夫變換(SHT)算法的一個改進,它在一定的范圍內進行霍夫變換,計算單獨線段的方向以及范圍,從而減少計算量,縮短計算時間。之所以稱PPHT為“概率”的,是因為並不將累加器平面內的所有可能的點累加,而只是累加其中的一部分,該想法是如果峰值如果足夠高,只用一小部分時間去尋找它就夠了。這樣猜想的話,可以實質性地減少計算時間。
在OpenCV中,我們可以用HoughLines函數來調用標准霍夫變換SHT和多尺度霍夫變換MSHT。
而HoughLinesP函數用於調用累計概率霍夫變換PPHT。累計概率霍夫變換執行效率很高,所有相比於HoughLines函數,我們更傾向於使用HoughLinesP函數。
總結一下,OpenCV中的霍夫線變換有如下三種:
<1>標准霍夫變換(StandardHough Transform,SHT),由HoughLines函數調用。
<2>多尺度霍夫變換(Multi-ScaleHough Transform,MSHT),由HoughLines函數調用。
<3>累計概率霍夫變換(ProgressiveProbabilistic Hough Transform,PPHT),由HoughLinesP函數調用。
⑶霍夫線變換的原理
【1】眾所周知, 一條直線在圖像二維空間可由兩個變量表示. 如:
<1>在笛卡爾坐標系: 可由參數: 斜率和截距(m,b) 表示。
<2>在極坐標系: 可由參數: 極徑和極角![]()

對於霍夫變換, 我們將采用第二種方式極坐標系來表示直線. 因此, 直線的表達式可為:

化簡便可得到:
![]()
【2】一般來說對於點
, 我們可以將通過這個點的一族直線統一定義為:
![]()
這就意味着每一對
代表一條通過點
的直線。
【3】如果對於一個給定點
我們在極坐標對極徑極角平面繪出所有通過它的直線, 將得到一條正弦曲線. 例如, 對於給定點X_0= 8 和Y_0= 6 我們可以繪出下圖 (在平面):

這三條曲線在平面相交於點 (0.925, 9.6), 坐標表示的是參數對
或者是說點
, 點
和點
組成的平面內的的直線。
【5】以上的說明表明,一般來說, 一條直線能夠通過在平面
尋找交於一點的曲線數量來檢測。而越多曲線交於一點也就意味着這個交點表示的直線由更多的點組成. 一般來說我們可以通過設置直線上點的閾值來定義多少條曲線交於一點我們才認為檢測到了一條直線。
【6】這就是霍夫線變換要做的. 它追蹤圖像中每個點對應曲線間的交點. 如果交於一點的曲線的數量超過了閾值, 那么可以認為這個交點所代表的參數對
在原圖像中為一條直線。
2、霍夫圓變換
霍夫圓變換的基本原理和上面講的霍夫線變化大體上是很類似的,只是點對應的二維極徑極角空間被三維的圓心點x, y還有半徑r空間取代。說“大體上類似”的原因是,如果完全用相同的方法的話,累加平面會被三維的累加容器所代替:在這三維中,一維是x,一維是y,另外一維是圓的半徑r。這就意味着需要大量的內存而且執行效率會很低,速度會很慢。
對直線來說, 一條直線能由參數極徑極角
表示. 而對圓來說, 我們需要三個參數來表示一個圓, 也就是:

這里的 表示圓心的位置 (下圖中的綠點) 而 r 表示半徑, 這樣我們就能唯一的定義一個圓了, 見下圖:


在OpenCV中,我們一般通過一個叫做“霍夫梯度法”的方法來解決圓變換的問題。
⑴霍夫梯度法的原理
【1】首先對圖像應用邊緣檢測,比如用canny邊緣檢測。
【2】然后,對邊緣圖像中的每一個非零點,考慮其局部梯度,即用Sobel()函數計算x和y方向的Sobel一階導數得到梯度。
【3】利用得到的梯度,由斜率指定的直線上的每一個點都在累加器中被累加,這里的斜率是從一個指定的最小值到指定的最大值的距離。
【4】同時,標記邊緣圖像中每一個非0像素的位置。
【5】然后從二維累加器中這些點中選擇候選的中心,這些中心都大於給定閾值並且大於其所有近鄰。這些候選的中心按照累加值降序排列,以便於最支持像素的中心首先出現。
【6】接下來對每一個中心,考慮所有的非0像素。
【7】這些像素按照其與中心的距離排序。從到最大半徑的最小距離算起,選擇非0像素最支持的一條半徑。8.如果一個中心收到邊緣圖像非0像素最充分的支持,並且到前期被選擇的中心有足夠的距離,那么它就會被保留下來。
這個實現可以使算法執行起來更高效,或許更加重要的是,能夠幫助解決三維累加器中會產生許多噪聲並且使得結果不穩定的稀疏分布問題。
人無完人,金無足赤。同樣,這個算法也並不是十全十美的,還有許多需要指出的缺點。
