使用OpenCV预处理Tesseract OCR的图像

时间:2015-03-09 05:57:25

标签: opencv image-processing ocr tesseract

我正在尝试开发一个使用Tesseract来识别手机摄像头拍摄的文本的应用程序。我正在使用OpenCV预处理图像以便更好地识别,应用高斯模糊和阈值方法进行二值化,但结果非常糟糕。

Here是我用于测试的图像: enter image description here

here预处理后的图片: enter image description here

我可以使用其他过滤器来使图像对Tesseract更具可读性吗?

5 个答案:

答案 0 :(得分:44)

我在这里介绍了为Tesseract准备图像的一些技巧: Using tesseract to recognize license plates

在你的例子中,有几件事正在发生......

您需要将文本设置为黑色,将图像的其余部分设置为白色(相反)。这是什么字符识别被调整。灰度 是好的,只要背景大部分为全白,文字大部分为全黑;文本的边缘可能是灰色的(抗锯齿),而可能有助于识别(但不一定 - 你必须要进行实验)

您所看到的一个问题是,在图片的某些部分,文字实际上是“薄的”#34; (并且在阈值处理后字母中的间隙显示出来),而在其他部分,它实际上是#34;厚的" (并且字母开始合并)。 Tesseract不会那样:)这是因为输入图像没有均匀照明,所以单个阈值并不适用于所有地方。解决方案是进行局部自适应阈值处理"其中针对图像的每个邻居计算不同的阈值。有很多种方法,但请查看:

你遇到的另一个问题是线条不直。根据我的经验,Tesseract可以处理非常有限的程度的非直线(几个百分比的透视失真,倾斜或倾斜),但它并不适用于波浪< / em>行。如果可以,请确保源图像有直线:)不幸的是,没有简单的现成答案;您必须自己研究研究文献并实施最先进的算法之一(如果可能的话,请开源 - 实际上需要开源解决方案)。 Google学术搜索&#34; curved line OCR extraction&#34;会让你开始,例如:

最后:我认为使用python生态系统(ndimage,skimage)比使用C ++中的OpenCV更好。 OpenCV python包装器对于简单的东西是可以的,但是对于你想要做的事情,他们不能完成这项工作,你需要抓住许多OpenCV中没有的东西(当然你可以连连看)。在C ++中实现像曲线检测这样的东西将比在python中实现更长的数量级(*即使你不了解python也是如此)。

祝你好运!

答案 1 :(得分:13)

  
      
  1. 以300 dpi(每英寸点数)扫描并不是OCR(光学字符识别)的正式标准,但它被认为是黄金标准。

  2.   
  3. 将图像转换为灰度可提高读取文本的准确性。

  4.   

我编写了一个模块,用于读取Image中的文本,然后处理图像以获得OCR Image Text Reader 的最佳结果。

import tempfile

import cv2
import numpy as np
from PIL import Image

IMAGE_SIZE = 1800
BINARY_THREHOLD = 180


def process_image_for_ocr(file_path):
    # TODO : Implement using opencv
    temp_filename = set_image_dpi(file_path)
    im_new = remove_noise_and_smooth(temp_filename)
    return im_new


def set_image_dpi(file_path):
    im = Image.open(file_path)
    length_x, width_y = im.size
    factor = max(1, int(IMAGE_SIZE / length_x))
    size = factor * length_x, factor * width_y
    # size = (1800, 1800)
    im_resized = im.resize(size, Image.ANTIALIAS)
    temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.jpg')
    temp_filename = temp_file.name
    im_resized.save(temp_filename, dpi=(300, 300))
    return temp_filename


def image_smoothening(img):
    ret1, th1 = cv2.threshold(img, BINARY_THREHOLD, 255, cv2.THRESH_BINARY)
    ret2, th2 = cv2.threshold(th1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    blur = cv2.GaussianBlur(th2, (1, 1), 0)
    ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    return th3


def remove_noise_and_smooth(file_name):
    img = cv2.imread(file_name, 0)
    filtered = cv2.adaptiveThreshold(img.astype(np.uint8), 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 41, 3)
    kernel = np.ones((1, 1), np.uint8)
    opening = cv2.morphologyEx(filtered, cv2.MORPH_OPEN, kernel)
    closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel)
    img = image_smoothening(img)
    or_image = cv2.bitwise_or(img, closing)
    return or_image

答案 2 :(得分:5)

注意:这应该是对我回答的评论,但是它太长了所以我把它作为答案。

来自“谷歌公司Ray Smith的Tesseract OCR引擎概述”在https://github.com/tesseract-ocr/docs/blob/master/tesseracticdar2007.pdf

“处理遵循传统的一步一步 管道,但其中一些阶段是不寻常的 一天,甚至现在可能仍然如此。第一步是 一个连通分量分析,其中概述了 组件存储。这是计算上的 当时昂贵的设计决定,但有一个 显着优势:通过检查嵌套 概述,以及子孙的数量 概述,检测逆文本很简单 像黑白文本一样容易识别它。正方体 可能是第一个能够处理的OCR引擎 白色黑色文字如此琐碎。“

因此,似乎不需要在白色背景上使用黑色文字,并且也应该相反。

答案 3 :(得分:1)

您可以通过更改--psm和--oem值来使用OCR的配置,在您的情况下,我建议您使用

-psm 3 --oem 2

您也可以查看以下链接以获取更多详细信息 here

答案 4 :(得分:0)

我猜您已经使用了通用方法进行二值化,这就是整个图像未统一二值化的原因。您可以使用自适应阈值技术进行二值化。您还可以进行一些偏斜校正,透视校正,噪声消除,以获得更好的效果。

请参考此介质article,以了解上述技术以及代码示例。