首页 > 解决方案 > tesseract 在简单的数字检测中失败

问题描述

我想对这样的图像执行OCR

带数值的 6x6 矩阵

它是一个以冒号作为小数分隔符的数字数据表。它不嘈杂,对比度很好,白色背景上的黑色文字。作为一个额外的预处理步骤,为了解决框架边框的问题,我剪切了每个单元格,将其二值化,用白色边框填充它(以防止边缘问题),然后仅将单个单元格图像传递给tesseract. 我还查看了单个细胞图像,以确保切割过程按预期工作并且不会产生伪影。以下是 的输入图像的两个示例tesseract

上表中的单个单元格。 内容:1,7

上表中的单个单元格。 内容:57

不幸的是,tesseract无法一致地解析这些。我没有找到正确识别所有 36 个值的配置。

--oemSO上有几个类似的问题,通常的答案是对和--psm参数的特定组合的建议。所以我用 pytesseract 编写了一个 python 脚本,它遍历--oem从 0 到 3 的所有组合以及从 0 到 13 的所有值--psm以及 alslang=englang=deu. 我忽略了引发错误的组合。

示例1:上面的“ --psm 13 --oem 31,7”图像被错误识别为“4,7”,但“57”图像被正确识别为“57”。

例2:上面的“ --psm 6 --oem 31,7”图像被正确识别为“1,7”,但“57”图像被错误识别为“o/”。

有什么建议可以帮助提高 tesseract 的输出质量吗?

我的正方体版本:

tesseract v4.0.0.20190314
 leptonica-1.78.0
  libgif 5.1.4 : libjpeg 8d (libjpeg-turbo 1.5.3) : libpng 1.6.34 : libtiff 4.0.9 : zlib 1.2.11 : libwebp 0.6.1 : libopenjp2 2.2.0
 Found AVX2
 Found AVX
 Found SSE

标签: ocrtesseractpython-tesseract

解决方案


解决方案


从原始图像中,我们可以看到有 5 个不同的行。

每次迭代,我们将取一行,应用归一化并读取。

我们需要了解如何仔细设置图像索引。

import cv2
from pytesseract import image_to_string

img = cv2.imread("0VXIY.jpg")
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(h, w) = gry.shape[:2]

start_index = 0
end_index = int(h/5)

问题为什么要声明开始索引和结束索引?

我们想在每次迭代中读取一行。让我们看一个例子:

当前图像的高度和宽度分别为 645 和 1597 像素。

根据索引划分图像:

起始索引 结束索引
0 129
129 258 (129 + 129)
258 387 (258 + 129)
387 516 (387 + 129)

让我们看看图像是否可读?

起始索引 结束索引 图片
0 129 在此处输入图像描述
129 258 在此处输入图像描述
258 387 在此处输入图像描述
387 516 在此处输入图像描述

不,它们不适合阅读,也许稍作调整可能会对我们有所帮助。喜欢:

起始索引 结束索引 图片
0 129 - 20 在此处输入图像描述
109 218 在此处输入图像描述
218 327 在此处输入图像描述
327 436 在此处输入图像描述
436 545 在此处输入图像描述
545 654 在此处输入图像描述

现在它们适合阅读。


当我们将除法归一化应用于每一行时:

起始索引 结束索引 图片
0 109 在此处输入图像描述
109 218 在此处输入图像描述
218 327 在此处输入图像描述
327 436 在此处输入图像描述
436 545 在此处输入图像描述
545 654 在此处输入图像描述

现在当我们阅读:

1,7 | 57 | 71 | 59 | .70 | 65

| 57 | 1,5 | 71 | 59 | 70 | 65

| 71 | 59 | 1,3 | 57 | 70 | 60

| 71 | 59 | 56 | 1,3 | 70 | 60

| 72 | 66 | 71 | 59 | 1,2 | 56

| 72 | 66 | 71 | 59 | 56 | 4,3

代码:

import cv2
from pytesseract import image_to_string

img = cv2.imread("0VXIY.jpg")
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(h, w) = gry.shape[:2]
# print(img.shape[:2])
start_index = 0
end_index = int(h/5) - 20

for i in range(0, 6):
    # print("{}->{}".format(start_index, end_index))
    gry_crp = gry[start_index:end_index, 0:w]
    blr = cv2.GaussianBlur(gry_crp, (145, 145), 0)
    div = cv2.divide(gry_crp, blr, scale=192)
    txt = image_to_string(div, config="--psm 6")
    print(txt)
    start_index = end_index
    end_index = start_index + int(h/5) - 20

推荐阅读