0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于OpenCV经典霍夫变换的一些内容

新机器视觉 ? 来源:古月居 ? 作者:Eragonl ? 2021-07-06 10:43 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

本文主要讲述的是霍夫变换的一些内容,并加入一些在生活中的应用,希望能对读者对于霍夫变换的内容有所了解。

首先我先说的是,霍夫变换是一个特征提取技术。其可用于隔离图像中特定形状的特征的技术,应用在图像分析、计算机视觉和数字图像处理领域。目的是通过投票程序在特定类型的形状内找到对象的不完美实例。

这个投票程序是在一个参数空间中进行的,在这个参数空间中,候选对象被当作所谓的累加器空间中的局部最大值来获得,所述累加器空间由用于计算霍夫变换的算法明确地构建。此处我们主要介绍的是比较基本的霍夫变换在直线中的应用,例如在图像中检测直线(线段),Hough变换的主要优点是对于噪声有良好的鲁棒性。

基础原理介绍

正如我们上面所介绍的那样,霍夫变换最简单的是检测直线。我们知道,直线的方程表示可以由斜率k和截距b表示(这种表示方法,称为斜截式,也就是高中的时候学习到的一种常用形式),如下所示:

y=kx+b

如果我们用参数空间表示则为(b,k),即,我们可以用斜率和截距就能表示一条直线。但这种形式会产生一个问题,那就是当我们的直线斜率k为无限大的时候(即垂线),这会使得该直线无法使用斜截式来进行表示,此处我们需要使用到另一种直线的表现形式:黑塞法线式(或者简称为法线式):

r=xcosθ+ysinθ

其中r是原点到直线上最近点的距离(其他人可能把这记录为ρ,下面也可以把r看成参数ρ,两者含义相同),θ是x轴与连接原点和最近点直线之间的夹角。

从而我们可以将图像的每一条直线与一对参数(r,θ)相关联。由参数(r,θ)构成的平面有时被称为霍夫空间,用于表示二维直线所构成的集合。

我们经过Hough变换后,我们圆来笛卡尔坐标系中的一个点可以映射到Hough空间中去。

经过原笛卡尔坐标系中的定点(3,4),通过该点的所有可能直线的(r,θ)的关系。显示了在极坐标对极径极角平面绘出所有通过该定点的直线, 将得到一条正弦曲线。正弦曲线的形状取决于,点到所定义原点的距离r。通常,r越大,正弦曲线的振幅越大,反之则会越小。

所以我们可以得到一个结论,给定平面中的单个点,那么通过该点的所有直线的集合对应于(r,θ)平面中的正弦曲线,这对于该点是独特的。一组两个或更多点形成一条直线将产生在该线的(r,θ)处交叉的正弦曲线。因此,检测共线点的问题可以转化为找曲线相交点的问题。

例:

考虑下面三个点,这里显示为黑点。

(注:此处也展示了霍夫变换的几个基本步骤:首先,对每个点均绘制不同角度的线条,这些线全部经过各自的对应点并显示为实线。其次,对于每条实线,找到经过原点的对应垂线并显示为虚线。然后找到虚线的长度和角度。这些值显示在图表下方的表格中。这对被转换的三个点中的每一个都重复该过程。然后将结果绘制成图,有时称为霍夫空间图)

曲线相交的点给出的距离和角度表示各个测试点相交的线。

分析上下文,边缘段的点(一个或多个)的坐标(xi,yi)在图像中是已知的,并且因此作为参数线等式中的常量,而r与θ是未知变量是我们要寻找的。如果我们绘制由(r,θ)每个定义的可能值(xi,yi)。

笛卡尔图像空间中的点映射到霍夫参数空间中的曲线(正弦曲线)。这个点到曲线的变换是直线的霍夫变换。当在霍夫参数空间中查看时,在笛卡尔图像空间中共线的点变得很明显,因为它们产生在相同(r,θ)点相交的曲线。

霍夫变换提取直线

