霍夫變換檢測直線的原理是利用累加器找到最大的 ( ρ , θ ) (ρ,θ) (ρ,θ)數對,如文章所述,圓形的數學運算式為 ( x ? x c e n t e r ) 2 + ( y ? y c e n t e r ) 2 = r 2 (x-x_{center})^2+(y-y_{center})^2=r^2 (x?xcenter?)2+(y?ycenter?)2=r2,其中 ( x c e n t e r , y c e n t e r ) (x_{center},y_{center}) (xcenter?,ycenter?)為圓心坐標, r r r為圓的直徑,因此可知一個圓需要 x c e n t e r , y c e n t e r , r x_{center},y_{center},r xcenter?,ycenter?,r三個引數確定,如果采用霍夫直線相同的原理,則需要圍繞被探測點對全域點進行搜索,進而獲取可能的圓心坐標,然后再通過圓心坐標計算該點相對應的半徑,構成 ( x c e n t e r , y c e n t e r , r ) (x_{center},y_{center},r) (xcenter?,ycenter?,r)數對,再利用累加方法對下一些像素點進行相同處操作,最后看哪個數對位置中的累加出的數值最大,即代表過這一簇點的圓,但是這種操作的計算量過大,效率比較低,于是H.K.YUEN等大神提出了一種優化演算法,利用邊緣點的梯度法向為路徑進行圓心點搜索,可以大大縮小圓心點搜索范圍,提高效率,
在opencv-python中,我們使用函式cv2.HoughCircles函式來解決圓識別問題,函式說明如下圖所示:
每個引數的含義如下圖所示:
- image:8位待處理灰度影像;
- circles:輸出被檢測到的圓,以三元素浮點型向量表示 ( x , y , r a d i u s ) (x,y,radius) (x,y,radius);
- method:探測方法,當前的實作是用的CV_HOUGH_GRADIENT方法;
- dp:累加器解析度與影像解析度的反比,例如,如果dp=1,累加器的解析度與輸入影像相同,如果dp=2,則累加器的寬度和高度為原來的一半;
- minDist:檢測到的圓中心之間的最小距離,如果引數太小,除了一個真實的圓外,還可能錯誤地檢測到多個相鄰圓,如果太大可能會錯過一些圓;
- param1:第一個特定引數,對于CV_HOUGH_GRADIENT方法,它是傳遞給Canny()邊緣檢測器的兩個閾值中較高的閾值(較低的閾值小兩倍);
- param2:第二個特定引數,對于CV_HOUGH_GRADIENT方法,它是檢測階段圓心的累加器閾值,它越小,可能檢測到的假圓越多(因為滿足累加器上限的條件變多了),與累加器最大數值結果代表的圓將被首先回傳,
- minRadius:最小圓半徑;
- maxRadius:最大圓半徑,
基于上文所述,霍夫圓檢測的效果進行測驗,待處理原圖如下圖所示:

處理代碼如下所示:
img = cv2.imread('singlecircle.jpg',0)
img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,minDist=20,param1=50,param2=30,minRadius=0,maxRadius=0)
print('circles1:', circles)
circles = np.uint16(np.around(circles))
print('circles2:', circles)
for i in circles[0,:]:
# draw the outer circle
cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
# draw the center of the circle
cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
運行結果如下:
此時我們發現程式顯示了很多圓形,并非是我們想要的結果,此時我們調整霍夫變換函式的引數,調整“minDist=20”為“minDist=100”,之后程式的運行效果為:

肉眼可見效果明顯好了很多,從函式功能定義來看,輸出circle變數應該包含形如
(
x
c
e
n
t
e
r
,
y
c
e
n
t
e
r
,
r
)
(x_{center},y_{center},r)
(xcenter?,ycenter?,r)形式的數對,我們將circle變數內容列印出來,如下圖所示:
此處,我們可以思考一下,為什么圓心坐標最后都是.5的形式呢?當然,我們也可以通過改變其他引數的形式去達到只識別一個圓的目的,比如我們將"param2=30"修改為"param2=100"效果如下:

對于多個圓,我們也可以通過cv2.HoughCircles()函式進行識別,被處理原圖如下圖所示:

程式運行結束后效果如下圖所示:
可見效果比較明顯,但還沒有達到比較規整的效果,通過調整函式中的引數可以實作我們想要的識別效果,在引數中,dp引數值得深入分析,其與累加器解析度成反比,如果dp=1,累加器屬正常狀態,如果dp=2,則按照2倍執行累加,所以dp值越大,累加器累加速度越快,因此在上限閾值以上的被檢測圓數量也就越多,為了測驗,我們將dp調整為2,其他引數保持不變,觀察函式的執行效果:
可見檢測出來的圓多了好多,
歡迎大家在評論區留言評論,感謝大家的關注!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/327855.html
標籤:AI
