Tesseract OCR无法检测不同字体大小和未水平对齐的字母。

20
我正在尝试检测这些价格标签文本,它们通常已经过明显的预处理。虽然可以轻松读取其上方写的文本,但无法检测价格值。我正在使用Python绑定pytesseract,但它也无法从CLI命令中读取。大多数情况下,它试图将价格识别为一个或两个字符的部分。 示例1:

tesseract D:\tesseract\tesseract_test_images\test.png output

这个样例图片的输出如下:

je Beutel

13

然而,如果我将价格裁剪并拉伸,使它们看起来分开且字体大小相同,则输出就很好。

处理后的图像(裁剪和缩小价格):

je Beutel

1,89

如何使OCR Tesseract按我的意愿工作,因为我将处理大量相似的图像? 编辑:添加了更多的价格标签:
sample2sample3sample4sample5 sample6 sample7


3
尝试设计一种算法,使用例如cv2.connectedComponentscv2.boundingRect函数来检测同一水平区域上大小不同的连通区域。然后可以通过放大较小的区域、缩小较大的区域或单独隔离不同的区域并分别进行调用tesseract - dROOOze
你能写一个例子来说明它可能如何工作吗?也许我可以逐个输入组件,它仍然可以工作,但connectedComponent返回一张黑色的图像。 - NONONONONO
请参见https://dev59.com/31cP5IYBdhLWcg3w-Opz。 - dROOOze
2个回答

15
问题在于您使用的图像尺寸较小。现在,当tesseract处理图像时,它将“8”、“9”和“,”视为一个单独的字母,因此预测为“3”,或者可能将“8”和“,”视为一个字母,“9”视为另一个字母,从而产生错误的输出。下面显示的图像说明了这一点。

detected contours of original(small) image

一个简单的解决方案是将原始图像的大小增加2或3倍甚至更多,然后传递给tesseract,以便它可以像下面显示的那样单独检测每个字母。(这里我将其大小增加了2倍)

detected contours of resized(larger) image

下面是一个简单的Python脚本,可以解决你的问题。
import pytesseract
import cv2

img = cv2.imread('dKC6k.png')
img = cv2.resize(img, None, fx=2, fy=2)

data = pytesseract.image_to_string(img)
print(data)

检测到的文本:

je Beutel

89
1.

现在,您可以从文本中提取所需数据,并根据您的要求进行格式化。

data = data.replace('\n\n', '\n')
data = data.split('\n')

dollars = data[2].strip(',').strip('.')
cents = data[1]

print('{}.{}'.format(dollars, cents))

所需格式:

1.89

提问者明确表示,他/她正在尝试检测价格标签文本,这些文本始终以显示格式清晰预处理。 - skt7
我正在更新问题,添加更多测试用例,几乎所有情况下都无法正常工作。在你的答案中,89被识别为1的前面,这表明它存在问题(它们应该在同一行,1不应该在89下面,而且逗号被识别为点)。我真正关注的是逗号上方有数字的部分。 - NONONONONO
1
这就是Tesseract的工作原理,它识别字符并根据其位置打印文本。你需要在某种程度上理解这一点,或者需要训练自己的模型,以便完美地按照你的要求工作,我认为在你的情况下更可取,因为你需要处理具有相同格式的图像。 - skt7
@NONONONONO 你可以上传图片到 GitHub 存储库并分享链接,这样我可以更清楚地了解你的数据集,并据此向您提供建议。 - skt7
1
我真的不能分享那些东西,因为它们确实不应该被分享,但无论如何我还是添加了一些测试用例。我不确定你所说的“位置”是什么意思,因为正如你所看到的,尽管89与1在同一行且靠右,但它未能被识别为1,89(就像阅读一样)。此外,显然图像大小不是问题,因为所有图片中价格数字上方的字母都被正确识别了。我转向了一个全新的架构来识别价格数字。 - NONONONONO
显示剩余5条评论

6
问题在于Tesseract引擎没有训练识别这种文本拓扑结构。您可以: 1. 训练自己的模型,特别需要提供具有不同拓扑(字符位置)变化的图像。您实际上可以使用相同的图像,并重新排列字符的位置。 2. 将图像重新组织成文本簇并使用Tesseract。特别是,我会考虑将“分”部分移动到逗号的右侧,在这种情况下,您可以直接使用Tesseract。一些相关标准将是文本簇的高度(以区分分和整数)和文本簇的位置(从左到右阅读)。 通常,计算机视觉算法(包括CNN)为您提供了更高级别的图像表示(特征或描述符),但它们无法创建处理中间结果的逻辑或算法。在您的情况下,这将是:“如果这些字母的高度较小,则为分”,“如果高度和垂直位置相同,则为同一数字,无论是在逗号的左侧还是右侧”。
事实是,通过训练很难达到这一点,同时将其作为算法写给人类却非常简单。抱歉没有给你一个实际的实现,但我的文本就是伪代码。

训练Tesseract2

训练Tesseract4

深度表示和图像聚类的联合无监督学习


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