美文网首页
霍夫变换

霍夫变换

作者: 原上的小木屋 | 来源:发表于2020-06-01 22:27 被阅读0次

基本原理

  • 霍夫变换,是将座标由直角座标系变换到极座标系,然后再根据数学表达式检测某些形状(如直线和圆)的方法。当直线上的点变换到极座标中的时候,会交于一定的r、t的点。这个点即为要检测的直线的参数。通过对这个参数进行逆变换,我们就可以求出直线方程。

基本步骤

  1. 我们用边缘图像来对边缘像素进行霍夫变换。
    canny边缘检测步骤
  • 进行高斯滤波
  • 两个方向上进行sobel滤波
  • 将两个方向上sobel滤波之后的两个矩阵变换为一个梯度幅度矩阵和一个梯度方向矩阵
  • 利用梯度幅度矩阵和梯度方向矩阵进行非极大值抑制
  • 对上一步进行非极大值抑制之后的梯度幅度矩阵进行阈值滞后,这便是canny边缘检测的完整步骤
  1. 在霍夫变换后获取值的直方图并选择最大点。
  2. 对极大点的r和t的值进行霍夫逆变换以获得检测到的直线的参数。

详细步骤

  • 求出图像的对角线长rmax;
  • 在边缘点(x,y)处,t取遍[0,179],根据下式执行霍夫变换:rho=xcos(t)+ysin(t),做一个180×rmax大小的表,将每次按上式计算得到的表格(t,r)处的值加1。换句话说,这就是在进行投票。票数会在一定的地方集中。
  • 在该表中,如果遍历到的像素的投票数大于其8近邻的像素值,则它不变。如果遍历到的像素的投票数小于其8近邻的像素值,则设置为0。
  • 极大值点(r,t)通过下式进行逆变换:y=−xcos(t)/sin(t)+rx/sin(t)=−ysin(t)/cos(t)+r/cos(t)
  • 对于每个局部最大点,使y=0−H−1,x=0−W−1,然后执行上式中的逆变换,并在输入图像中绘制检测到的直线。请将线的颜色设置为红色(R,G,B)=(255,0,0)
def Hough_Line_step1(edge):
    ## Voting
    def voting(edge):
        H, W = edge.shape
        drho = 1
        dtheta = 1
        # get rho max length
        rho_max = np.ceil(np.sqrt(H ** 2 + W ** 2)).astype(np.int)#计算大于等于该值的最小整数,这里需要解释一下,rho_max即为sqrt(a**2+b**2)
        #是因为后面的公式rho=asint+bcost,可以用高中知识轻易证明,rho的绝对值要小于rho_max
        # hough table#计算霍夫表格
        hough = np.zeros((rho_max * 2, 180), dtype=np.int)#生成霍夫表格的尺#寸,因此可以看到这里hough的高度为二倍的rho_max,也就很容易理解后面的hough[rho+rho_max,theta]+=1了
        # get index of edge
        ind = np.where(edge == 255)#取得边缘像素点的索引
        ## hough transformation
        for y, x in zip(ind[0], ind[1]):
            for theta in range(0, 180, dtheta):
                # get polar coordinat4s
                t = np.pi / 180 * theta#依次计算角度的弧度值
                rho = int(x * np.cos(t) + y * np.sin(t))#依次计算不同弧度值对应的不同的rho值
                # vote
                hough[rho + rho_max, theta] += 1#进行投票,票数在一定地方集中
        out = hough.astype(np.uint8)
        return out
    # voting
    out = voting(edge)
    return out

第一步完成后,需要对投票结果进行非极大值抑制,和canny边缘检测最后一步的阈值滞后中的落入高阈值与低阈值区间的处理方法极为相似,即抽取八邻域与中间点做比较,如果有比中间像素值大的情况,中间像素值置为0

    # non maximum suppression
    def non_maximum_suppression(hough):
        rho_max, _ = hough.shape #得到hough图像的尺寸
        ## non maximum suppression
        for y in range(rho_max):
            for x in range(180):
                # get 8 nearest neighbor
                x1 = max(x - 1, 0)#非常巧妙的处理,兼顾了边缘和中央区域
                x2 = min(x + 2, 180)#非常巧妙的处理,兼顾了边缘和中央区域
                y1 = max(y - 1, 0)#非常巧妙的处理,兼顾了边缘和中央区域
                y2 = min(y + 2, rho_max - 1)#非常巧妙的处理,兼顾了边缘和中央区域
                if np.max(hough[y1:y2, x1:x2]) == hough[y, x] and hough[y, x] != 0:
                    pass
                # hough[y,x] = 255
                else:
                    hough[y, x] = 0
        return hough

