Python 中使用 OpenCV 进行线条检测?
在这篇文章中,我们将学习如何使用一种称为霍夫变换的技术来检测图像中的线条。
霍夫变换?
霍夫变换是一种特征提取方法,用于检测任何简单的形状,只要您可以用数学形式表示该形状。即使形状稍微断裂或扭曲,它也能设法检测到形状。我们将了解它如何用于检测线条。
“简单”形状是指可以用少数几个参数表示的形状。例如,一条直线只需要两个参数(斜率、截距)就可以表示,而一个圆需要三个参数——圆心的坐标和半径(x、y、r)。
使用霍夫变换从图像中检测线条
一条直线可以用方程表示——或者可以用参数形式表示为,其中(ρ)是原点到直线的垂直距离,而ϴ是这条垂直线与水平轴形成的角度,以逆时针方向测量(OpenCV 使用这种表示方法)。请查看下图
因此,如果直线穿过原点下方,则其ρ为正,角度小于180。如果它穿过原点上方,则不采用大于180的角度,而是采用小于180的角度,并将ρ取为负值。任何垂直线都将具有0度,而水平线将具有90度。
累加器
任何直线都可以用这两个参数(ρ,ϴ)表示。因此,它首先创建一个二维数组或累加器(用于保存这两个参数的值),并且最初将其设置为0。其中行表示ρ,列表示ϴ。数组的大小取决于我们所需的精度,例如,如果我们需要角度精度为1度,则需要180列,而ρ是可能的最大距离,即图像的对角线长度,ρ是可能的最大距离,即图像的对角线长度。因此,采用1像素精度,行数可以是图像的对角线长度。
假设我们有一个100*100的图像,中间有一条水平线。取直线的第一个点,我们知道它的(x,y)值。现在,在方程中,将ϴ设置为0、1、2、3…180,并检查得到的ρ值。对于每个(ρ,ϴ)对,在累加器中相应(ρ,ϴ)单元格的值加1。因此,现在在累加器中,单元格(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()
结果
以及检测到的线条−