关于霍夫变换检测直线和圆的一些思考

近期博主在手码一些经典算法,在理解霍夫变换对直线和圆检测的过程中,解决了一些顽固性疑虑,本文主要将两种方法做了类比,把圆检测和直线检测对应起来。所以可以作为萌新们看过原理后的进一步理解,首先需要兄弟萌提前熟悉下原理:
霍夫变换直线检测(Line Detection)原理及示例
(不要偷懒哦,看了大神的讲解才能看懂本文(^U^)ノ~YO)

霍夫变换检测直线

简述下霍夫变换做的事:把笛卡尔坐标中的直线对应为参数空间的一个点。(没错,就是这么简单),在霍夫空间里一条直线可以用(ρ,θ)来表示,即经过笛卡尔坐标某一个固定点所有直线对应到霍夫空间里就是无数个点,我个人把它称为散点图。发现没有,这个散点图的前提是锁定某一个像素点,所以这无数个点只描述了经过一个点的直线!为了计算方便,一般会把θ分为180份(这样就是有限个啦,比较符合计算机工作原理),并假设其覆盖了全部直线。

ρ=xcos⁡θ+ysin⁡θ

对照公式可以看到,每带入一个θ就会得到一个ρ,所以每遍历经过过一个像素点所有直线就会得到180个ρ,问题来了,这些ρ一般不为整数,如果硬性规定这些拖着尾巴的ρ相等,条件会不会太严苛了?没错,机智的码农们决定砍掉这些小数点后的尾巴,列举出所有可能的ρ值,组成霍夫变换中的重要角色——投票器:

之后就是找每一个边缘点勒令他(直线)化为180个分身(点),并对应投票器进行投票。如果有n个边缘点,则会有n副散点图,也就是n个二维投票器,可以想象一下把这些散点图堆积到一起,在垂直于霍夫空间的方向上累加各投票窗口的点数,是不是很好理解为什么投票总数为n*180啦?Finally,得票数多的(ρ,θ)就是要找的直线啦~

霍夫变换检测圆

类似的,我们知道圆的方程式表示为:

在这里插入图片描述
要确定一个圆则需要知道其圆心坐标和半径,这就是圆检测的参数空间了。三个参数则把霍夫空间升级为三维,兄弟萌自动脑补一下。
可以确定的是圆心的范围不会超过整张图片,所以在锁定一个边缘点的条件下,可以遍历整张图象的像素点,以所有像素点为圆心,计算得到不一样的半径,类似的,也应该找到一个可能的最大半径,以一为步长穷举出这些半径,按照计算值对这个三维投票器进行投票。
前面所述只是一个边缘点的投票器,要完成圆的检测需要对所有边缘点都进行这样的三维投票,再将这些三维投票器整合到一起,被投次数多的被认定为圆。

当然上述圆检测的解读只是我为了横向对比直线和圆的霍夫变换及其检测原理所分析的,这样能更帮助理解,但事实上这种方法太耗时间啦~主流的大家都用的霍夫梯度法进行降维分步计算的,我再贴个链接:(点进去康!)

OpenCV霍夫梯度找圆算法

霍夫变换检测直线代码

import cv2
import numpy as np


img = cv2.imread("line.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img1 = cv2.GaussianBlur(gray,(3,3),0)
# cv2.imshow('image',img)
canny = cv2.Canny(img1, 30, 50)
arr = np.array(canny)
location = np.argwhere(arr == 255)
H,W =canny.shape
l_max = np.ceil(np.sqrt(H**2+W**2)).astype(np.int)
hough = np.zeros((l_max, 180), dtype=np.int)
for y, x in location:
    for theta in range(180):
        t = np.pi/180*theta
        l = int(x * np.cos(t) + y * np.sin(t))
        hough[l, theta] += 1
out = hough.astype(np.uint8)
# print(out)
m = img.copy()
ind_x = np.argsort(hough.ravel())[::-1][:5]
ind_y = ind_x.copy()
thetas = ind_x % 180
rhos = ind_y // 180
for theta,rho in zip(thetas,rhos):
    t = np.pi/180*theta
    for x in range(W):
        if np.sin(t) != 0:
            y = - (np.cos(t) / np.sin(t)) * x + l / np.sin(t)
            y = int(y)
            if y >= H or y < 0:
                continue
        m[y, x] = [0, 255, 255]
    for y in range(H):
        if np.cos(t) != 0:
            x = - (np.sin(t) / np.cos(t)) * y + (rho) / np.cos(t)
            x = int(x)
            if x >= W or x < 0:
                continue
        m[y, x] = [0,0,255]
m = m.astype(np.uint8)
cv2.imshow('tu',m)
cv2.waitKey()

代码主要参考这篇博文:

霍夫变换检测图像直线算法python实现

暂时完结,撒花★,°:.☆( ̄▽ ̄)/$:.°★

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值