首页 > 解决方案 > 如何防止 HoughLines 多次检测某些行

问题描述

因此,我正在编写这段代码以从图像中的某些图形中提取数据。这些图像都是从一本书中扫描出来的。由于我们在这里讨论的是 100 多张图像,因此我当然想自动化该过程。我的第一步是确保所有图像都对齐。因为这本书的页面是手工扫描的,所以扫描件彼此之间都有轻微的偏移或旋转。幸运的是,图像上有一些虚线,可以用作对齐它们的参考点。之后,我可以通过在这些虚线上对图像进行切片,将图像分成更小的子图像。这样,所有扫描图像的所有子图像都是相同的。

所以,第一步当然是检测这些虚线。我的策略可以用 4 个步骤来描述:

现在可能会出现几个问题。有时 HoughLines 会检测到错误的线条(例如书中下一页的折叠),但这可以通过在右侧稍微裁剪图像来解决(总是欢迎更好的解决方案)。第二个(也是最大的)问题是 HoughLines 有时倾向于将单行识别为多行。我认为这与 Canny Edge Detection 对边​​缘过于粗糙或模糊有关,因此 HoughLines 实际上会看到多条线。有没有一种方法可以“平滑” Canny 的输出,以便 HoughLines 准确检测每条线一次?

在这个特定图像的情况下,中间的垂直虚线没有被识别,而书中下一页的折叠却被识别。此外,垂直虚线被识别为多条线。(左源图像,检测到中间边缘,检测到右线)

在此处输入图像描述

# load image
img_large = cv2.imread("image.png")
# resize for ease of use
img_ori = cv2.resize(img_large, None, fx=0.2, fy=0.2, interpolation=cv2.INTER_CUBIC)
# create grayscale
img = cv2.cvtColor(img_ori, cv2.COLOR_BGR2GRAY)
# create mask for image size
mask = np.zeros((img.shape[:2]), dtype=np.uint8)
# do a morphologic close to merge dotted line
kernel = np.ones((8, 8))
res = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# detect edges for houghlines
edges = cv2.Canny(res, 50, 50)
# detect lines
lines = cv2.HoughLines(edges, 1, np.pi/180, 200)
# draw detected lines
for line in lines:
    rho, theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*a)
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*a)
    cv2.line(mask, (x1, y1), (x2, y2), 255, 2)
    cv2.line(img, (x1, y1), (x2, y2), 127, 2)

标签: pythonopencvhough-transformcanny-operatorhoughlines

解决方案


在您的脚本中,像素箱和旋转箱对于您设置的阈值来说太精细了:

lines = cv2.HoughLines(edges, 1, np.pi/180, 200)

因此,您可以调整阈值参数 (200) 以仅获得一条线,或调整 rho (1) 和 theta (np.pi/180) 参数,或调整所有这些。您可以从图像中选择一组仅包含一条水平线或垂直线的图像。然后进行网格搜索以查找在您的一组测试图像中仅检测一条线的参数。


推荐阅读