最后一步,也就是根据特征点把线画在原图上的一步,叫rough反变换

    def inverse_hough(hough, img):#将经历第一步第二步过程的rough图像和原图像作为参数输入进来
        H, W, _ = img.shape#原图像尺寸
        rho_max, _ = hough.shape#hough图像尺寸
        out = img.copy()#复制一个
        # get x, y index of hough table
        ind_x = np.argsort(hough.ravel())[::-1][:20]#按行重组倒序取前20个值得索引坐标
        ind_y = ind_x.copy()
        thetas = ind_x % 180#取得角度
        rhos = ind_y // 180 - rho_max / 2#取得rhos值,这个不必解释,很好理解,和前面的第一个函数结合起来看非常明显
        # each theta and rho#坐标系转换
        for theta, rho in zip(thetas, rhos):
            # theta[radian] -> angle[degree]
            t = np.pi / 180. * theta#算出t
            # hough -> (x,y)
            for x in range(W):
                if np.sin(t) != 0:
                    y = - (np.cos(t) / np.sin(t)) * x + (rho) / np.sin(t)#依据x逐次算出y的坐标
                    y = int(y)
                    if y >= H or y < 0:
                        continue
                    out[y, x] = [0, 0, 255]#在图中表示出来
            for y in range(H):#依据y逐步算出x的坐标
                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
                    out[y, x] = [0, 0, 255]#将其表示出来
        out = out.astype(np.uint8)
        return out

下面我们来总结一下霍夫检测直线的具体步骤

  1. 进行高斯滤波
  2. 两个方向上进行sobel滤波
  3. 将两个方向上sobel滤波之后的两个矩阵变换为一个梯度幅度矩阵和一个梯度方向矩阵
  4. 利用梯度幅度矩阵和梯度方向矩阵进行非极大值抑制
  5. 对上一步进行非极大值抑制之后的梯度幅度矩阵进行阈值滞后
    至此,canny边缘检测任务完成,hough变换是建立在canny边缘检测的基础上的
  6. 建立hough矩阵,具体构建方法见上述说明。细节:hough角度0-180rho_max2sqrt(a**2+b**2),依次遍历进行投票
  7. 对hough矩阵进行非极大值抑制(8像素领域)
  8. 排序输出,hough前n个值取其rho及角度thetas,由这两个值反向推的x,y坐标
    至此,hough检测的任务便完成了

相关文章

  • 【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,

    【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑文辑: https://blog.c...

  • OpenCV-Python学习(十六):霍夫变换

    目录: 1.什么是霍夫变换? 2.OpenCV中的霍夫线变换-->直线检测 3.OpenCV中的霍夫圆变换-->圆...

  • 霍夫变换之直线检测

    霍夫变换 查看图像 结果: 边缘检测 结果: 霍夫变换检测直线 结果:

  • 霍夫变换

    霍夫变换——直线   Hough Line Transform用来做直线检测,前提是已经做了边缘检测。  霍夫变换...

  • 霍夫变换

    随机霍夫变换介绍[https://blog.csdn.net/zkl99999/article/details/4...

  • 霍夫变换

    一、霍夫直线检测 霍夫变换(Hough Transfrom),是1972年提出的,最开始就是用来在图像中检测直线,...

  • 霍夫变换

    基本原理 霍夫变换,是将座标由直角座标系变换到极座标系,然后再根据数学表达式检测某些形状(如直线和圆)的方法。当直...

  • 霍夫变换---OpenCV-Python开发指南(35)

    什么是霍夫变换 霍夫变换是一种在图像中寻找直线,圆形以及其他简单形状的方法。霍夫变换采用类似于投票的方式来获取当前...

  • 霍夫变换概述和标准霍夫变换

    在图像处理和计算机视觉领域中,如何冲当前的退选哪个中提取出所需要的特征信息是图像识别的关键所在。在许多应用场合中需...

  • Python+OpenCV教程17:霍夫变换

    主站:http://ex2tron.wang原文:Python+OpenCV教程17:霍夫变换 学习使用霍夫变换识...

网友评论

      本文标题:霍夫变换

      本文链接:https://www.haomeiwen.com/subject/xoijzhtx.html