承接上篇博文,在基本搞懂霍夫檢測直線是怎麼進化到檢測圓後,開始(痴心妄想)自己寫**了!雖說最後的效果不是很好,但是重要的是在碼**過程中發現和解決的一些問題(不一定有共性,但兄弟萌可以避免下這些bug)。
上篇博文已經闡述了我們是如何從三維計數**轉到霍夫梯度法的,該演算法主要分為兩步,先找圓心疑似點,再對疑似點進行半徑確定:
假設已經得到影象的邊緣資訊(包含角度和梯度值)
1.利用邊緣點的梯度資訊,沿著梯度方向畫線,將將線段經過的所有累加器中的點(a,b)的hough(h,w)+=1。
此步原理是:圓上的點沿著梯度方向畫線,這些線會交於圓心。
2.統計排序霍夫累加器中的投票時,得票是越高,說明更多得邊緣梯度線經過該點,是圓心的可能性就更大。
3.針對某個圓心計算所有邊緣點到其的距離,認為頻數較大的距離為可能半徑值。(個人的簡化做法)
1.如何沿著邊緣點的梯度方向畫線?
博主採用的斜截式來表示梯度線(即為邊緣的法線),首先我們獲得的梯度方向角為:
theta = np.arctan2(i2,
(i1+
0.0000000000001))
*180
/np.pi
帶著這個賊小的數是為了不出現分母為零的情況!這裡排除了k=inf的情況,但是還是會出現k值比較大的情況,為了畫線方便做了這樣一步操作:
#篩選k值(即把小於0.05或者超過50的k值剔除)
index =
for i in
range
(len
(k)):if
abs(k[i]
)<
0.05
orabs
(k[i]
)>50:
new_k = np.delete(k,index)
new_location = np.delete(location,index,axis=
0)
在影象中畫直線時其經過的不是質點而是畫素點(有物理長寬),所以本文先求取了各個邊緣點梯度線的k和b值,因此經過邊緣點(x0,y0)的直線可表示為:y0=k*x0+b,以乙個畫素為單位不斷增加x值,利用直線方程求取對應的y值,以此來求得直線經過的所有畫素點。
2.對k值進行分類處理
第一問已經剔除了難以利用的k值及其對應的邊緣點座標,接下來要對k值進行分類。由第一問已經知道博文求取梯度線經過的畫素點的方法是步進法(自己胡謅的名字),會出現乙個新的問題,是在x軸上步進好還是在y軸上步進好呢?這就是為什麼要對k值進行乙個分類。
當k的絕對值小於1時,意味著每增加乙個畫素值,y的增加(或減少)不超過乙個畫素值,是可以遍歷該直線經過的所有畫素的。但如果是增加y值,那麼x會增加幾個畫素值,這樣會跳過好幾畫素塊,故博主將k小於1的分出來,對於分出來的邊緣點,進行x軸上的遞進。(本處偷了懶~其實按照原理也可以對k=0或k=inf的邊緣點進行操作的)
3.在尋找一些需要注意的問題:
博主初步畫梯度直線時,針對的是canny識別出來的邊緣進行操作的,但是識別的圓心不准。改為對梯度幅值不為零的所有畫素點畫梯度方向直線後發現效果好了很多,即從上面的**改為下面的:
location = np.argwhere(edge==
255)
location = np.argwhere(g)
對比:
4.半徑求取的辦法:
博主用了最簡單的思路,求取所有的邊緣點到可能圓心的距離,認為半徑值是距離的眾數字。
d = np.sqrt(
(location[:,
0]-h[0])
**2+(location[:,
1]-w[0])
**2)d = d.astype(
int)
c =[
]for i in d:
if i not
in c:
#進行統計,生成二維列表
a =for i in d:
if i in a:
a[i]
= a[i]+1
else
: a[i]=1
# 使用sorted對字典進行排序
b =sorted
(a.items(
),key=
lambda item:item[1]
,reverse=
true
)r = b[0][0]
最後效果圖:
可以看到其實最後的結果不太理想,反思問題可能是中間只對k值小於一的邊緣點進行了處理,而且在演算法中我直接認定投票值最多的畫素點為圓心,沒有進行下一步處理,在獲取半徑時候也只是簡單取了眾數,總而言之還有很多紕漏沒解決啦~僅作參考哈,多有不足望大家指出。
霍夫梯度法找圓
opencv內部提供了乙個基於hough變換理論的找圓演算法,houghcircle與一般的擬合圓演算法比起來,各有優勢 優勢 houghcircle對雜訊點不怎麼敏感,並且可以在同乙個圖中找出多個圓 反觀擬合圓演算法,單純的擬合結果容易受雜訊點的影響,且不支援乙個輸入中找多個圓 opencv內的h...
霍夫梯度法測圓
opencv內部提供了乙個基於hough變換理論的找圓演算法,houghcircle與一般的擬合圓演算法比起來,各有優勢 優勢 houghcircle對雜訊點不怎麼敏感,並且可以在同乙個圖中找出多個圓 反觀擬合圓演算法,單純的擬合結果容易受雜訊點的影響,且不支援乙個輸入中找多個圓 opencv內的h...
基於梯度的霍夫圓檢測
基於梯度的霍夫圓檢測原理 略 直接看 一 首先讀取一張,處理成灰度圖。並對其做濾波降噪,因為霍夫圓檢測是對雜訊敏感的。這裡用到的降噪方法一般是用保留邊緣的濾波。我用的是這張圖 二 然後就可以用霍夫圓檢測啦。rows,cols gray.shape circles cv.houghcircles gr...