侵权投诉

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

新机器视觉 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

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

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

收藏 人收藏
分享:

评论

相关推荐

在Anaconda中安装python包seaborn

在Anaconda中安装python包seaborn(现代电源技术题库)-在Anaconda中安装p....
发表于 09-18 15:01 5次 阅读
在Anaconda中安装python包seaborn

CAFFE+OPENCV+OPENBLAS+ANACONDA+UBUNTU14.04配置

CAFFE+OPENCV+OPENBLAS+ANACONDA+UBUNTU14.04配置(新型电源技....
发表于 09-18 14:30 5次 阅读
CAFFE+OPENCV+OPENBLAS+ANACONDA+UBUNTU14.04配置

Python科学计算利器Anaconda

Python科学计算利器Anaconda(开关电源技术毕业设计)-Python科学计算利器Anaco....
发表于 09-18 14:26 7次 阅读
Python科学计算利器Anaconda

介绍3种方法跨时钟域处理方法

跨时钟域处理是FPGA设计中经常遇到的问题,而如何处理好跨时钟域间的数据,可以说是每个FPGA初学者....
的头像 FPGA设计论坛 发表于 09-18 11:33 623次 阅读
介绍3种方法跨时钟域处理方法

BorlandCBuilder6.0安装OPENCV方法

BorlandCBuilder6.0安装OPENCV方法(新型电源技术结课论文UC3842)-文档为....
发表于 09-17 15:34 7次 阅读
BorlandCBuilder6.0安装OPENCV方法

Kinect-Face-Tracking-----使用opencv显示后的超级简化版本

Kinect-Face-Tracking-----使用opencv显示后的超级简化版本(电源技术发展....
发表于 09-17 15:06 6次 阅读
Kinect-Face-Tracking-----使用opencv显示后的超级简化版本

如何使用工业树莓派做ython的PWM控制

虹科工业树莓派 准备工作 硬件: 虹科工业树莓派1台 DIO模块1个 Windows系统电脑1台 L....
的头像 广州虹科电子科技有限公司 发表于 09-16 10:57 1088次 阅读
如何使用工业树莓派做ython的PWM控制

声级频率计权的基本定义

1、声级频率计权声级频率计权的基本定义是指其恒幅稳态正弦输入信号级与显示装置上指示信号级两者之间作为频率函数关系而规定的差...
发表于 09-16 08:39 0次 阅读

es6语法中函数参数

es6语法中函数参数 本文在我们的《 实用ES6》 一书中有介绍 。 深入了解ES6中引入的新语言功能。  ES6引入了Ar...
发表于 09-16 08:17 0次 阅读

实现步进电机运动

目前做一个项目遇到一个问题,就是在实现步进电机运动时,点动模式电机振动很厉害,现在就一个非常强大的第三方库Accelstepper进...
发表于 09-16 07:34 0次 阅读

Python解释器的基本结构

简介Byterun是一个用Python实现的Python解释器。通过对Byterun的研究,我惊奇地发现Python解释器的基本结构很容易符合500行...
发表于 09-16 06:42 0次 阅读

用ES6编写JavaScript函数

这篇文章是在我们的书,功能 实用ES6 。 获取的ES6引入的新的语言特性的深刻理解。  箭功能用ES6引入作为编写J...
发表于 09-16 06:40 0次 阅读

python爬取猫咪交易数据

最近发现身边朋友开始养猫咪的也来越多了,甚至有的人会花大几千块钱去买一只猫来养。现在很流行养一些比较名贵的猫,比如橘猫、...
发表于 09-15 16:08 0次 阅读

基于Python-casacore的射电测量集文件生成方法

基于Python-casacore的射电测量集文件生成方法(开关电源技术试卷)-该文档为基于Pyth....
发表于 09-15 13:11 11次 阅读
基于Python-casacore的射电测量集文件生成方法

C语言中struct的用法有哪些

定义结构体变量       下面举一个例子来说明怎样定义结构体变量。                ....
的头像 STM32嵌入式开发 发表于 09-15 09:41 669次 阅读

机器人工具箱中的常用函数介绍

这一节,就机器人工具箱中的一些常用的函数做一下简单的介绍。机器人工具箱在机器人建模、轨迹规划、控制、可视化仿真等方面给机...
发表于 09-15 09:04 0次 阅读

Serverless概念

Serverless简介概念Serverless的全称是Serverless computing无服务器运算,又被称为函数即服务(Function-as-a-Service,缩...
发表于 09-15 07:38 0次 阅读

电机传递函数为角速率和转角

北航计算机控制系统大作业2 (13页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦!14...
发表于 09-15 06:53 0次 阅读

过零点检测在无传感器的无刷直流电机控制中有何作用

六步换相原理是什么? 如何去编写六步换相函数的代码程序呢? 过零点检测在无传感器的无刷直流电机控制中有何作用? ...
发表于 09-15 06:33 0次 阅读

符合IEPE标准的CbM机器学习赋能平台

CbM需要捕获全带宽数据,以确保时域和频域中的所有谐波、混叠及其他机械相互作用都得到考虑。这种数据收....
发表于 09-13 12:45 3373次 阅读
符合IEPE标准的CbM机器学习赋能平台

C++基础语法友元类和友元函数

本期是C++基础语法分享的第五节,今天给大家来分享一下: (1)explicit(显式)关键字; (....
的头像 C语言编程学习基地 发表于 09-12 09:52 190次 阅读

如何通过Python脚本实现WIFI密码的暴力破解

前言 本文将记录学习下如何通过 Python 脚本实现 WIFI 密码的暴力破解,从而实现免费蹭网。....
的头像 马哥Linux运维 发表于 09-10 17:09 323次 阅读
如何通过Python脚本实现WIFI密码的暴力破解

C++基础语法之inline 内联函数

上节我们分析了C++基础语法的const,static以及 this 指针,那么这节内容我们来看一下....
的头像 C语言编程学习基地 发表于 09-09 09:38 152次 阅读

如何使用C++语法中的volatile

volatile volatile int i = 10; volatile 关键字是一种类型修饰符....
的头像 C语言编程学习基地 发表于 09-09 09:38 214次 阅读

C++语法中的inline内联函数详解

上节我们分析了C++基础语法的const,static以及 this 指针,那么这节内容我们来看一下....
的头像 C语言编程学习基地 发表于 09-09 09:33 1019次 阅读

Kitronik ARCADE游戏手柄实现连连看

连连看相信大家都玩过,但这个用Kitronik AR CADE游戏手柄来玩连连看的项目你相信是一个高....
的头像 电子森林 发表于 09-08 11:47 223次 阅读
Kitronik ARCADE游戏手柄实现连连看

函数信号发生器的功能及优势

函数信号发生器是一种信号发生装置,能产生某些特定的周期性时间函数波形 ( 正弦波、方波、三角波、锯齿....
发表于 09-08 11:35 98次 阅读

计算机视觉中如何调用OpenCV库

学习计算机视觉最重要的能力应该就是编程了,为了帮助小伙伴尽快入门计算机视觉,小白准备了【走进Open....
的头像 新机器视觉 发表于 09-08 10:26 1500次 阅读

如何在环境安装使用Python操作word

作者丨超级大洋葱806 https://tangxing.blog.csdn.net/article....
的头像 Android编程精选 发表于 09-05 15:13 438次 阅读
如何在环境安装使用Python操作word

如何利用Python抓取用户发的话题

大多数APP里面返回的是json格式数据,或者一堆加密过的数据 。这里以超级课程表APP为例,抓取超....
的头像 马哥Linux运维 发表于 09-05 09:37 218次 阅读
如何利用Python抓取用户发的话题

Spark SQL的概念及查询方式

一、Spark SQL的概念理解 Spark SQL是spark套件中一个模板,它将数据的计算任务通....
的头像 数据分析与开发 发表于 09-02 15:44 182次 阅读
Spark SQL的概念及查询方式

你们知道指针和引用正确的使用场景吗

先解决两个疑问 ◆ 指针和引用的不同之处是什么? ◆ 何时用用指针?何时用引用? 指针和引用的不同之....
的头像 STM32嵌入式开发 发表于 09-02 14:37 180次 阅读
你们知道指针和引用正确的使用场景吗

为什么要进行单相机标定

为什么要进行单相机标定? 广义:畸变矫正和一维和二维测量 畸变矫正: 在几何光学和阴极射线管(CRT....
的头像 新机器视觉 发表于 09-02 09:45 213次 阅读

分享一个最新的的Python对象序列化方式

许多Python标准库都有一些未被赏识的精华。其中之一是允许简单优雅的基于参数类型的函数分发。这一特....
的头像 马哥Linux运维 发表于 09-01 15:19 674次 阅读
分享一个最新的的Python对象序列化方式

jsonpath库中的常规功能介绍

1 简介 在日常使用Python的过程中,我们经常会与json格式的数据打交道,尤其是那种嵌套结构复....
的头像 Linux爱好者 发表于 09-01 14:11 186次 阅读
jsonpath库中的常规功能介绍

Python 代码加速运行的的小技巧

Python 是一种脚本语言,相比 C/C++ 这样的编译语言,在效率和性能方面存在一些不足。但是,....
的头像 Android编程精选 发表于 09-01 11:28 245次 阅读

HFSS-API常用的基本形状和布尔操作函数

摘要: 上节HFSS-API入门第一弹:画个Box主要是分享了调用改良hfssapi新建工程和设计文....
的头像 知社学术圈 发表于 08-27 15:38 153次 阅读

如何过滤掉MySQL大批量插入的重复数据

线上库有6个表存在重复数据,其中2个表比较大,一个96万+、一个30万+,因为之前处理过相同的问题,....
的头像 阿铭linux 发表于 08-27 11:00 273次 阅读

基于Rust基础上如何去编写一个Linux内核模块

编者按:近些年来 Rust 语言由于其内存安全性和性能等优势得到了很多关注,尤其是 Linux 内核....
的头像 开关电源芯片 发表于 08-27 09:59 1028次 阅读

四个方面全面解析Linux 下 C++ 编译&链接

【导读】:编译与链接对CC++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译与链接过程,陌生在于大....
的头像 开关电源芯片 发表于 08-27 09:36 2803次 阅读
四个方面全面解析Linux 下 C++ 编译&链接

OpenCV在低对比度缺陷检测中的应用实例

导读本文主要介绍OpenCV在低对比度缺陷检测中的应用实例。 实例一(LCD屏幕脏污检测) 参考实例....
的头像 尖刀视 发表于 08-26 15:52 231次 阅读
OpenCV在低对比度缺陷检测中的应用实例

女友让翻译化妆品标签 看大佬如何用Python轻松解决

最近小编遇到一个生存问题,女朋友让我给她翻译英文化妆品标签。美其名曰:“程序猿每天英语开发,英文一定....
的头像 阿铭linux 发表于 08-25 17:27 242次 阅读

OpenCV中的Python实现

OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Window....
的头像 人工智能 发表于 08-25 15:55 199次 阅读

利用Python和PyTorch处理面向对象的数据集

本篇是利用 Python 和 PyTorch 处理面向对象的数据集系列博客的第 2 篇。 如需阅读第....
的头像 FPGA开发圈 发表于 08-25 15:30 1107次 阅读

OpenCV图像处理如何进行梯度检测

梯度简单来说就是求导,OpenCV 提供了三种不同的梯度滤波器,或者说高通滤波器: Sobel,Sc....
的头像 新机器视觉 发表于 08-25 11:42 292次 阅读

如何使用Python来制作酷炫的图形

1. 什么是turtle turtle又称为海龟绘图,是Wally Feurzeig, Seymou....
的头像 上海磐启微电子有限公司 发表于 08-25 11:36 285次 阅读

python程序里如何链接MySQL数据库

在python程序里,如何链接MySQL数据库? 连接MYSQL需要3步 1、安装 必须先安装MyS....
的头像 奈因PCB电路板设计 发表于 08-23 14:56 1489次 阅读

Python虚拟环境pipenv的使用

一般我们创建 Python 项目的时候都会创建一个虚拟环境,这样做的好处就是会把项目环境和操作系统环....
的头像 开关电源芯片 发表于 08-23 10:15 193次 阅读

数据分析利器之Excel的常用函数

导读:在【Excel功能篇】,我们围绕Excel的基础功能以及常见的练习题梳理了Excel的常用功能....
的头像 上海磐启微电子有限公司 发表于 08-17 16:43 372次 阅读
数据分析利器之Excel的常用函数

如何用Python制作出一个二维码

下载myqr库 使用windows+R键,输入cmd调出命令窗口 在黑框里输入(在python3环境....
的头像 阿铭linux 发表于 08-17 09:48 248次 阅读
如何用Python制作出一个二维码

如何用python自制一款炫酷的音乐播放器

前言 晚上坐在电脑面前,想着一边撸代码,一边听音乐。搜了搜自己想听的歌,奈何好多歌曲都提示需要版权,....
的头像 阿铭linux 发表于 08-17 09:37 2330次 阅读

西门子PLC中四舍五入和截取函数显示

四舍五入和截取函数也属于数据类型转换函数。下表显示了这些函数的名称、数据类型(输入参数和函数值)和任....
的头像 人工智能 发表于 08-16 16:08 516次 阅读

简述linux 驱动程序的数据封装

0.引言 基于 ARM 内核的 SoC 在引入设备树技术之后,通过设备树文件来描述不同的设备并匹配不....
的头像 开关电源芯片 发表于 08-14 11:34 428次 阅读
简述linux 驱动程序的数据封装

浅析具有内置数据库和身份验证支持的 Python 框架

Replit 使编码人员能够快速构建应用程序。除了浏览器,开发人员可以启动服务器,将数据存储在 Re....
的头像 阿铭linux 发表于 08-14 11:05 364次 阅读

一文剖析隐藏shell脚本内容的工具shc

从事 Linux 开发的同学,经常需要编写 shell 脚本,有时脚本中会涉及到一些敏感内容,比如一....
的头像 开关电源芯片 发表于 08-14 10:44 315次 阅读
一文剖析隐藏shell脚本内容的工具shc

简述go语言标准库 net/url 库的过程。

本文是一篇学习笔记,记录了作者学习 go 语言标准库 net/url 库的过程。 参考:https:....
的头像 阿铭linux 发表于 08-14 10:35 259次 阅读

如何才能熟练掌握关于for循环

好吧,也许你认为我在写一篇如何使用for循环的文章,,,,首先,我想说无论是学习C语言还是学习jav....
的头像 C语言编程基础 发表于 08-14 09:47 267次 阅读

二叉树的所有路径介绍

以为只用了递归,其实还用了回溯 257. 二叉树的所有路径 题目地址:https://leetcod....
的头像 新材料在线 发表于 08-13 17:51 530次 阅读
二叉树的所有路径介绍