我们通过将霍夫参数空间量化为有限间隔或累加器单元来实现变换。随着算法的运行,每个算法都把(xi,yi)转换为一个离散化的 (r,θ)曲线,并且沿着这条曲线的累加器单元被递增。累加器阵列中产生的峰值表示图像中存在相应的直线的相应证明。

此时需要注意的是,现在我们考虑的是直线的霍夫变换。累加器阵列的维度是二维的(也就是r和θ)。

那么对于图像来说,(x,y)处的每个像素及其邻域,霍夫变换算法被用于确定该像素是否有足够的直线证据。如果是,它将计算该线的参数 (r,θ),然后查找参数落入的累加器箱,并增加该箱的值(投票值)。通过查找具有最高值的箱,通常通过查找累加器空间中的局部最大值,可以提取最可能的线,并且读出它们的(近似的)几何定义。

找到这些峰值的最简单方法是通过应用某种形式的阈值,但其他技术可能在不同情况下产生更好的结果。由于返回的行不包含任何长度信息,因此通常有必要在下一步中查找图像的哪些部分与哪些行匹配。此外,由于边缘检测步骤中存在缺陷误差,通常会在累加器空间中出现错误,这可能使得找到合适的峰值以及适当的线条变得非常重要。

线性霍夫变换的最终结果是类似于累加器的二维阵列(矩阵),该矩阵的一个维度是量化角度θ,另一个维度是量化距离r。矩阵的每个元素的值等于位于由量化参数 (r,θ)表示的线上的点或像素的总和。

所以具有最高值的元素表示输入图像中代表最多的直线。我们也可以把累计器单元的结果认为是投票值。换句话说,将每个交点看成一次投票,也就是说A(r,θ)=A(r,θ)+1,所有点都如此进行计算后,可以设置一个阈值,投票大于这个阈值的可以认为是找到的直线。

霍夫变换提取圆

而当我们需要去进行圆检测的时候,我们累加器是三维累加器,在圆检测的情况下,我们可以知道的是其对应的参数方程为:

(x?a)2+(y?b)2=r2

其中a和b是圆心的坐标并且是r半径。在这种情况下,算法的计算复杂度开始增加,因为我们现在在参数空间和三维累加器中有三个坐标。(通常,累加器阵列的计算和大小随着参数数量的增加而多项式增加,因此,基本霍夫技术仅适用于简单曲线。)

它的算法步骤如下:

1.首先创建累加器空间,由每个像素单元格构成。最初每个单元格都设置为0。

2.然后对于每个图像中的边缘点(i,j),按照圆方程(i?a)2+(j?b)2=r2将那些可能是一个圆中心的单元格值进行累加。这些单元格在等式中由字母a表示。

3.然后在前面的步骤中由每个可能找到的值a,区找到满足等式的所有可能值b。

4.搜索累加器空间中的局部最大值。这些单元格表示算法检测到的圆圈。

如果我们不知道事先定位的圆的半径,可以使用三维累加器空间来搜索具有任意半径的圆。当然,这在计算上更加昂贵。

该方法还可以检测部分位于累加器空间外部的圆,只要该圆的区域内仍有足够的圆。

总结

霍夫变换在很多地方都有着应用,如果是在OpenCV(Python)下想要使用霍夫变换,只需要使用函数cv2.HoughLinesP函数,需要注意的是该函数并不是标准的霍夫变换,其为:概率霍夫变换,它只分析点的子集并估计这些点都属于一条直线的概率,这是标准霍夫变换的优化版本。该函数计算代价少,执行更快,但准确度有一定程度的下降。

cv2.HoughLinesP函数的语法如下:

cv2.HoughLinesP(image,rho,theta,threshold,minLineLength,maxLineGap)

其参数分别解释如下:

·image:要处理的二值图像;·rho:线段的几何表示,表示取距离的间隔,一般取1;·theta:线段的几何表示,表示取角度的间隔,一般取np.pi/180;·threshold:阈值,低于该阈值的会被忽略;·minLineLength:最小直线长度,小于该长度会被忽略;·maxLineGap:最大线段间隙,大于此间隙才被认为是两条直线。

