图像处理之Hough变换检测直线

这篇具有很好参考价值的文章主要介绍了图像处理之Hough变换检测直线。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、 前言

霍夫变换是一种特征检测(feature extraction),被广泛应用在图像分析(image analysis)、计算机视觉(computer vision)以及数位影像处理(digital image processing)。由RichardDuda和PeterHart在公元1972年发明,并称之为广义霍夫变换(generalizedHoughtransform),广义霍夫变换和更早前1962年的PaulHough的专利有关。经典的霍夫变换是侦测图片中的直线,之后,霍夫变换不仅能识别直线,也能够识别任何形状,常见的有圆形、椭圆形。1981年,因为DanaH.Ballard的一篇期刊论文"Generalizing the Hough transform to detect arbitrary shapes",让霍夫变换开始流行于计算机视觉界。霍夫变换是用来辨别找出物件中的特征,例如:线条。他的算法流程大致如下,给定一个物件、要辨别的形状的种类,算法会在参数空间(parameter space)中执行投票来决定物体的形状,而这是由累加空间(accumulator space)里的局部最大值(local maximum)来决定。

二、Hough 变换

一条直线可由两个点 A = ( x 1 , y 1 ) A=(x_1,y_1) A=(x1,y1) B = ( x 2 , y 2 ) B=(x_2,y_2) B=(x2,y2)确定(笛卡尔坐标)
图像处理之Hough变换检测直线,图像处理,图像处理,人工智能

