一、概念
1.1 標準霍夫變換檢測圓
與霍夫變換檢測直線是非常類似的,只是將引數空間擴充套件到了三維,把問題轉換為求解引數空間中相交最多的 (a,b,r)引數對,其中(a,b)是圓心,r是半徑,但這種方式增加了很多的計算量,所以在實際中並不常用。
1.2 OpenCV中的霍夫梯度檢測圓
OpenCV中霍夫變換圓檢測對標準霍夫變換圓檢測做了運算上的最佳化,它採用的是 “霍夫梯度法”,原理如下:
1)圓心估計
- 用Canny演算法進行邊緣檢測,得到邊界二值圖;
- 用Sobel運算元計算原圖的梯度;
- 遍歷邊緣二值圖中的非0點,沿著梯度方向和反方向畫線段(梯度方向為圓弧的法線方向,即半徑方向),線段的起點和長度由引數允許的半徑區間決定。將線段經過的點在累加器中記數;
- 對累計器中的點從大到小排序,記數越大越有可能成為圓心。
2)半徑估計
- 計算所有邊界圖中的非0點離圓心的距離,並從小到大排序;
- 從小半徑r開始,距離相差在一個小量範圍內的點,都認為是同一個圓,記數屬於該半徑r的非0點數,記為n
- 嘗試放大半徑,同樣記數改半徑的點數;
- 判斷兩個半徑孰優孰劣的依據——點的線密度(點數n/半徑r),密度越高,半徑的可信度越大
- 重複以上步驟,直至半徑超過引數允許的範圍,從而得到最優半徑。
該方法的不足:
-
在霍夫梯度法中,我們使用Sobel導數來計算區域性梯度,那麼隨之而來的假設是,其可以視作等同於一條區域性切線,並這個不是一個數值穩定的做法。在大多數情況下,這樣做會得到正確的結果,但或許會在輸出中產生一些噪聲;
-
在邊緣影像中的整個非0畫素集被看做每個中心的候選部分。因此,如果把累加器的閾值設定偏低,演算法將要消耗比較長的時間。第三,因為每一箇中心只選擇一個圓,如果有同心圓,就只能選擇其中的一個;
-
因為中心是按照其關聯的累加器值的升序排列的,並且如果新的中心過於接近之前已經接受的中心的話,就不會被保留下來。且當有許多同心圓或者是近似的同心圓時,霍夫梯度法的傾向是保留最大的一個圓。可以說這是一種比較極端的做法,因為在這裡預設Sobel導數會產生噪聲,若是對於無窮解析度的平滑影像而言的話,這才是必須的。
二、OpenCV中函式介面介紹
void HoughCircles(InputArray image,OutputArray circles, int method, double dp, double minDist, double param1=100,double param2=100, int minRadius=0, int maxRadius=0 )
/*
* 第一個引數,InputArray型別的image,輸入影像,即源影像,需為8位的灰度單通道影像。
* 第二個引數,InputArray型別的circles,經過呼叫HoughCircles函式後此引數儲存了檢測到的圓的輸出向量,每個向量由包含了3個元素的浮點向量(x, y, radius)表示。
* 第三個引數,int型別的method,即使用的檢測方法,目前OpenCV中就霍夫梯度法一種可以使用,它的識別符號為CV_HOUGH_GRADIENT,在此引數處填這個識別符號即可。
* 第四個引數,double型別的dp,用來檢測圓心的累加器影像的解析度於輸入影像之比的倒數,且此引數允許建立一個比輸入影像解析度低的累加器。上述文字不好理解的話,來看例子吧。例如,如果dp= 1時,累加器和輸入影像具有相同的解析度。如果dp=2,累加器便有輸入影像一半那麼大的寬度和高度。
* 第五個引數,double型別的minDist,為霍夫變換檢測到的圓的圓心之間的最小距離,即讓我們的演算法能明顯區分的兩個不同圓之間的最小距離。這個引數如果太小的話,多個相鄰的圓可能被錯誤地檢測成了一個重合的圓。反之,這個引數設定太大的話,某些圓就不能被檢測出來了。
* 第六個引數,double型別的param1,有預設值100。它是第三個引數method設定的檢測方法的對應的引數。對當前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示傳遞給canny邊緣檢測運算元的高閾值,而低閾值為高閾值的一半。
* 第七個引數,double型別的param2,也有預設值100。它是第三個引數method設定的檢測方法的對應的引數。對當前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在檢測階段圓心的累加器閾值。它越小的話,就可以檢測到更多根本不存在的圓,而它越大的話,能透過檢測的圓就更加接近完美的圓形了。
* 第八個引數,int型別的minRadius,有預設值0,表示圓半徑的最小值。
* 第九個引數,int型別的maxRadius,也有預設值0,表示圓半徑的最大值。
*/
三、OpenCV中霍夫梯度檢測圓實施步驟
HoughCircles函式可以利用霍夫變換演算法檢測出灰度圖中的圓。它和之前的HoughLines和HoughLinesP比較明顯的一個區別是它不需要源圖是二值的,而HoughLines和HoughLinesP都需要源圖為二值影像,具體步驟如下:
- 彩色影像->灰度圖
- 去噪(高斯核)
- Hough圓檢測