使用 OpenCV 在 Python 中检测直线?
在这篇文章中,我们将学习如何借助一种称为霍夫变换的技术检测图像中的直线。
霍夫变换?
霍夫变换是一种特征提取方法,用于检测任何简单形状,前提是您可以用数学形式表示该形状。即使形状有一点损坏或扭曲,它也能以某种方式检测出形状。我们将了解它如何对直线起作用。
"简单"形状是仅用几个参数即可表示的形状。例如,一条线只能用两个参数(斜率、截距)表示,而一个圆有三个参数——中心坐标和半径 (x,y, r)。
使用霍夫变换从图像中检测线条
一条线可以用一个方程表示 - 或者以参数形式表示为,其中 (ρ) 是从原点到线的垂直距离,ϴ 是这条垂直线和水平轴逆时针测量形成的角度(此表示法在 OpenCV 中使用)。查看下图
因此,如果线从原点下方经过,则其 rho 为正,角度小于 180。如果线从原点上方经过,则角度将小于 180,而不是大于 180,并且 rho 为负。任何垂直线都将为 0 度,水平线将为 90 度。
累加器
任何线都可以用这两个项 (ρ,ϴ) 表示。因此,它首先创建一个 2D 数组或累加器(用于保存两个参数的值),并将其初始设置为 0。其中行表示 ρ,列表示 ϴ。数组的大小取决于我们所需的精度,例如,如果我们需要角度精度为 1 度,则需要 180 列和 ρ,即可能的最大距离是图像的对角线长度,而 ρ 是可能的最大距离是图像的对角线长度。因此,取一个像素的精度和行数可以是图像的对角线长度。
假设我们有一张 100*100 的图像,中间有一条水平线。取该线的第一个点,我们知道它的 (x,y) 值。现在在等式中,将值 ϴ=0,1,2,3…hellip;180 放入并检查您得到的 ρ 值。对于每个 (ρ,ϴ) 对,其对应的 (ρ,ϴ) 单元格中的累加器的值加一。因此,现在在累加器中,单元格 (50,90) = 1,以及其他一些单元格。现在取线上的第二个点。重复与第一个点相同的步骤。增加与 (ρ,ϴ) 对应的单元格中的值。这次,单元格 (50,90) = 2。因此,我们实际上是在投票 (ρ,ϴ) 值。我们对线上的每个点继续此过程。在每个点,单元格 (50,90) 将增加或投票,而其他单元格可能不会被投票。这样,最后,单元格 (50,90) 将获得最高票数。因此,如果您在累加器中搜索最大票数,则会得到值 (50,90),这表示此图像中有一条线,距离原点 50 度,角度为 90 度。这就是霍夫变换对线的工作原理。
OpenCV 中的霍夫变换
上面解释的所有内容都封装在 OpenCV 函数 cv2.HoughLines() 中。它只是返回一个 (ρ,ϴ) 值的数组,其中 ρ 以像素为单位,ϴ 以弧度为单位。
下面是使用 openCV 和霍夫线变换进行线检测的程序。
下面是停车场的实际图像,我们将使用霍夫线变换和 OpenCV 库对此图像进行线检测。
示例
import cv2 import numpy as np img = cv2.imread("parkingLot1.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 75, 150) lines = cv2.HoughLinesP(edges, 1, np.pi/180, 30, maxLineGap=250) for line in lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (0, 0, 128), 1) cv2.imshow("linesEdges", edges) cv2.imshow("linesDetected", img) cv2.waitKey(0) cv2.destroyAllWindows()
结果
并且检测到线条−