我正在尝试删除此图像中的水平线和垂直线,以便拥有更多不同的文本区域。
我正在使用下面的代码,它遵循 guide
image = cv2.imread('image.jpg')
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(
blurred, 255,
cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV,
25,
15
)
# Create the images that will use to extract the horizontal and vertical lines
horizontal = np.copy(thresh)
vertical = np.copy(thresh)
# Specify size on horizontal axis
cols = horizontal.shape[1]
horizontal_size = math.ceil(cols / 20)
# Create structure element for extracting horizontal lines through morphology operations
horizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (horizontal_size, 1))
# Apply morphology operations
horizontal = cv2.erode(horizontal, horizontalStructure)
horizontal = cv2.dilate(horizontal, horizontalStructure)
# Show extracted horizontal lines
cv2.imwrite("horizontal.jpg", horizontal)
# Specify size on vertical axis
rows = vertical.shape[0]
verticalsize = math.ceil(rows / 20)
# Create structure element for extracting vertical lines through morphology operations
verticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1, verticalsize))
# Apply morphology operations
vertical = cv2.erode(vertical, verticalStructure)
vertical = cv2.dilate(vertical, verticalStructure)
在此之后,我知道我需要隔离线条并用白线掩盖原始图像,但是我不确定如何继续。
有人有什么建议吗?
最佳答案
Jeru's answer 已经给了你你想要的。但我想添加一个可能比你目前所拥有的更通用的替代方案。
您正在将彩色图像转换为灰度值,然后应用自适应阈值以尝试查找线条。您对其进行过滤以仅获得长的水平和垂直线,然后使用该蒙版在这些位置将原始图像绘制为白色。
在这里,我们查找所有线条,并将它们从图像中删除,然后用周围的颜色绘制它们。这个过程根本不涉及阈值,所有形态学操作都应用于彩色图像的 channel 。
理想情况下,我们会使用颜色形态,但这种实现很少见。数学形态学是基于最大值和最小值运算的,颜色三元组(即向量)的最大值或最小值没有很好的定义。
因此,我们将以下过程分别应用于三个颜色 channel 中的每一个。这应该会产生对这个应用程序来说足够好的结果:
input
RGB图像,提取第一个 channel 。这是一张灰度图像。我们将此图像称为 channel
。 channel
的小结构元素 (SE) 的闭合和 channel
之间的区别(闭合是膨胀,然后是具有相同 SE 的腐 eclipse ,你'也在使用它来查找行)。我们将此输出称为 thin
。 thin = closing(channel)-channel
。此步骤类似于您的本地阈值,但未应用实际阈值。由此产生的强度表明线条的深浅程度。背景。如果将 thin
添加到 channel
,您将填充这些薄结构。这里 SE 的大小决定了什么被认为是“薄”的。 thin
应用具有长水平 SE 的开口,对 thin
应用具有长垂直 SE 的开口,并取两个结果中的最大值。我们称之为 lines
。请注意,这与您用于生成 horizontal
和 vertical
的过程相同。我们没有按照 Jeru 的建议将它们加在一起,而是取最大值。这使得输出强度仍然匹配 channel
中的对比度。 (用数学形态学的说法,开口的上界是一个开口)。这里 SE 的长度决定了什么长度足以成为一条线。 lines
添加到 channel
即可。将结果写入输出图像的第一个 channel 。 使用 PyDIP 这是一个非常简单的脚本:
import PyDIP as dip
input = dip.ImageReadTIFF('/home/cris/tmp/T4tbM.tif')
output = input.Copy()
for ii in range(0,3):
channel = output.TensorElement(ii)
thin = dip.Closing(channel, dip.SE(5, 'rectangular')) - channel
vertical = dip.Opening(thin, dip.SE([100,1], 'rectangular'))
horizontal = dip.Opening(thin, dip.SE([1,100], 'rectangular'))
lines = dip.Supremum(vertical,horizontal)
channel += lines # overwrites output image
编辑:
当增加第一个 SE 的大小时,上面设置为 5,大到足以移除示例图像中间的较粗的灰色条,导致包含反转文本“POWERLIFTING”的部分 block 留在
thin
.为了过滤掉这些部分,我们可以改变
thin
的定义如下:notthin = dip.Closing(channel, dip.SE(11, 'rectangular'), ["add max"]))
notthin = dip.MorphologicalReconstruction(notthin, channel, 1, "erosion")
thin = notthin - channel
也就是说,我们用
thin=closing(channel)-channel
代替 thin=reconstruct(closing(channel))-channel
。重建只是扩展选定的(不是薄的)结构,以便选择结构的一部分,现在选择完整的结构。现在在 thin
中的唯一内容是未连接到较厚结构的线。我还添加了
"add max"
作为边界条件——这会导致关闭以白色扩展图像外部的区域,因此将图像边缘的线条视为线条。关于python - 使用 Open CV 屏蔽水平线和垂直线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51380692/