opencv(4.5.3)-python(二十九)--Hough线变换
翻译及二次校对:cvtutorials.com
目标
在本章中:
- • 我们将理解Hough变换的概念。
- • 我们将看到如何使用它来检测图像中的线条。
- • 我们将看到以下函数:cv.HoughLines(), cv.HoughLinesP()
理论
Hough变换是一种流行的技术,可以检测任何形状。即使它是破碎的或扭曲一点点的形状,也可以检测。我们来看看它如何检测一条线。
一条线可以表示为y=mx+c,或者以参数形式表示为ρ=xcosθ+ysinθ,其中ρ是原点到线的垂直距离,θ是这条垂直线与水平轴形成的角度,以逆时针方向测量(这个方向因你如何表示坐标系而异。OpenCV中使用了这种表示方法)。) 请看下面的图片。
因此,如果直线经过原点以下,它将有一个正的rho和一个小于180的角度。如果它经过原点以上,不是取大于180的角度,而是取小于180的角度,并且rho是负的。任何垂直线都是0度,水平线都是90度。
现在让我们来看看Hough变换对线条的作用。任何线条都可以用这两个参数来表示,(ρ,θ)。因此,首先它创建了一个二维数组或累加器(用于保存两个参数的值),并且最初将其设置为0。让行表示ρ,列表示θ。数组的大小取决于你需要的精度。假设你希望角度的精度是1度,你就需要180列。对于ρ,可能的最大距离是图像的对角线长度。所以取一个像素的精度,行的数量可以是图像的对角线长度。
考虑一个100x100的图像,中间是一条水平线。取该线的第一个点。你知道它的(x,y)值。现在在直线方程中,把数值θ=0,1,2,....,180,然后检查你得到的ρ。对于每一对(ρ,θ),你在我们的累加器中的相应(ρ,θ)单元格中的值增加1。所以现在在累加器中,单元格(50,90)=1,还有其他一些单元格。
现在取直线上的第二个点。做到与上面一样。递增你得到的对应于(rho, theta)的单元格中的值。这一次,单元格(50,90)=2。你所做的实际上是对(ρ,θ)值进行投票。你对线上的每一个点都继续这个过程。在每个点上,(50,90)单元格将被递增或被选上,而其他单元格可能被选上也可能不被选上。这样,在最后,单元格(50,90)将拥有最大的票数。因此,如果你在累积器中搜索最大票数,你会得到(50,90)这个值,这说明在这幅图中有一条线,距离原点50,角度90度。这在下面的动画中得到了很好的体现。
这就是Hough变换对线条的作用。它很简单,也许你可以自己用Numpy实现它。下面是一张显示累积器的图片。一些位置的亮点表示它们是图像中可能的线条的参数。(图片来源:维基百科)
OpenCV中的Hough变换
上面解释的一切都被封装在OpenCV的函数cv.HoughLines()中。它只是返回一个(rho, theta)
值的数组。ρ以像素为单位,θ以弧度为单位。第一个参数,输入的图像应该是二进制图像,所以在应用hough变换之前要应用阈值或使用canny边缘检测。第二个和第三个参数分别是ρ和θ的精度。第四个参数是阈值,这意味着它应该得到的最低票数才能被认为是一条线。记住,投票数取决于线上的点的数量。所以它代表了应该被检测到的最小长度的线。
import cv2 as cv
import numpy as np
img = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.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))
cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv.imwrite('houghlines3.jpg',img)
结果如下:
概率Hough变换
在Hough变换中,你可以看到,即使是有两个参数的线,它也需要大量的计算。概率Hough变换是我们看到的Hough变换的一个优化。它不把所有的点都考虑在内。相反,它只考虑一个随机的点的子集,这对线的检测是足够的。我们只需要降低阈值。请看下面的图片,它比较了Hough空间中的Hough变换和概率Hough变换。
OpenCV的实现是基于Matas, J. and Galambos, C. and Kittler, J.V. [164]的《使用渐进式概率Hough变换进行线条的鲁棒检测》。使用的函数是cv.HoughLinesP()。它有两个新的参数。
- • minLineLength - 线段的最小长度。短于此的线段会被拒绝。
- • maxLineGap - 线段之间的最大允许间隙,以便将它们视为一条线。
最重要的是,它直接返回线的两个端点。在以前的情况下,你只能得到线的参数,而且你必须找到所有的点。这里,一切都很直接和简单。
import cv2 as cv
import numpy as np
img = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength=100,maxLineGap=10)
for line in lines:
x1,y1,x2,y2 = line[0]
cv.line(img,(x1,y1),(x2,y2),(0,255,0),2)
cv.imwrite('houghlines5.jpg',img)
结果如下:
其他资源
- 1. 维基百科上的霍夫变换[1]
引用链接
[1]
维基百科上的霍夫变换: https://en.wikipedia.org/wiki/Hough_transform
相关文章
- python 小波分解_python低通滤波器
- pycharm安装opencv-python_pycharm opencv
- Python环境搭建手把手图文教程
- python的进制转换器,Python进制转换[通俗易懂]
- Py之cv2:cv2库(OpenCV,opencv-python)的简介、安装、使用方法(常见函数、方法等)最强详细攻略[通俗易懂]
- python常见运维脚本_Python运维常用脚本[通俗易懂]
- opencv使用教程_opencv安装教程python
- OpenCV-Python学习(7)—— OpenCV 轨迹栏操作和键盘响应操作
- lambda表达式python_Python中的Lambda表达式「建议收藏」
- python如何抛出异常_python自定义异常
- PYTHON主机_我的Python世界PDF
- python抛出异常写法_零基础学 Python(32):如何抛出和捕获异常?「建议收藏」
- python绘制条形柱状图_Python柱状图
- python使用opencv如何保存图片_OpenCV Python 保存图片
- VSCode,一款好用编程开发工具,提升Python开发效率
- opencv(4.5.3)-python(十二)--图像阈值处理
- opencv(4.5.3)-python(十五)--图像梯度
- opencv(4.5.3)-python(十八)--轮廓线入门
- opencv(4.5.3)-python(十九)--轮廓线的特征
- 【7】python_matplotlib 输出(保存)矢量图方法;画图时图例说明(legend)放到图像外侧;Python_matplotlib图例放在外侧保存时显示不完整问题解决
- Python 平台是独立的吗?
- opencv(4.5.3)-python(二十二)--轮廓线层次结构
- python-Python与MongoDB数据库-使用Python执行MongoDB查询(三)
- python图片小爬虫详解编程语言
- Python结合MySQL实现信息交互(python与mysql交互)
- python学习Linux、Python,体验自由的乐趣(lexlinux)
- Python玩转Redis:提升缓存效率(python使用redis)
- Python脚本实现Linux系统管理及自动化部署(python写linux)
- Python如何使用MySQL构建立连接(python怎么连接mysql)
- python定时器使用示例分享
- python中frommoduleimport*的一个坑