【问题标题】:Extract text with strikethrough from image从图像中提取带有删除线的文本
【发布时间】:2020-07-01 04:13:55
【问题描述】:

这是一个示例图片 ->

我想提取具有删除线的文本装饰/样式的文本。 所以对于上面的图片我想提取-de location

我该怎么做?

这是我目前使用 OpenCV 和 python 所获得的:

import cv2
import numpy as np
import matplotlib.pyplot as plt
im = cv2.imread(<image>)
kernel = np.ones((1,44), np.uint8)
morphed = cv2.morphologyEx(im, cv2.MORPH_CLOSE, kernel)
plt.imshow(morphed)

这给了我水平线->

我是图像处理的新手,因此很难仅隔离带有删除线的文本。

奖励 -> 除了删除线文本,我还想提取相邻文本,以便我可以正确地设置/标记删除线文本信息以及其他文本。

更新 1: 根据第一个答案,我做了以下事情:-

import cv2
# Load image, convert to grayscale, Otsu's threshold
image = cv2.imread('image.png')
result = image.copy()
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + 
cv2.THRESH_OTSU)[1]
# Detect horizontal lines
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(40,1))
detect_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, 
horizontal_kernel, iterations=10)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, 
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(result, [c], -1, (36,255,12), 2)
plt.imshow(result)

我能够得到这张图片 -

我尝试使用水平内核的值,但没有运气。

更新 2: 我进一步修改了上面的 sn-p 并得到了这个 -

import cv2
import numpy as np
import matplotlib.pyplot as plt
# Load image, convert to grayscale, Otsu's threshold
result = image.copy()
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

kernel = np.ones((4,2),np.uint8)
erosion = cv2.erode(thresh,kernel,iterations = 1)
dilation = cv2.dilate(thresh,kernel,iterations = 1)

trans = dilation
# plt.imshow(erosion)

# Detect horizontal lines
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (8,1))
detect_horizontal = cv2.morphologyEx(trans, cv2.MORPH_OPEN, horizontal_kernel, iterations=10)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(result, [c], -1, (36,255,12), 2)
plt.imshow(result)

我能够得到这张图片 - 这个解决方案也适用于我的其他图像类型 -

这不是一个 100% 准确的解决方案(无法获得 de 删除线文本),但我喜欢目前的性能。

现在,我正在努力研究如何检查相邻像素是黑色还是白色以隔离删除线。

【问题讨论】:

    标签: python opencv image-processing underline strikethrough


    【解决方案1】:

    实现这一目标的一种方法是:

    1. 二值化图像 (https://docs.opencv.org/master/d7/d4d/tutorial_py_thresholding.html)
    2. 查找水平线 (Horizontal Line detection with OpenCV)
    3. 对于每一行,检查顶部和底部像素是否为白色
    4. 如果有非白色的顶部和底部像素,则该区域对应于删除线
    5. 对图像做一个连通分量 (connected component labeling in python)
    6. 检查与先前检测到的行对应的标签,并屏蔽该标签以获取删除线文本。

    【讨论】:

    • 感谢您的回答。我一直坚持到第 2 步。@nathancy 的回答对第 2 步的我来说是部分有用的。我用目前为止的内容更新了我的问题。
    【解决方案2】:

    您可以使用删除线属性,例如厚度。删除线的粗细小于下划线。可以通过形态学进行选择,通过形态学重构恢复连通分量。

    import cv2
    img = cv2.imread('juFpe.png', cv2.IMREAD_GRAYSCALE)
    thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV )[1]
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(1,5))
    kernel2=cv2.getStructuringElement(cv2.MORPH_RECT,(8,8))
    detect_thin = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
    detect_thin = cv2.morphologyEx(detect_thin, cv2.MORPH_DILATE, kernel2)
    marker=cv2.compare(detect_thin, thresh,cv2.CMP_LT) # thin lines
    while True: #morphological reconstruction
        tmp=marker.copy()
        marker=cv2.dilate(marker, kernel2)
        marker=cv2.min(thresh, marker)
        difference = cv2.subtract(marker, tmp)
        if cv2.countNonZero(difference) == 0:
            break
    
    cv2.imwrite('lines.png', marker)
    

    结果:

    【讨论】:

    • 感谢您的回答。我正在尝试使用您的解决方案,但到目前为止,我的其他图像都失败了。这是我的另一个图像样本供您尝试 - imgur.com/bVKo712
    猜你喜欢
    • 2018-08-25
    • 2022-01-18
    • 2020-02-20
    • 2019-04-01
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多