OpenCV 4.10.0
开源计算机视觉
|
如果您可以用数学形式表示任何形状,那么霍夫变换是一种流行的检测任何形状的技术。即使形状略有破损或扭曲,它也可以检测到该形状。我们将看到它是如何对线工作的。
一条线可以表示为\(y = mx+c\),或以参数形式表示,即\(\rho = x \cos \theta + y \sin \theta\),其中\(\rho\)是原点到线的垂直距离,\(\theta\)是由这条垂直线和水平轴形成的角度,并逆时针测量(此方向取决于您如何表示坐标系。此表示形式在 OpenCV 中使用)。查看下面的图片
因此,如果线通过原点下方,它将具有正 rho 和小于 180 的角度。如果它高于原点,则不取大于 180 的角度,而取小于 180 的角度,而 rho 取负值。任何垂直线都将具有 0 度而水平线将具有 90 度。
现在让我们看看霍夫变换如何对线工作。任何线都可以用这两个术语\(((\rho, \theta))\)表示。因此,它首先创建一个 2D 数组或累加器(以保存两个参数的值),并最初将其设置为 0。行表示\(\rho\),列表示\(\theta\)。数组的大小取决于您需要的精度。假设您希望角度精度为 1 度,您将需要 180 列。对于\(\rho\),可能的最大距离是图像的对角线长度。因此,以一个像素的精度,行数可以是图像的对角线长度。
考虑一个 100x100 的图像,其中有一条水平线位于中间。取线的第一个点。您知道它的 (x,y) 值。现在在线程方程中,设置值\(\theta = 0,1,2,....,180\)并检查您获得的\(\rho\)。对于每个\(((\rho, \theta))\)对,您在相应的\(((\rho, \theta))\)单元中将其累加器中的值增加 1。因此,现在累加器中,单元 (50,90) = 1 以及一些其他单元。
现在获取该直线上的第二个点,并执行上述操作。对对应于你获得的(\((\rho, \theta)\))的值所在的单元格中的值进行增量。这次,单元格为 (50,90) = 2。实际上,你是在对(\((\rho, \theta)\))值进行投票。你对直线上的每个点连续执行此过程。在每个点,单元格 (50,90) 都将获得增量或选票,其它单元格可能获得增量或选票也可能没有。 таким образом, 最后单元格 (50,90) 将获得最大选票。所以如果你搜索累加器找出最大选票,你将获得值 (50,90),表示在距离原点 50 的位置且角度为 90 度的图像中存在一条直线。以下动画对此的展示十分清晰(图片由 Amos Storkey 友情提供)
这是霍夫变换线工作原理。此原理很简单。下图为显示了累加器的图片。某些位置上的亮点表明它们是图片中可能存在的直线的参数。(图片由 Wikipedia 友情提供)
以上所有解释均封装在 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 | 对于多尺度霍夫变换,它是距离分辨率 ρ 的除数。粗糙累加器距离分辨率是 ρ,而精确累加器分辨率 ρ/srn。如果 srn=0 和 stn=0,则使用经典霍夫变换。否则,这两个参数应为正数。 |
stn | 对于多尺度霍夫变换,它是距离分辨率 θ 的除数。 |
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 类型)。每条线都由一个 4 元素向量 (x1,y1,x2,y2) 表示,其中 (x1,y1) 和 (x2,y2) 是每条检测到的线段的结束点。 |
rho | 累加器距离分辨率(像素)。 |
theta | 累加器角度分辨率(弧度)。 |
threshold | 累加器阈值参数。只会返回有足够选票的直线。 |
minLineLength | 最小线段长度。短于该长度的线段会被拒绝。 |
maxLineGap | 同一条直线上两个点之间允许的最大间隙,以将它们连接起来。 |