Python OpenCV Hough直线检测算法的原理实现
作者:乔卿 发布时间:2021-01-29 10:10:00
直线检测原理
核心要点:图像坐标空间、参数空间、极坐标参数空间 -> (极坐标)参数空间表决
给定一个点,我们一般会写成y=ax+b的形式,这是坐标空间的写法;我们也可以写成b=-xa+y的形式,这是参数空间的写法。也就是说,给定一个点,那么经过该点的直线的参数必然满足b=-xa+y这一条件,也就是必然在参数空间中b=-xa+y这条直线上。如果给定两个点,那么这两点确定的唯一的直线的参数,就是参数空间中两条参数直线的交点。
由于上述写法不适合处理水平或垂直的直线,我们可以使用极坐标的形式描述直线,即ρ=xcosθ+ysinθ,其中ρ是从原点到直线的垂直距离,θ是由这条垂直线和水平轴形成的角度(以逆时针方向测量),
如下图所示:
因此,任何垂直线θ=0,水平线θ=90°。那么极坐标参数空间中的曲线交点就是由两个点确定的一条直线,如下图所示。
现在让我们看看Hough变换是如何处理直线的。任何一条线都可以用这两个参数来表示(ρ,θ)。
首先创建一个二维数组,即累加器,用来保存两个参数的值,然后最初将其设置为全0。让行表示ρ,列表示θ。数组的尺寸取决于所需的精度。假设希望角度的精度为1度,则需要180列,枚举0°-179°的所有情况。对于ρ,可能的最大距离是图像的对角线长度。因此,以一个像素的精度计算,行数可以是图像的对角线长度。
枚举所有的点,对于每一个点,将所有经过这一点的直线对应的参数(ρ,θ)在参数空间中找到对应位置,令该位置的累加器加1,即投票。这一过程如下图所示。
枚举完成所有点之后,累加器中值最大的(若干个)参数组合(ρ,θ)就是经过点最多的(若干条)直线,如下图所示,两条直线对应累加器中最亮的两个点。
总的来说,对于多个点,我们可以用(离散)参数空间表决的方法,记录每个点对应的允许的参数组合,求得那些被允许次数最多的参数组合,就是最多点经过的直线。
在图像矫正任务中,我们经过Canny算子检测出了若干边缘点,这些点主要集中在四个边界上,因此我们只需要使用Hough直线检测,求出四条直线,就能确定四个边界。
OpenCV实现
cv.HoughLines()封装了上述步骤,该函数原型为:
cv.HoughLines(image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]]) -> lines
参数:
lines:数组,每一个元素都是一条直线对应的(ρ, θ),ρ以像素为单位,θ以弧度为单位。
image:输入图像,需要是二值图像,所以在应用hough变换之前应用阈值或canny边缘检测。
rho:ρ的精度。
theta:θ的精度。
threshold:阈值,得票数高于该值的线才被认为是线,由于投票数取决于线上的点数,所以它代表了应该被检测到的线的最小点数。
下面是具体代码:
def hough_detect(image_path):
# 读取图像并转换为灰度图像
image = cv2.imread(image_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 使用Canny算子检测边缘
edges = canny_detect(image_path, False)
# 使用Hough检测直线
lines = cv2.HoughLines(edges, 1, np.pi/180, 200)
# 绘制直线
for line in lines:
rho, theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv2.imshow('line,jpg', image)
cv2.waitKey()
hough_detect('images/2.jpeg')
效果:
后面需要调整一下超参数。
来源:https://blog.csdn.net/qq_41112170/article/details/125729006
猜你喜欢
- 简单的说延迟复制就是设置一个固定的延迟时间,比如1个小时,让从库落后主库一个小时。MySQL延时复制库作用存在即合理,延迟复制可以用来解决以
- 一、字典的基本操作1.定义字典 字典也是一个列表型的数据结构,字典的数据是用“{ }&rd
- 本文实例为大家分享了python面向对象版的学生信息管理系统的具体代码,供大家参考,具体内容如下功能:1.能循环输入内容2.展示功能-1.新
- JDBC,Java Database Connectivity,即 Java 数据库连接。实际上 JDBC 是 Java 中的一套和数据库进
- 看了一个月的文档和资料以后,终于让我参与到项目中来了,哈哈,痛快!虽然只是让我解决一个小问题,不过有活干就是好。在写代码的过程中遇到了一个小
- 本文实例为大家分享了微信小程序实现电影App导航和轮播的具体代码,供大家参考,具体内容如下最终的目的:底部:我们要搞好这样的底部要在app.
- 注意:第三种方法要在 XSell 中使用,在 finalsell 中使用不了方式一:临时使用自动补全功能mysql -u root -p -
- 感谢人类方方面面的创新,今天Web开发已经不需要在如何设计网站上面浪费时间了。框架和库帮助web开发者得以专注于真正的开发工作上。下面的这些
- 本文实例讲述了Python开发微信公众平台的方法。分享给大家供大家参考,具体如下:这两天将之前基于微信公众平台的代码重构了下,基础功能以库的
- 今天碰到一个很有意思的问题,需要将普通的 Unicode字符串转换为 Unicode编码的字符串,如下:将 \\u9500\\u552e 转
- 引言近期做一些基于TCP协议的项目,跟其他接口方调试时经常出现不一致的问题,而程序日志又不能完成保证公正,就只能通过tcpdump抓包的方式
- 最近了解下基于 Token 的身份验证,跟大伙分享下。很多大型网站也都在用,比如 Facebook,Twitter,Google+,Gith
- body {font-family: Arial, sans-serif; }这是我迄今
- 众所周知,binlog日志对于mysql数据库来说是十分重要的。在数据丢失的紧急情况下,我们往往会想到用binlog日志功能进行数据恢复(定
- 前段时间公司数据库服务器崩溃启动不起来,经过我初步排查是/home目录挂载不上导致启动不起来,虽然通过注释/etc/fstab中的挂载信息,
- 在java的应用中,我们经常会对数据库进行必要的操作,下来我们就了解一下如何用java连接mysql数据库 以及java连接sql serv
- 计算信息熵的公式:n是类别数,p(xi)是第i类的概率假设数据集有m行,即m个样本,每一行最后一列为该样本的标签,计算数据集信息熵的代码如下
- 工作中我们经常需要判断某个变量/属性是否为undefined。通常有两种写法// 方式1 typeof age === 'undef
- 我相信绝大多数小伙伴在自学python时,运用pycharm进行编写程序时发现字体太小不方便进行编写,通常像codeblocks
- 一、查询条件精确,针对有参数传入情况 二、SQL逻辑执行顺序 FROM-->JOIN-->WHERE-->GROUP--&