如何在Python/OpenCV中将图像分割成清晰的段落?

4

TL;DR: 如何在图片上选择一个段落,使其不包含相邻的(顶部和底部)段落?

我有一组扫描图像,它们都是单列文本,例如这个。这些图像都是黑白的,已经旋转、降噪和去除了白色空间。

我想要做的是将每个图像分成段落。我的初始想法是测量每行的平均亮度,以找到文本行之间的空格,并尝试选择从该行开始匹配缩进并测量该矩形的亮度的矩形。但这似乎有点麻烦。

此外,这些行有时倾斜(两端的垂直差异最多约为10像素),因此有时会出现行重叠。因此,我想选择一个段落中的所有字母,并使用它们来绘制一块文本块,使用这种方法得到了这个结果,但我不确定如何进一步进行。选择每个字母矩形,从左侧开始n像素,并尝试包含每个起始矩形不少于第一个矩形x - 偏移量的矩形?但接下来呢?

1个回答

6

这是针对所附段落结构的特定解决方案。我不确定您是否需要更通用的解决方案,但这可能需要额外的工作:

import cv2
import numpy as np
import matplotlib.pyplot as plt

image = cv2.imread('paragraphs.png', 0)

# find lines by horizontally blurring the image and thresholding
blur = cv2.blur(image, (91,9))
b_mean = np.mean(blur, axis=1)/256

# hist, bin_edges = np.histogram(b_mean, bins=100)
# threshold = bin_edges[66]
threshold = np.percentile(b_mean, 66)
t = b_mean > threshold
'''
get the image row numbers that has text (non zero)
a text line is a consecutive group of image rows that 
are above the threshold and are defined by the first and 
last row numbers
'''
tix = np.where(1-t)
tix = tix[0]
lines = []
start_ix = tix[0]
for ix in range(1, tix.shape[0]-1):
    if tix[ix] == tix[ix-1] + 1:
        continue
    # identified gap between lines, close previous line and start a new one
    end_ix = tix[ix-1]
    lines.append([start_ix, end_ix])
    start_ix = tix[ix]
end_ix = tix[-1]
lines.append([start_ix, end_ix])

l_starts = []
for line in lines:
    center_y = int((line[0] + line[1]) / 2)
    xx = 500
    for x in range(0,500):
        col = image[line[0]:line[1], x]
        if np.min(col) < 64:
            xx = x
            break
    l_starts.append(xx)

median_ls = np.median(l_starts)

paragraphs = []
p_start = lines[0][0]

for ix in range(1, len(lines)):
    if l_starts[ix] > median_ls * 2:
        p_end = lines[ix][0] - 10
        paragraphs.append([p_start, p_end])
        p_start = lines[ix][0]

p_img = np.array(image)
n_cols = p_img.shape[1]
for paragraph in paragraphs:
    cv2.rectangle(p_img, (5, paragraph[0]), (n_cols - 5, paragraph[1]), (128, 128, 0), 5)

cv2.imwrite('paragraphs_out.png', p_img)

输入/输出

enter image description here


谢谢,这对大多数图像都很有效 - 但也有例外情况:http://imgur.com/a/z0836。所以确实,我需要进行一些调整,但没关系 :) - MrVocabulary
你能否向我解释一下代码的前几行是做什么的?我不太理解你在直方图方面所做的事情。 - MrVocabulary
1
好的,我会添加注释。直方图是为了可视化而设计的,但被留在那里了。你可以使用百分位数代替。 - Rosa Gronchi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接