如何从图像中提取垂直和水平线

时间:2020-08-13 12:26:53

标签: python opencv

任务:

我有一组图像,每个图像看起来像这样:

enter image description here

我想从这张图片中提取所有水平线和所有垂直线。

所需结果:

enter image description here

enter image description here

当前方法:

import cv2


image = cv2.imread('img.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3, 3), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (20, 1))
horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=1)

结果如下:

enter image description here

问题:

很明显,当前内核太窄,无法绕过左侧的垂直粗线。这条线是41像素粗,因此内核(42,1)可以正常工作,但是我丢失了比41像素短的真实水平线:

enter image description here

有没有完美的技术可以解决这个问题?

2 个答案:

答案 0 :(得分:0)

这个想法是通过骨架化将所有这些行调整为相同的“大小” 应用形态学过滤器并使用较小的过滤器

image = cv2.imread('Your_ImagePath' , cv2.IMREAD_COLOR)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

thresh = skeletonize(thresh)
cv2.imshow("Skelton",thresh)
cv2.waitKey()

horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 1))
horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, 
iterations=1)

cv2.imshow("Horizontal Lines" , horizontal)
v2.waitKey()

输出图像:

enter image description here

注意:skeletonize.py的骨骼化代码

答案 1 :(得分:0)

我会考虑做一个“形态学开口” ,它具有一个高而细的结构元素(即一条垂直线,高15像素,宽1像素),以找到垂直条和水平线长15像素,高1像素以找到水平线。

您可以使用 OpenCV 进行相同的操作。但我只是在终端机中使用 ImageMagick 来完成此操作,因为我可以更快地这样做!这是垂直工作的命令-尝试改变15以获得不同的结果:

magick shapes.png -morphology open rectangle:1x15 result.png

这是一个动画,显示结果如何随着15(行的长度)的变化而变化:

enter image description here

这是将结构元素设为水平线时的外观:

magick shapes.png -morphology open rectangle:15x1 result.png

enter image description here

如果您不熟悉形态学,那么Anthony Thyssen here会提供出色的描述。请注意,可以用 ImageMagick 对其进行解释,但是这些原理同样适用于Python OpenCV -请参见here