OpenCV 4.11.0
开源计算机视觉
加载中…
搜索中…
未找到匹配项
霍夫线变换

目标

  • 我们将了解霍夫变换的概念。
  • 我们将学习如何使用它来检测图像中的直线。
  • 我们将学习以下函数:cv.HoughLines()cv.HoughLinesP()

理论

霍夫变换是一种流行的技术,可以检测任何形状,只要您可以用数学形式表示该形状。即使形状稍微断裂或变形,它也能检测到形状。我们将看到它如何用于直线。

一条直线可以用\(y = mx+c\)表示,也可以用参数形式表示为\(\rho = x \cos \theta + y \sin \theta\),其中\(\rho\)是原点到直线的垂直距离,\(\theta\)是由这条垂直线和水平轴形成的角度,逆时针方向测量(方向取决于你如何表示坐标系。OpenCV中使用这种表示方法)。请查看下面的图像

图像

因此,如果直线经过原点下方,则它将具有正的ρ和一个小于180的角度。如果它经过原点上方,则角度取小于180,ρ取负值,而不是取大于180的角度。任何垂直线都将具有0度,水平线将具有90度。

现在让我们看看霍夫变换如何用于直线。任何直线都可以用这两个参数\(\rho, \theta\)来表示。所以首先它创建一个二维数组或累加器(用于保存这两个参数的值),并且它最初设置为0。行表示\(\rho\),列表示\(\theta\)。数组的大小取决于您需要的精度。假设您希望角度精度为1度,则需要180列。对于\(\rho\),最大可能距离是图像的对角线长度。因此,如果取一个像素精度,则行数可以是图像的对角线长度。

考虑一个100x100的图像,中间有一条水平线。取直线的第一个点。你知道它的(x,y)值。现在在线性方程中,将\(\theta = 0,1,2,....,180\)代入,并检查你得到的\(\rho\)值。对于每个\(\rho, \theta\)对,你都会在累加器中相应的\(\rho, \theta\)单元中将值加一。所以现在在累加器中,单元(50,90) = 1以及其他一些单元。

现在取直线上的第二个点。执行与上述相同的操作。将你得到的\(\rho, \theta\)对应单元的值加一。这次,单元(50,90) = 2。你实际上是在对\(\rho, \theta\)值进行投票。你对直线上的每个点都重复这个过程。在每个点上,单元(50,90)都将被递增或投票,而其他单元可能会或可能不会被投票。这样,最终,单元(50,90)将获得最大票数。因此,如果你搜索累加器以获得最大票数,你将得到值(50,90),这意味着图像中有一条线,距离原点50,角度为90度。这在下图动画中得到了很好的体现(图片来自:Amos Storkey

这就是霍夫变换对直线的工作原理。很简单。下面是一张显示累加器的图像。某些位置的亮点表示它们是图像中可能直线的参数。(图片来自:维基百科

OpenCV中的霍夫变换

上面解释的所有内容都封装在OpenCV函数cv.HoughLines()中。它只返回一个\(\rho, \theta\)值的数组。\(\rho\)以像素为单位测量,\(\theta\)以弧度为单位测量。第一个参数,输入图像应该是二值图像,所以在应用霍夫变换之前应用阈值或使用Canny边缘检测。

我们使用函数:cv.HoughLines (image, lines, rho, theta, threshold, srn = 0, stn = 0, min_theta = 0, max_theta = Math.PI)

参数
图像8位单通道二值源图像。该函数可能会修改图像。
lines直线的输出向量(cv.32FC2 类型)。每条线都由一个两元素向量 (ρ,θ) 表示。ρ是距坐标原点 (0,0) 的距离。θ是直线的旋转角度(以弧度表示)。
rho累加器中距离分辨率(以像素为单位)。
theta累加器中角度分辨率(以弧度为单位)。
threshold累加器阈值参数。只返回获得足够投票数的直线。
srn对于多尺度霍夫变换,它是距离分辨率 rho 的除数。粗略累加器距离分辨率为 rho,精确累加器分辨率为 rho/srn。如果 srn=0 且 stn=0,则使用经典霍夫变换。否则,这两个参数都应为正数。
stn对于多尺度霍夫变换,它是角度分辨率 theta 的除数。
min_theta对于标准和多尺度霍夫变换,要检查直线的最小角度。必须介于 0 和 max_theta 之间。
max_theta对于标准和多尺度霍夫变换,要检查直线的最大角度。必须介于 min_theta 和 CV_PI 之间。

试试看

概率霍夫变换

在霍夫变换中,您可以看到,即使对于具有两个参数的直线,它也需要大量的计算。概率霍夫变换是我们看到的霍夫变换的一种优化方法。它不会考虑所有点。相反,它只考虑足以进行直线检测的随机点子集。我们只需要降低阈值即可。请参见下图,该图比较了霍夫空间中的霍夫变换和概率霍夫变换。(图片来自:Franck Bettinger的主页

图像

OpenCV 的实现基于 Matas,J. 和 Galambos,C. 和 Kittler,J.V. 的《使用渐进概率霍夫变换进行鲁棒的直线检测》 [185]

我们使用函数:cv.HoughLinesP (image, lines, rho, theta, threshold, minLineLength = 0, maxLineGap = 0)

参数
图像8位单通道二值源图像。该函数可能会修改图像。
lines线段输出向量(cv.32SC4 类型)。每条线段由一个四元素向量 (x1,y1,x2,y2) 表示,其中 (x1,y1) 和 (x2,y2) 是检测到的线段的两个端点。
rho累加器中距离分辨率(以像素为单位)。
theta累加器中角度分辨率(以弧度为单位)。
threshold累加器阈值参数。只返回获得足够投票数的直线。
minLineLength最小线段长度。短于此长度的线段将被拒绝。
maxLineGap同一直线上允许的点之间最大间隙,用于连接这些点。

试一试