首页 > 解决方案 > 在不应用高斯模糊的情况下检测 Python OpenCV 中的线条

问题描述

我正在检测无噪音、以编程方式生成的 png 文件中的线条。我通常会使用霍夫线,这需要我首先从精明检测中提供边缘,但精明检测的第一步是应用高斯模糊来消除噪声。有没有一种方法可以在我的原始图像上进行边缘检测而不会故意模糊它?我怀疑这会比先去毛刺产生更好的结果,因为线条已经非常干净且对比度很高。

这是一个使用精明检测和图像的简单示例。每组中的线从 5 像素宽开始,然后下一行是 4,然后是 3、2 和 1。如您所见,canny 检测不能完美工作(2 像素线看起来小于 1 像素那些):

原图:

在此处输入图像描述

边缘(canny 检测的结果):

在此处输入图像描述

示例代码:


import cv2
import numpy as np
import matplotlib.pylab as plot

# img = cv2.imread("8px_and_2px_lines.png")
img = cv2.imread("5-1px_lines.png")

crop_size = 520
img = img[100:crop_size, 100:crop_size]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imwrite("5-1px_lines_cropped.png", img)
cv2.imshow("start", img)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
cv2.imshow("canny", edges)
cv2.imwrite("5-1px_lines_cropped_canny.png", edges)
# plot.imshow(edges, cmap="gray")
# plot.show()

lines = cv2.HoughLines(edges, 1, np.pi / 180, 200)
line_length = 3000
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 + line_length * (-b))
    y1 = int(y0 + line_length * (a))
    x2 = int(x0 - line_length * (-b))
    y2 = int(y0 - line_length * (a))
    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv2.imshow("lines", img)
cv2.waitKey()

关于如何对这些图像进行更好的线检测有什么想法吗?我认为精明检测器内置的高斯模糊使线条更难检测。

标签: pythonopencvedge-detection

解决方案


一种简单的方法是简单地设置阈值,将线条反转为白色,然后进行骨架化。这是 Python/OpenCV/Skimage 的代码

输入:

在此处输入图像描述

import cv2
import numpy as np
import skimage.morphology

img = cv2.imread("lines_horizontal.png")
ht, wd = img.shape[:2]

# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# create a binary thresholded image
thresh = cv2.threshold(gray, 0, 1, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

# invert so lines are white
thresh = 1 - thresh

# apply skeletonization
skeleton = skimage.morphology.skeletonize(thresh)
skeleton = (255*skeleton).clip(0,255).astype(np.uint8)

# save result
cv2.imwrite("lines_horizontal_skeleton.png", skeleton)

# show results
cv2.imshow("skeleton", skeleton)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

在此处输入图像描述

请注意,端点处的骨架化在末端会出现一些失真。

另请注意,OpenCV opencv-contrib-python 具有类似于骨架化的细化方法。


推荐阅读