另一方面, y = k x + b y=kx+b y=kx+b也可以写成关于 ( k , q ) (k,q) k,q的函数表达式(霍夫空间):
{ q = − k x 1 + y 1 q = − k x 2 + y 2 \left\{ \begin{aligned} q=-kx_1+y_1 \\ q=-kx_2+y_2 \\ \end{aligned} \right. {q=kx1+y1q=kx2+y2
空间变换过程如下图:
变换后的空间成为霍夫空间。即:笛卡尔坐标系中一条直线,对应霍夫空间的一个点。
图像处理之Hough变换检测直线,图像处理,图像处理,人工智能
反过来同样成立(霍夫空间的一条直线,对应笛卡尔坐标系的一个点):
图像处理之Hough变换检测直线,图像处理,图像处理,人工智能
笛卡尔坐标系中两个点对应霍夫空间两条线:
图像处理之Hough变换检测直线,图像处理,图像处理,人工智能
如果笛卡尔坐标系三个点共线,对应的霍夫空间的三条线相交于一点
图像处理之Hough变换检测直线,图像处理,图像处理,人工智能
霍夫变换的后处理的基本方式:选择由尽可能多直线汇成的点。
但是,按照直角坐标系表示的话会出现下图的情况:当图像空间中点共的线垂直于x轴时,斜率无限大,在霍夫空间无法找到交点。因而,人们最终引入了极坐标的表示法。
图像处理之Hough变换检测直线,图像处理,图像处理,人工智能
极坐标下的霍夫直线检测原理与直角坐标系下完全一致,唯一需要重新推导的是与霍夫空间的极坐标参数函数:
y = ( − c o s θ s i n θ ) x + r s i n θ y=\left(-\frac{cos\theta}{sin\theta}\right)x+\frac{r}{sin\theta} y=(sinθcosθ)x+sinθr
化简便可得到:
r = x c o s θ + y s i n θ r=xcos\theta+ysin\theta r=xcosθ+ysinθ
如果对于一个给定点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),意味着每一对 ( r , θ ) (r,\theta) (r,θ)代表一条通过点 ( x θ , y θ ) (x_\theta,y_\theta) (xθ,yθ)的直线。我们在极坐标对极径极角平面绘出所有通过它的直线, 将得到一条正弦曲线. 例如, 对于给定点 ( x 0 = 8 和 y 0 = 6 ) (x_0= 8 和y_0= 6) (x0=8y0=6) 我们可以绘出下图 (在平面):
图像处理之Hough变换检测直线,图像处理,图像处理,人工智能
极坐标与笛卡尔坐标的转换公式,从极坐标转换 ( r , θ ) (r,θ) (r,θ)在笛卡尔坐标系 ( x , y ) (x,y) (x,y):
{ x = r c o s θ y = r s i n θ \left\{ \begin{aligned} x=rcos\theta \\ y=rsin\theta \\ \end{aligned} \right. {x=rcosθy=rsinθ
从笛卡儿坐标转换 ( x , y ) (x,y) (x,y) 到极坐标 ( r , θ ) (r,θ) (r,θ):
r = x 2 + y 2 θ = a r c t a n ( y / x ) r=\sqrt{x^2+y^2} \\ \theta=arctan(y/x) r=x2+y2 θ=arctan(y/x)
在极坐标系下,其实是一样的:极坐标的点→霍夫空间的直线,只不过霍夫空间不再是 [ k , q ] [k,q] [k,q]的参数,而是 ( r , θ ) (r,\theta) (r,θ)

三、直线检测

通过上面的介绍可知,画出 x − y x-y xy坐标空间中的点在参数空间中对应的曲线,然后计算参数空间中曲线的交点,就能求得待求的参数。但还有一个问题,当参数空间中的曲线存在多个交点时,如何挑选出最有可能的解呢?
具体计算时,可将参数空间划分为所谓的累加单元 A ( θ , ρ ) A(\theta,\rho) A(θ,ρ)。如图下图所示,对于 x − y x-y xy平面的每一个非背景点 ( x k , y k ) (x_k,y_k) (xk,yk),令 θ \theta θ等于每个可取的细分值,根据 θ = − x k θ + y k \theta=-x_k\theta+y_k θ=xkθ+yk计算出对应的 ρ \rho ρ值,每计算出一组 A ( θ , ρ ) A(\theta,\rho) A(θ,ρ),则令 A ( θ , ρ ) = A ( θ , ρ ) + 1 A(\theta,\rho)=A(\theta,\rho)+1 A(θ,ρ)=A(θ,ρ)+1。计算所有结果后,找到 A ( θ , ρ ) A(\theta,\rho) A(θ,ρ)的峰值对应的 θ \theta θ ρ \rho ρ,即可检测直线。 ( θ m i n , θ m a x ) (\theta_{min},\theta_{max}) (θmin,θmax) ( ρ m i n , ρ m a x ) (\rho_{min},\rho_{max}) (ρmin,ρmax)是期望的参数范围: 0 ο ≤ θ ≤ 18 0 ο 0^\omicron \leq\theta \leq180^\omicron 0οθ180ο − D ≤ θ ≤ D -D \leq\theta \leq D DθD, D D D是图像对角线的长度。 θ \theta θ ρ \rho ρ的细分数量决定了检测结果的精度。
图像处理之Hough变换检测直线,图像处理,图像处理,人工智能

投票过程可以观看下面的GIF,
图像处理之Hough变换检测直线,图像处理,图像处理,人工智能
左边上青色的点代表图像上的像素点,黄色的代表对各个点不同角度搜索。右半边是投票盘,颜色越浅代表票数越多。

四、代码实现

1.hough检测

def lines_detector_hough(img,ThetaDim=None, DistStep=None, threshold=None, halfThetaWindowSize=2,
                         halfDistWindowSize=None):
    '''

    :param img: 经过边缘检测得到的二值图
    :param ThetaDim: hough空间中theta轴的刻度数量(将[0,pi)均分为多少份),反应theta轴的粒度,越大粒度越细
    :param DistStep: hough空间中dist轴的划分粒度,即dist轴的最小单位长度
    :param threshold: 投票表决认定存在直线的起始阈值
    :return: 返回检测出的所有直线的参数(theta,dist)和对应的索引值,
    '''
    row,col= edge.shape
    if ThetaDim == None:
        ThetaDim = 90
    if DistStep == None:
        DistStep = 1
    # 计算距离分段数量
    MaxDist = np.sqrt(row ** 2 + col ** 2)
    DistDim = int(np.ceil(MaxDist / DistStep))

    if halfDistWindowSize == None:
        halfDistWindowSize = int(DistDim /50)

    # 建立投票
    accumulator = np.zeros((ThetaDim, DistDim))  # theta的范围是[0,pi). 在这里将[0,pi)进行了线性映射.类似的,也对Dist轴进行了线性映射
    #
    sinTheta = [np.sin(t * np.pi / ThetaDim) for t in range(ThetaDim)]
    cosTheta = [np.cos(t * np.pi / ThetaDim) for t in range(ThetaDim)]
    #计算距离(rho)
    for i in range(row):
        for j in range(col):
            if not edge[i, j] == 0:
                for k in range(ThetaDim):
                    accumulator[k][int(round((i * cosTheta[k] + j * sinTheta[k]) * DistDim / MaxDist))] += 1
    M = accumulator.max()
#---------------------------------------
    #非极大抑制
    if threshold == None:
        threshold = int(M * 1.369/ 10)
    result = np.array(np.where(accumulator > threshold))  # 阈值化
    #获得对应的索引值
    temp = [[], []]
    for i in range(result.shape[1]):
        eight_neiborhood = accumulator[
                           max(0, result[0, i] - halfThetaWindowSize + 1):min(result[0, i] + halfThetaWindowSize,
                                                                              accumulator.shape[0]),
                           max(0, result[1, i] - halfDistWindowSize + 1):min(result[1, i] + halfDistWindowSize,
                                                                             accumulator.shape[1])]
        if (accumulator[result[0, i], result[1, i]] >= eight_neiborhood).all():
            temp[0].append(result[0, i])
            temp[1].append(result[1, i])
    #记录原图所检测的坐标点(x,y)
    result_temp= np.array(temp)
#-------------------------------------------------------------
    result = result_temp.astype(np.float64)
    result[0] = result[0] * np.pi / ThetaDim
    result[1] = result[1] * MaxDist / DistDim
    return result,result_temp

2.画直线代码

def drawLines(lines, edge, color=(255, 0, 0), err=3):

    '''
    :param lines: 检测后的直线参数
    :param edge: 原图
    :param color: 直线的颜色
    :param err:检测的可接受的误差值
    :return: 无
    '''

    if len(edge.shape) == 2:
        result = np.dstack((edge, edge, edge))
    else:
        result = edge
    Cos = np.cos(lines[0])
    Sin = np.sin(lines[0])

    for i in range(edge.shape[0]):
        for j in range(edge.shape[1]):
            e = np.abs(lines[1] - i * Cos - j * Sin)
            if (e < err).any():
                result[i, j] = color
    plt.imshow(result, cmap='gray')
    plt.axis('off')
    plt.show()

3.画hough空间代码

def data_img(data):

    '''
    :param data: 直线上含有的点(x,y)
    :return: 输出hough空间图像
    '''

    fig = plt.figure()  # 新建画布
    ax = axisartist.Subplot(fig, 111)  # 使用axisartist.Subplot方法创建一个绘图区对象ax
    fig.add_axes(ax)
    ax.axis[:].set_visible(False)  # 隐藏原来的实线矩形
    ax.axis["x"] = ax.new_floating_axis(0, 0, axis_direction="bottom")  # 添加x轴
    ax.axis["y"] = ax.new_floating_axis(1, 0, axis_direction="bottom")  # 添加y轴
    ax.axis["x"].set_axisline_style("->", size=1.0)  # 给x坐标轴加箭头
    ax.axis["y"].set_axisline_style("->", size=1.0)  # 给y坐标轴加箭头
    t = np.arange(-np.pi / 2, np.pi / 2, 0.1)
    ax.annotate(text='x', xy=(2 * math.pi, 0), xytext=(2 * math.pi, 0.1))  # 标注x轴
    ax.annotate(text='y', xy=(0, 1.0), xytext=(-0.5, 1.0))  # 标注y轴
    for i in range(data.shape[1]):
        rho = data[0][i] * np.cos(t) + data[1][i] * np.sin(t)
        plt.plot(t, rho)
    plt.show()

4.检测结果

图像处理之Hough变换检测直线,图像处理,图像处理,人工智能
点击这里可以下载检测图片
全部代码可见本人GitHub仓库,如果代码有用,please click star
hough检测之前需要canny算子检测基础的边缘,点击这里可以查看有关canny算法相关内容

如果本文对你有帮助,关注加点赞!!!!!文章来源地址https://www.toymoban.com/news/detail-605866.html

到了这里,关于图像处理之Hough变换检测直线的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【课程介绍】OpenCV 基础入门教程:图像读取、显示、保存,图像处理和增强(如滤波、边缘检测、图像变换),特征提取和匹配,目标检测和跟踪

    [ 专栏推荐 ] 😃 《视觉探索: OpenCV 基础入门教程》 😄 ❤️【简介】: Opencv 入门课程适合初学者,旨在介绍 Opencv 库的基础知识和核心功能。课程包括图像读取、显示、保存,图像处理和增强(如滤波、边缘检测、图像变换),特征提取和匹配,目标检测和跟踪等内容。学

    2024年02月16日
    浏览(45)
  • 《数字图像处理》dlib人脸检测获取关键点,delaunay三角划分,实现人脸的几何变换warpping,接着实现两幅人脸图像之间的渐变合成morphing

           这学期在上《数字图像处理》这门课程,老师布置了几个大作业,自己和同学一起讨论完成后,感觉还挺有意思的,就想着把这个作业整理一下 :   目录 1.实验任务和要求 2.实验原理 3.实验代码 3.1利用人脸特征点检测工具dlib获取人脸关键点 目录 1.实验任务和要求

    2024年02月03日
    浏览(33)
  • Matlab实现Hough直线检测

    基于Matlab实现图像的直线识别 代码如下:(有些参数需要自己根据图像情况调整)

    2024年02月04日
    浏览(29)
  • 《数字图像处理-OpenCV/Python》连载(22)绘制直线与线段

    本书京东优惠购书链接:https://item.jd.com/14098452.html 本书CSDN独家连载专栏:https://blog.csdn.net/youcans/category_12418787.html 本章介绍OpenCV的绘图功能和简单的鼠标交互处理方法。与Excel或Matplotlib中的可视化数据图不同,OpenCV中的绘图功能主要用于在图像的指定位置绘制几何图形。 本

    2024年02月02日
    浏览(75)
  • 数字信号与图像处理实验三:图像处理基础与图像变换

    ​ 通过本实验加深对数字图像的理解,熟悉MATLAB中的有关函数;应用DCT对图像进行变换;熟悉图像常见的统计指标,实现图像几何变换的基本方法。 ​ 选择两幅图像,读入图像并显示,同时使用Matlab计算图像的大小,灰度平均值、协方差矩阵、灰度标准差和相关系数。 DC

    2024年02月04日
    浏览(47)
  • 数字图像处理实验四--图像变换

    (图像变换) 实验内容: 对图像lena、cameraman和face进行傅里叶变换,观察图像能量在频谱图中的分布情况。 利用Matlab生成下列图像,并对其进行旋转30度、90度和120度,然后对他们分别进行傅里叶变换。 对图像lena、cameraman和face用DCT变换进行图像压缩,舍掉的变换系数分别小

    2024年04月14日
    浏览(52)
  • OpenCV(图像处理)-基于Python-图像的基本变换-平移-翻转-仿射变换-透视变换

    为了方便开发人员的操作,OpenCV还提供了一些图像变换的API,本篇文章讲简单介绍各种API的使用,并附上一些样例。 图像缩放函数,用于把图像按指定的尺寸放大或缩小。 dst = cv2.resize(src, dsize, fx, fy, interpolation) dst = 生成的目的图像 src:需要变换的原图像 disize:(x, y)需要

    2024年02月08日
    浏览(42)
  • 图像处理之图像的离散余弦变换

    一、前言 离散余弦变换(Discrete Cosine Transform, DCT)是 以一组不同频率和幅值的余弦函数和来近似一幅图像,实际上是傅立叶变换的实数部分 。离散余弦变换有一个重要的性质,即 对于一幅图像,其大部分可视化信息都集中在少数的变换系数上 。因此,离散余弦变换经常用于图

    2024年02月05日
    浏览(33)
  • python图像处理实战(三)—图像几何变换

    🚀写在前面🚀 🖊个人主页:https://blog.csdn.net/m0_52051577?type=blog  🎁欢迎各位大佬支持点赞收藏,三连必回!! 🔈本人新开系列专栏—python图像处理 ❀愿每一个骤雨初晴之时,所有的蜻蜓振翅和雨后惊雷,都归你。 前言       图像几何变换就是在不改变图像像素值的前提

    2024年02月11日
    浏览(46)
  • python图像处理实战(二)—图像几何变换

    🚀写在前面🚀 🖊个人主页:https://blog.csdn.net/m0_52051577?type=blog  🎁欢迎各位大佬支持点赞收藏,三连必回!! 🔈本人新开系列专栏—python图像处理 ❀愿每一个骤雨初晴之时,所有的蜻蜓振翅和雨后惊雷,都归你。 前言       图像几何变换就是在不改变图像像素值的前提

    2024年02月09日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包