【发布时间】:2021-10-10 00:33:06
【问题描述】:
我正在检测以编程方式生成的无噪音 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()
关于如何更好地对这些图像进行线检测有什么想法吗?我认为 Canny 检测器内置的高斯模糊使线条更难检测。
【问题讨论】:
-
您的结果没有问题。每条粗线的两侧都有一条 Canny 边缘和 Hough 线。
-
@fmw42 让我困惑的是为什么两条像素宽度的线只有一条边,而一条像素线仍然有两条
-
有趣的问题!查看 Canny 边缘图像,看看它显示的是一个还是两个
-
@fmw42 我会更新我的答案,我提供的图像实际上是精明的图像。
-
我相信答案与梯度算子有关,以及它在边缘移动时如何与边缘重叠。例如,取一个垂直 (1,0,-1) 内核,并在值为 0 的背景上,在值为 1 的 1 行边缘上一次垂直移动一个像素,并进行相关乘法和加法。您将看到 -1、0 和 1 的结果有 3 个值。任何非零值都成为边。所以你有 2 个边缘被黑色 0 空间隔开。使用 2 像素边缘,您可以按顺序获得 5 个非零值,没有空格。这被非最大抑制缩小到一条线。
标签: python opencv edge-detection