点击下方卡片,关注“机器视觉与深度学习”
视觉/图像重磅干货,第一时间送达!
检测线可用于各种类型的应用,例如机器人导航、无人机导航、运动分析和交通管理。本文我们将使用HoughLinesP函数来检测线条并从线条中提取角度。
检测线 想象一下,您想要创建一架无人机或一辆可以沿着路线行驶的简单汽车。事实上,创造和使用它似乎很有趣。或者您可能想跟踪道路上的线路并根据车道对汽车进行分类。对于这些类型的程序,您需要检测线条,并且可能需要根据您的目的提取角度。OpenCV 提供了多种检测直线和提取角度的函数:
HoughLines()HoughLinesP()
选择合适的功能
HoughLinesP可以检测碎片或不连续线(例如图像中的虚线或线段)时更有效。它提供有关检测到的线路的更多详细信息。 HoughLines更适合检测完整、连续的线条。当检测图像中长的、不间断的线条时,它非常有用。 我们需要一种可以检测各种形状的线条的算法,而不仅仅是直线。例如,如果道路向右成 45 度角,则 HoughLines() 函数在这种情况下可能无效。因此,我将使用HoughLinesP()函数HoughLinesP() 函数如何工作? 我不会深入研究该HoughLinesP()函数的数学细节,因为 Google 或 Youtube 等平台上有很多可用的资源。下面简单解释一下该HoughLinesP()函数的工作原理: OpenCV 中的函数HoughLinesP使用概率霍夫变换来检测图像中的线段。
从边缘检测开始提取潜在的线点,然后进行投票过程来识别经过这些点的线,在参数空间中累积投票。参数空间是霍夫变换累积投票以检测图像中的线条的地方,每个维度代表被检测模型的一个参数,例如线条的斜率和截距。在阈值化选择突出线之后,它提取由端点表示的线段,提供有关其位置和长度的详细信息。
这种方法可有效检测碎片或不连续的线,例如虚线或线段,与传统方法(如HoughLines.HoughLinesP() 函数的参数HoughLinesP(image, rho, theta, threshold,minLineLength,maxLineGap)
image:8 位、单通道输入图像。rho:累加器的距离分辨率(以像素为单位)。(1在大多数情况下是有效的)theta:累加器的角度分辨率(以弧度为单位)。(np.pi/180)阈值:简单的阈值。较高的阈值会导致线条更少但更准确,而较低的阈值会产生相反的效果。设置此参数的最佳方法是尝试不同的值。这完全取决于您的目的。minLineLength:最小行长度。maxLineGap:同一直线上的点之间允许的最大间隙以链接它们。
选择这些参数(Threshold、minLineLength 和 maxLineGap)的最佳方法是尝试不同的值组合。这些参数没有通用的最佳值;它们取决于图像的具体特征和期望的结果。检测直线时如何使用提取的角度? 想象一下算法从直线中提取出 67 度角。等式为:direction_x = cos(extracted_angle=67) → velocity_x=1*direction_x
direction_y = sin(extracted_angle=67) → velocity_y=1*direction_y
步骤/代码 1. 读取图像并将其转换为灰度 2. 使用 Canny 边缘检测器提取边缘。 3. 对Canny边缘检测后得到的图像应用HoughLinesP函数。 4. 获取 HoughLinesP 函数的输出,对其进行迭代,绘制线条,并使用简单的公式提取角度。Canny 边缘检测 Canny 边缘检测器创建一个二值图像,这在使用 HoughLinesP 函数之前是必不可少的。或者,可以使用其他过滤器或检测器。 Canny 边缘检测器有助于识别图像中的边缘
检测直线并计算角度代码:# read imageimage = cv2.imread("resources/blog1.png")# conert image to graygray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# extract edges with canny edge detectoredges = cv2.Canny(gray, 50, 150, apertureSize=3)
# apply HoughLinesP# cv2.HoughLinesP() returns an array of lines detected in the image.lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=75, minLineLength=100, maxLineGap=20)
if lines is not None: for i, line in enumerate(lines): x1, y1, x2, y2 = line[0] dy = (y2 - y1) dx = (x2 - x1)# convert radian to degree and extract angle angle = np.rad2deg(np.arctan2(dy, dx))# Since the Y-axis increases downwards(in opencv), invert the angle. angle = 180 - angle if angle > 0 else -angle# different color for every line color = tuple(np.random.randint(0, 255, 3).tolist())# detected line cv2.line(rgb_image, (x1, y1), (x2, y2), color, 3)# draw shape to starting and finishing points of lines cv2.putText(rgb_image, '>', (x1, y1), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,255), 3) cv2.putText(rgb_image, '<', (x2, y2), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,255), 3)# angle cv2.putText(rgb_image, str(round(angle, 1)),(x1 , int((y1+y2)/2)), cv2.FONT_HERSHEY_SIMPLEX, 1, color, 3)
plt.imshow(rgb_image)
—THE END—
觉得有用,麻烦给个赞和在看
|