python - 使用 Open CV 屏蔽水平线和垂直线

标签 python python-3.x opencv computer-vision

我正在尝试删除此图像中的水平线和垂直线,以便拥有更多不同的文本区域。

enter image description here

我正在使用下面的代码,它遵循 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 中的每一个。这应该会产生对这个应用程序来说足够好的结果:

  • 提取红色 channel : input RGB图像,提取第一个 channel 。这是一张灰度图像。我们将此图像称为 channel
  • 应用顶帽过滤器来检测薄结构: 应用到 channel 的小结构元素 (SE) 的闭合和 channel 之间的区别(闭合是膨胀,然后是具有相同 SE 的腐 eclipse ,你'也在使用它来查找行)。我们将此输出称为 thinthin = closing(channel)-channel 。此步骤类似于您的本地阈值,但未应用实际阈值。由此产生的强度表明线条的深浅程度。背景。如果将 thin 添加到 channel ,您将填充这些薄结构。这里 SE 的大小决定了什么被认为是“薄”的。
  • 过滤掉短线,只保留长线: thin 应用具有长水平 SE 的开口,对 thin 应用具有长垂直 SE 的开口,并取两个结果中的最大值。我们称之为 lines 。请注意,这与您用于生成 horizontalvertical 的过程相同。我们没有按照 Jeru 的建议将它们加在一起,而是取最大值。这使得输出强度仍然匹配 channel 中的对比度。 (用数学形态学的说法,开口的上界是一个开口)。这里 SE 的长度决定了什么长度足以成为一条线。
  • 填写原始图像 channel 中的行: 现在只需将 lines 添加到 channel 即可。将结果写入输出图像的第一个 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" 作为边界条件——这会导致关闭以白色扩展图像外部的区域,因此将图像边缘的线条视为线条。

    output

    关于python - 使用 Open CV 屏蔽水平线和垂直线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51380692/

    相关文章:

    Python-3.x:在用户定义的类之间传递实时数据

    python - QStyledItemDelegate 在QTableView中显示QComboBox

    image - 如何将RGB图像转换为单 channel 灰度图像,并使用python保存它?

    c++ - OpenCV:断言失败(src.checkVector(2,CV_32F)

    opencv - 如何结合运动和外观描述符

    python - AWS BOTO3 连接到 MS SQL 数据库时出错

    python - 从 csv 文件导入数据 - 为什么他们打印不同的东西?

    python - "is"运算符对整数的行为异常

    python - 如何在 pandas 数据框中复制和修改日期行 Python

    python - python 将 RGB 转换为灰度