如何使用 OCR 检测图像中的下标数字?

dsp*_*cer 10 python ocr tesseract python-tesseract

tesseract通过pytesseract绑定用于 OCR 。不幸的是,我在尝试提取包含下标样式数字的文本时遇到了困难——下标数字被解释为一个字母。

例如,在基本图像中:

在此处输入图片说明

我想将文本提取为“CH3”,即我不担心知道数字3是图像中的下标。

我在此使用的尝试tesseract是:

import cv2
import pytesseract

img = cv2.imread('test.jpeg')

# Note that I have reduced the region of interest to the known 
# text portion of the image
text = pytesseract.image_to_string(
    img[200:300, 200:320], config='-l eng --oem 1 --psm 13'
)
print(text)
Run Code Online (Sandbox Code Playgroud)

不幸的是,这将错误地输出

'CHs'
Run Code Online (Sandbox Code Playgroud)

也有可能得到'CHa',具体取决于psm参数。

我怀疑这个问题与文本的“基线”在整个行中不一致有关,但我不确定。

如何从此类图像中准确提取文本?

更新 - 2020 年 5 月 19 日

在看到 Achintha Ihalage 的回答后tesseract,我没有为 提供任何配置选项,我探索了这些psm选项。

由于感兴趣的区域是已知的(在这种情况下,我使用 EAST 检测来定位文本的边界框),可能不需要在我的原始代码中将文本视为单行的的psm配置选项tesseractimage_to_string针对上面边界框给出的感兴趣区域运行给出输出

CH

3
Run Code Online (Sandbox Code Playgroud)

当然,这可以很容易地处理得到CH3

Ann*_*son 3

您需要在将图像输入之前对其进行预处理tesseract,以提高 OCR 的准确性。PIL我在这里使用和 的组合cv2来执行此操作,因为cv2它具有良好的过滤器来消除模糊/噪声(膨胀、腐蚀、阈值),并且PIL可以轻松增强对比度(区分文本与背景),并且我想展示如何预先可以使用其中任何一个来完成处理...(不过,并不是 100% 需要同时使用两者,如下所示)。你可以写得更优雅——这只是一般的想法。

import cv2
import pytesseract
import numpy as np
from PIL import Image, ImageEnhance


img = cv2.imread('test.jpg')

def cv2_preprocess(image_path):
  img = cv2.imread(image_path)

  # convert to black and white if not already
  img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

  # remove noise
  kernel = np.ones((1, 1), np.uint8)
  img = cv2.dilate(img, kernel, iterations=1)
  img = cv2.erode(img, kernel, iterations=1)

  # apply a blur 
  # gaussian noise
  img = cv2.threshold(cv2.GaussianBlur(img, (9, 9), 0), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

  # this can be used for salt and pepper noise (not necessary here)
  #img = cv2.adaptiveThreshold(cv2.medianBlur(img, 7), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2)

  cv2.imwrite('new.jpg', img)
  return 'new.jpg'

def pil_enhance(image_path):
  image = Image.open(image_path)
  contrast = ImageEnhance.Contrast(image)
  contrast.enhance(2).save('new2.jpg')
  return 'new2.jpg'


img = cv2.imread(pil_enhance(cv2_preprocess('test.jpg')))


text = pytesseract.image_to_string(img)
print(text)
Run Code Online (Sandbox Code Playgroud)

输出:

CH3
Run Code Online (Sandbox Code Playgroud)

预处理cv2生成的图像如下所示: 在此输入图像描述

增强功能为PIL您提供:

在此输入图像描述

在这个特定的示例中,您实际上可以在该cv2_preprocess步骤之后停止,因为这对读者来说已经足够清楚了:

img = cv2.imread(cv2_preprocess('test.jpg'))
text = pytesseract.image_to_string(img)
print(text)
Run Code Online (Sandbox Code Playgroud)

输出:

CH3
Run Code Online (Sandbox Code Playgroud)

但是,如果您正在处理不一定以白色背景开始的东西(即灰度转换为浅灰色而不是白色) - 我发现该PIL步骤确实有帮助。

要点是提高准确性的方法tesseract通常有:

  1. 修复 DPI(重新缩放)
  2. 修复图像的亮度/噪点
  3. 修复文本大小/线条(倾斜/扭曲文本)

执行其中一项或全部三项将会有所帮助......但亮度/噪音可能比其他两项更具有普遍性(至少从我的经验来看)。