【问题标题】:Preprocessing image for Tesseract OCR with OpenCV使用 OpenCV 对 Tesseract OCR 进行图像预处理
【发布时间】:2015-05-10 06:05:21
【问题描述】:

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

Here 是我用于测试的图像:

here 预处理后的图像:

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

【问题讨论】:

    标签: opencv image-processing ocr tesseract


    【解决方案1】:

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

    在您的示例中,发生了几件事...

    您需要将文本设置为黑色,将图像的其余部分设置为白色(不是相反)。这就是字符识别的重点。灰度可以的,只要背景多为全白,文字多为全黑即可;文本的边缘可能是灰色的(抗锯齿),可能有助于识别(但不一定 - 您必须进行试验)

    您看到的其中一个问题是,在图像的某些部分,文字真的很“薄”(并且在阈值处理后出现了字母中的间隙),而在其他部分,它真的很“厚”(和字母开始合并)。 Tesseract 不喜欢这样 :) 发生这种情况是因为输入图像的光照不均匀,因此单个阈值并不适用于任何地方。解决方案是执行“局部自适应阈值”,其中为图像的每个邻域计算不同的阈值。有很多方法可以做到这一点,但请查看以下示例:

    您遇到的另一个问题是线条不直。根据我的经验,Tesseract 可以处理非常有限度的非直线(百分之几的透视失真、倾斜或歪斜),但它并不真正适用于波浪 线。如果可以,请确保源图像具有直线 :) 不幸的是,对此没有简单的现成答案;您必须查看研究文献并自己实现一种最先进的算法(如果可能的话,开源它 - 确实需要一个开源解决方案)。在 Google Scholar 中搜索“curved line OCR extraction”会帮助您入门,例如:

    最后:我认为使用 python 生态系统(ndimage、skimage)比使用 C++ 中的 OpenCV 会做得更好。 OpenCV python 包装器适用于简单的东西,但对于你想要做的事情,它们不会完成这项工作,你需要抓取许多不在 OpenCV 中的部分(当然你可以混合和匹配)。在 C++ 中实现曲线检测之类的东西将比在 python 中长一个数量级(* 即使你不了解 python,也是如此)。

    祝你好运!

    【讨论】:

    • 感谢您的回答。我尝试使用直线图片和 AdaptiveThreshold 并得到不完美但相当不错的结果。我将研究曲线问题,并在找到解决方案时将其开源。最后,我会采纳你的建议并至少使用 python 完成这项任务。
    • 很遗憾,您的链接不再有效。我也会很感兴趣..
    • 更新链接:Adaptive gaussian thresholding in OpenCVLocal Otsu's methodLocal adaptive histogram equalization 一个简单的 google inurl 搜索可以修复很多损坏的链接
    • 您能否更新答案中的外部链接?谢谢!
    • 你知道tesseract引擎对图像执行了哪些预处理步骤吗?与this example 一样,tesseract 能够从彩色图像中检测文本,因此它必须在识别之前执行一些步骤。
    【解决方案2】:
    1. 以 300 dpi(每英寸点数)扫描并不是 OCR(光学字符识别)的正式标准,但它被认为是黄金标准。

    2. 将图像转换为灰度通常可以提高阅读文本的准确性。

    我编写了一个模块,它读取 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
    

    【讨论】:

    • 不知何故,即使经过这么多的改进,tesseract 仍然无法检测到我在图像上的文字。知道这里可以做些什么吗...?
    • 能否请您在这里查看一个 Tesseract 和 OpenCV 相关问题:stackoverflow.com/questions/66946835/…
    • @yardstick17,它适用于大多数图像,但对于某些图像,结果相当糟糕。对于带有白色文字的图像,例如在深色背景上带有白色文字的图像,效果并不好。
    【解决方案3】:

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

    来自“Tesseract OCR 引擎概述,作者 Ray Smith,Google Inc.”在https://github.com/tesseract-ocr/docs/blob/master/tesseracticdar2007.pdf

    "处理遵循传统的逐步 管道,但有些阶段在他们的 天,甚至现在可能仍然如此。第一步是 连通分量分析,其中的轮廓 组件被存储。这是一个计算 当时昂贵的设计决定,但有一个 显着优势:通过检查嵌套 轮廓,以及子孙的数量 轮廓,很容易检测反向文本和 识别它就像黑底白字一样容易。正方体 可能是第一个能够处理的 OCR 引擎 黑底白字太简单了。”

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

    【讨论】:

    • 这是旧文档 - 对 tesseract 4.x 无效
    • @user898678,你能告诉我一个在 tesseract 4.x 上运行良好的例子吗?
    • 只提供白色背景上的黑色字母作为输入(例如已经二值化的图像)
    【解决方案4】:

    您可以通过更改 --psm 和 --oem 值来调整 OCR 的配置,具体而言,我建议您使用

    --psm 3 --oem 2

    您还可以查看以下链接了解更多详情 here

    【讨论】:

      【解决方案5】:

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

      参考此媒体article,了解上述技术以及代码示例。

      【讨论】:

      • 欢迎来到 SO。回复前请参考stackoverflow.com/help/how-to-answer。在这种情况下,不要发布可能有一天会消失的链接。而是尝试将所有必要的信息放入您的答案中。
      【解决方案6】:

      对于像你这样的波浪形文本,在 GitHub 上有一个很棒的 Python 代码,它将文本转换为直线:https://github.com/tachylatus/page_dewarp.git(这是 MZucker 原始帖子的最新版本,这里解释了机制:https://mzucker.github.io/2016/08/15/page-dewarping.html

      【讨论】:

        猜你喜欢
        • 2017-09-21
        • 2015-06-14
        • 2019-01-12
        • 1970-01-01
        • 2014-03-30
        • 2019-10-16
        • 1970-01-01
        • 2020-12-29
        • 2019-06-04
        相关资源
        最近更新 更多