霍夫变换在自动驾驶中也有所应用,可以如下面一个简单例子所示,其实现的是对我们画面中的道路直线进行的检测:

import osimport reimport cv2import numpy as np

# 初始化一个掩膜def mask_create(): img = cv2.imread(‘0.png’) zero = np.zeros_like(img[:, :, 0]) poly = np.array([[50, 270], [220, 160], [345, 160], [480, 270]]) zero_fixed = cv2.fillConvexPoly(zero, poly, (255, 255, 255)) return zero_fixed

# 掩膜计算,传入的图像需要是BGR图def mask_calc(frame, mask): img = cv2.bitwise_and(frame[:, :, 0], frame[:, :, 0], mask=mask) return img

# 图像阈值操作,传入的图片需要是灰度图def threshold(low, high, img): ret, thresh = cv2.threshold(img, low, high, cv2.THRESH_BINARY) return thresh

# 对图像进行霍夫变换,输入的图像需要是二值图,距离r为1,旋转角为1度,投票阈值为30,最远距离为200像素# 并在原图上进行绘制图像def hough(thresh, img): lines = cv2.HoughLinesP(thresh, 1, np.pi/180, 30, maxLineGap=200) try: for line in lines: x1, y1, x2, y2 = line[0] img = cv2.line(img, (x1, y1), (x2, y2), (255, 255, 255), 3) except: return img else: return img# 主函数def mainn(): # 读取数据 col_frames = os.listdir(‘。。/frames/’) # 排序 col_frames.sort(key=lambda f: int(re.sub(‘D’, ‘’, f))) # 读取画面每一帧 for i in col_frames: img = cv2.imread(i) # 构建一个掩膜 mask = mask_create() # 对原图像进行掩膜计算 masked_frame = mask_calc(img, mask) thresh = threshold(135, 255, masked_frame) img = hough(thresh, img) cv2.imshow(‘img’, img) if cv2.waitKey(40) == ord(‘q’): break cv2.destroyAllWindows()

mainn()

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 函数
    +关注

    关注

    3

    文章

    4388

    浏览量

    65316
  • OpenCV
    +关注

    关注

    32

    文章

    648

    浏览量

    43275
  • python
    +关注

    关注

    56

    文章

    4832

    浏览量

    87781

原文标题:[OpenCV]经典霍夫变换原理

