霍夫检测圆:霍夫梯度法

承接上篇博文,在基本搞懂霍夫检测直线是怎么进化到检测圆后,开始(痴心妄想)自己写代码了!虽说最后的效果不是很好,但是重要的是在码代码过程中发现和解决的一些问题(不一定有共性,但兄弟萌可以避免下这些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 or abs(k[i])>50:
        index.append(i)
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:
        c.append(i)
#进行统计,生成二维列表
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值小于一的边缘点进行了处理,而且在算法中我直接认定投票值最多的像素点为圆心,没有进行下一步处理,在获取半径时候也只是简单取了众数,总而言之还有很多纰漏没解决啦~仅作参考哈,多有不足望大家指出。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值