前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >opencv(4.5.3)-python(二十九)--Hough线变换

opencv(4.5.3)-python(二十九)--Hough线变换

作者头像
用户9875047
发布2023-02-26 15:15:41
7260
发布2023-02-26 15:15:41
举报
文章被收录于专栏:机器视觉全栈er

翻译及二次校对: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边缘检测。第二个和第三个参数分别是ρ和θ的精度。第四个参数是阈值,这意味着它应该得到的最低票数才能被认为是一条线。记住,投票数取决于线上的点的数量。所以它代表了应该被检测到的最小长度的线。

代码语言:javascript
复制
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 - 线段之间的最大允许间隙,以便将它们视为一条线。

最重要的是,它直接返回线的两个端点。在以前的情况下,你只能得到线的参数,而且你必须找到所有的点。这里,一切都很直接和简单。

代码语言:javascript
复制
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]
引用链接

[1] 维基百科上的霍夫变换: https://en.wikipedia.org/wiki/Hough_transform

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-02-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器视觉全栈er 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引用链接
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档