文章出处:【微信号:vision263com,微信公众号:新机器视觉】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    零成本钢铁侠手套!树莓派+OpenCV 秒变手势遥控器!

    大家好,这是个树莓派和OpenCV的连载专题。使用树莓派与OpenCV实现姿态估计和面部特征点追踪使用树莓派与OpenCV实现面部和运动追踪的云台系统使用树莓派和
    的头像 发表于 08-16 16:16 ?106次阅读
    零成本钢铁侠手套!树莓派+<b class='flag-5'>OpenCV</b> 秒变手势遥控器!

    如何使用树莓派与OpenCV实现面部和运动追踪的云台系统?

    大家好,这是个树莓派和OpenCV的连载专题。使用树莓派与OpenCV实现姿态估计和面部特征点追踪使用树莓派与OpenCV实现面部和运动追踪的云台系统使用树莓派和
    的头像 发表于 08-14 17:45 ?194次阅读
    如何使用树莓派与<b class='flag-5'>OpenCV</b>实现面部和运动追踪的云台系统?

    如何板端编译OpenCV并搭建应用--基于瑞芯微米尔RK3576开发板

    运行opencv代码,来完成一些视觉内容,充分发挥该板的性能。要先编译opencv需要一些预先的准备工作首先更新软件包并安装必要的依赖:su
    发表于 08-08 17:14

    基于LockAI视觉识别模块:C++轮廓检测

    。 读取图像帧:从摄像头中获取实时视频帧。 预处理:将图像转换为灰度图、降噪等操作。 特征检测:执行边缘检测、变换等算法。 结果绘制:在原图上绘制检测到的特征。 显示结果:将处理后的图像输出到屏幕
    发表于 05-22 10:05

    电路基础知识最全汇总,看这篇就够了!(建议收藏)

    。 5.电路的断路与短路 电路的断路处:I=0,U≠0 电路的短路处:U=0,I≠0 。 二、基尔霍夫定律 1.几个概念 支路:是电路的个分支。结点:三条(或三条以上)支路的联接点称为结点
    发表于 05-08 14:18

    Debian和Ubuntu哪个好一些

    兼容性对比Debian和Ubuntu哪个好一些,并为您揭示如何通过RAKsmart服务器释放Linux系统的最大潜能。
    的头像 发表于 05-07 10:58 ?439次阅读

    树莓派在自动化控制项目中的一些潜在应用

    自动化控制项目中的一些潜在应用。之前,我们已经为Arduino平台探讨了相同的话题。我们确定Arduino是个出色的教育工具,但由于一些限制,它无法在工业环境中完全
    的头像 发表于 03-25 09:45 ?282次阅读
    树莓派在自动化控制项目中的<b class='flag-5'>一些</b>潜在应用

    LC滤波器设计与制作 [日 森荣二]

    本书主要介绍了滤波器的种类和特性,低通滤波器的经典设计,巴特沃思型低通滤波器的设计,切比雪型低通滤波器的设计,白塞尔型低通滤波器的设计,高斯型低通滤波器的设计,高通滤波器的设计方法, 带通滤波器
    发表于 03-06 15:04

    AN29-关于DC-DC转换器的一些想法

    电子发烧友网站提供《AN29-关于DC-DC转换器的一些想法.pdf》资料免费下载
    发表于 01-08 13:57 ?0次下载
    AN29-关于DC-DC转换器的<b class='flag-5'>一些</b>想法

    一些常见的动态电路

    无论是模电还是数电,理论知识相对来说还是比较枯燥,各种电路原理理解清楚不算容易,换种生动形象的方式或许会增加一些趣味性,也更容易理解这些知识。下面整理了一些常见的电路,以动态图形的方式展示。 整流
    的头像 发表于 11-16 09:26 ?1241次阅读
    <b class='flag-5'>一些</b>常见的动态电路

    经典傅里叶变换与快速傅里叶变换的区别

    经典傅里叶变换与快速傅里叶变换(FFT)在多个方面存在显著的区别,以下是对这两者的比较: 、定义与基本原理 经典傅里叶
    的头像 发表于 11-14 09:37 ?1449次阅读

    分享一些常见的电路

    理解模电和数电的电路原理对于初学者来说可能比较困难,但通过一些生动的教学方法和资源,可以有效地提高学习兴趣和理解能力。 下面整理了一些常见的电路,以动态图形的方式展示。 整流电路 单相桥式整流
    的头像 发表于 11-13 09:28 ?898次阅读
    分享<b class='flag-5'>一些</b>常见的电路

    欧姆定律和基尔霍夫定律的区别

    欧姆定律和基尔霍夫定律是电路学中两个重要的定律,它们各自描述了电路中不同的现象和规律。以下是它们之间的主要区别: 、定义与内容 欧姆定律 定义:描述电流、电压和电阻之间关系的基本定律。 内容
    的头像 发表于 10-28 15:19 ?1534次阅读

    dct变换的主要优点有哪些

    中的少数几个系数中,从而实现高效的压缩。以下是DCT变换一些主要优点: 能量压缩 :DCT的个显著优点是它能够将图像的能量集中在变换后的低频系数中。这意味着图像中最重要的信息(通常
    的头像 发表于 09-30 16:30 ?1371次阅读

    LED驱动器应用的一些指南和技巧

    电子发烧友网站提供《LED驱动器应用的一些指南和技巧.pdf》资料免费下载
    发表于 09-25 11:35 ?0次下载
    LED驱动器应用的<b class='flag-5'>一些</b>指南和技巧