提高图像中字母的质量

Improve the quality of the letters in a image

我正在处理带有文字的图像。问题是这些图像是收据,经过大量转换后,文本质量下降。 我正在使用 python 和 opencv。 我正在尝试使用来自文档 Morphological Transformations 的大量形态转换组合,但我没有得到令人满意的结果。

我现在正在做这个(我会评论我尝试过的,只是让取消评论我正在使用的):

kernel = np.ones((2, 2), np.uint8)
# opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
# dilation = cv2.dilate(opening, kernel, iterations=1)
# kernel = np.ones((3, 3), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)
# gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
#
img = erosion.copy()

有了这个,来自这张原始图片:

我明白了:

如您所见,它好一点了。但还是太糟糕了。 OCR(tesseract)不能很好地识别这里的字符。我已经训练过,但正如您所注意到的,每个 "e" 都是不同的,依此类推。

我得到了很好的结果,但我认为,如果我解决了这个问题,它们会更好。

也许我可以做另一件事,或者使用更好的形态变换组合。如果有其他工具(PIL、imagemagick 等)我可以使用,我可以使用它。

这是完整的图像,因此您可以看到它的外观:

正如我所说,它还不错,但是 "optimization" 的字母再多一点就完美了。

你有没有考虑相邻的像素并加上它们的总和。

例如:

n = numpy.zeros((3,3))
s = numpy.zeros((3,3))
w = numpy.zeros((3,3))
e = numpy.zeros((3,3))

n[0][1] = 1
s[2][1] = 1
w[1][0] = 1
e[1][2] = 1

img_n = cv2.erode(img, n, iterations=1)
img_s = cv2.erode(img, s, iterations=1)
img_w = cv2.erode(img, w, iterations=1)
img_e = cv2.erode(img, e, iterations=1)

result = img_n + img_s + img_w + img_e + img

此外,您可以使用 numpy 或 cv2 来添加数组。

根据我的经验,腐蚀会损害 OCR 质量。如果您有灰度图像(不是二进制),您可以使用更好的二值化算法。我使用 SAUVOLA 算法进行二值化。如果你只有二值图像,你能做的最好的事情就是去除噪声(去除所有小点)。

我发现 Ramer–Douglas–Peucker Algorithm 我正尝试在 Haskell 中为闭合多边形实现它。也许它可以解决一些问题。

在这个主题上工作了多年之后,我现在可以告诉我,我想做的事情需要付出很大的努力,它很慢,而且从来没有像我预期的那样奏效。字符中像素的不规则性总是不可预测的,这就是为什么 "easy algorithms" 不起作用。

问:那么不可能有一个像样的OCR,可以读取损坏的字符?

答:不,并非不可能。但它需要 "a bit" 不仅仅是使用侵蚀、形态闭合或类似的东西。

那怎么办?神经网络 :)

这里有两篇很棒的论文,对我帮助很大:

Can we build language-independent OCR using LSTM networks?

Reading Scene Text in Deep Convolutional Sequences

对于那些不熟悉 RNN 的人,我可以这样建议:​​

Understanding LSTM Networks

还有一个 python 库,它工作得很好(不幸的是,对于 C++ 甚至更好):

ocropy

我真的希望这可以帮助别人。