使用 Tesseract OCR 和 python 进行数字识别

2024-04-25

我使用 Tesseract 和 python 读取数字(从能量计)。 除了数字“1”之外,一切都运行良好。 Tesseract 无法读取“1”数字。

This is the picture I send to tesseract : enter image description here

tesseract 读取“0000027”。

我如何告诉 Tesseract 垂直杆是“1”?

这是我的超正方体初始化:

import tesseract

TESSERACT_LIBRARY_PATH = "C:\\Program Files (x86)\\Tesseract-OCR"
LANGUAGE = "eng"
CHARACTERS = "0123456789"
FALSE = "0"
TRUE = "1"

def init_ocr():
    """ 
    .. py:function:: init_ocr()

        Utilize the Tesseract-OCR library to create an tesseract_ocr that 
        predicts the numbers to be read off of the meter. 

        :return: tesseract_ocr Tesseracts OCR API.
        :rtype: Class
    """
    # Initialize the tesseract_ocr with the english language package.
    tesseract_ocr = tesseract.TessBaseAPI()
    tesseract_ocr.Init(TESSERACT_LIBRARY_PATH, LANGUAGE, 
                       tesseract.OEM_DEFAULT)


    # Limit the characters being seached for to numerics.
    tesseract_ocr.SetVariable("tessedit_char_whitelist", CHARACTERS)

    # Set the tesseract_ocr to predict for only one character.
    tesseract_ocr.SetPageSegMode(tesseract.PSM_AUTO)

    # Tesseract's Directed Acyclic Graph.
    # Not necessary for number recognition.
    tesseract_ocr.SetVariable("load_system_dawg", FALSE)
    tesseract_ocr.SetVariable("load_freq_dawg", FALSE)
    tesseract_ocr.SetVariable("load_number_dawg", TRUE)

    tesseract_ocr.SetVariable("classify_enable_learning", FALSE)
    tesseract_ocr.SetVariable("classify_enable_adaptive_matcher", FALSE)

    return tesseract_ocr

稍微不相关的答案,尽管可能符合您最初的目标。

我对 tesseract 也有类似的问题,并且我也有非常严格的性能要求。我发现this https://stackoverflow.com/questions/9413216/simple-digit-recognition-ocr-in-opencv-pythonSO 上的简单解决方案,并使用 OpenCV 制作了简单的识别器。

它归结为在您拥有的非常清晰的图像上查找边界矩形(从边缘),然后尝试将找到的对象与模板进行匹配。我相信您的情况的解决方案将既简单又精确,尽管需要的代码比现在稍微多一些。

我将关注这个问题,因为使用超正方体找到可行的解决方案会很好。

我的时间有限,但这似乎是一个可行的解决方案:

import os
import cv2
import numpy
KNN_SQUARE_SIDE = 50  # Square 50 x 50 px.


def resize(cv_image, factor):
    new_size = tuple(map(lambda x: x * factor, cv_image.shape[::-1]))
    return cv2.resize(cv_image, new_size)


def crop(cv_image, box):
    x0, y0, x1, y1 = box
    return cv_image[y0:y1, x0:x1]


def draw_box(cv_image, box):
    x0, y0, x1, y1 = box
    cv2.rectangle(cv_image, (x0, y0), (x1, y1), (0, 0, 255), 2)


def draw_boxes_and_show(cv_image, boxes, title='N'):
    temp_image = cv2.cvtColor(cv_image, cv2.COLOR_GRAY2RGB)
    for box in boxes:
        draw_box(temp_image, box)
    cv2.imshow(title, temp_image)
    cv2.waitKey(0)


class BaseKnnMatcher(object):
    distance_threshold = 0

    def __init__(self, source_dir):
        self.model, self.label_map = self.get_model_and_label_map(source_dir)

    @staticmethod
    def get_model_and_label_map(source_dir):
        responses = []
        label_map = []
        samples = numpy.empty((0, KNN_SQUARE_SIDE * KNN_SQUARE_SIDE), numpy.float32)
        for label_idx, filename in enumerate(os.listdir(source_dir)):

            label = filename[:filename.index('.png')]
            label_map.append(label)
            responses.append(label_idx)

            image = cv2.imread(os.path.join(source_dir, filename), 0)

            suit_image_standard_size = cv2.resize(image, (KNN_SQUARE_SIDE, KNN_SQUARE_SIDE))
            sample = suit_image_standard_size.reshape((1, KNN_SQUARE_SIDE * KNN_SQUARE_SIDE))
            samples = numpy.append(samples, sample, 0)

        responses = numpy.array(responses, numpy.float32)
        responses = responses.reshape((responses.size, 1))
        model = cv2.KNearest()
        model.train(samples, responses)

        return model, label_map

    def predict(self, image):
        image_standard_size = cv2.resize(image, (KNN_SQUARE_SIDE, KNN_SQUARE_SIDE))
        image_standard_size = numpy.float32(image_standard_size.reshape((1, KNN_SQUARE_SIDE * KNN_SQUARE_SIDE)))
        closest_class, results, neigh_resp, distance = self.model.find_nearest(image_standard_size, k=1)

        if distance[0][0] > self.distance_threshold:
            return None

        return self.label_map[int(closest_class)]


class DigitKnnMatcher(BaseKnnMatcher):
    distance_threshold = 10 ** 10


class MeterValueReader(object):
    def __init__(self):
        self.digit_knn_matcher = DigitKnnMatcher(source_dir='templates')

    @classmethod
    def get_symbol_boxes(cls, cv_image):
        ret, thresh = cv2.threshold(cv_image.copy(), 150, 255, cv2.THRESH_BINARY)
        contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        symbol_boxes = []
        for contour in contours:
            x, y, width, height = cv2.boundingRect(contour)

            # You can test here for box size, though not required in your example:
            # if cls.is_size_of_digit(width, height):
            #     symbol_boxes.append((x, y, x+width, y+height))

            symbol_boxes.append((x, y, x+width, y+height))
        return symbol_boxes

    def get_value(self, meter_cv2_image):
        symbol_boxes = self.get_symbol_boxes(meter_cv2_image)
        symbol_boxes.sort()  # x is first in tuple
        symbols = []
        for box in symbol_boxes:
            symbol = self.digit_knn_matcher.predict(crop(meter_cv2_image, box))
            symbols.append(symbol)
        return symbols


if __name__ == '__main__':
    # If you want to see how boxes detection works, uncomment these:
    # img_bw = cv2.imread(os.path.join('original.png'), 0)
    # boxes = MeterValueReader.get_symbol_boxes(img_bw)
    # draw_boxes_and_show(img_bw, boxes)

    # Uncomment to generate templates from image
    # import random
    # TEMPLATE_DIR = 'templates'
    # img_bw = cv2.imread(os.path.join('original.png'), 0)
    # boxes = MeterValueReader.get_symbol_boxes(img_bw)
    # for box in boxes:
    #     # You need to label templates manually after extraction
    #     cv2.imwrite(os.path.join(TEMPLATE_DIR, '%s.png' % random.randint(0, 1000)), crop(img_bw, box))

    img_bw = cv2.imread(os.path.join('original.png'), 0)
    vr = MeterValueReader()
    print vr.get_value(img_bw)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Tesseract OCR 和 python 进行数字识别 的相关文章

  • 收据褪色部分可以恢复吗?

    我有一些包含一些扫描收据的文件 我需要使用 OCR 从中提取文本 由于收据上打印的文字在一段时间后会褪色 导致收据上的某些文字不清晰 影响OCR结果 褪色单词的一些示例 有什么方法可以恢复褪色的部分 以便提高 OCR 结果吗 我在OpenC
  • Python Pandas to_sql,如何创建带有主键的表?

    我想使用 Pandas 的 to sql 函数创建一个 MySQL 表 该函数有一个主键 在 mysql 表中拥有主键通常是件好事 如下所示 group export to sql con db name config table grou
  • 如何下载 NLTK 数据?

    更新的答案 NLTK 适用于 2 7 我有3 2 我卸载了3 2并安装了2 7 现在可以了 我已经安装了 NLTK 并尝试下载 NLTK 数据 我所做的是按照该网站上的说明进行操作 http www nltk org data html h
  • AngularJS 和 Django 的 DOM、JavaScript 和服务器端数据库之间是否存在三向数据绑定框架?

    AngularJS 爱好者兜售的功能之一是该框架提供的 DOM 内容和 JavaScript 数据之间的双向数据绑定 我目前正在开发几个集成 AngularJS 和 Django 的学习项目 其中一个痛点是 AngularJS 解决的 Ja
  • 使用SchemDraw库自动保存图像

    我想在Python中使用这个库来生成电气图 https cdelker bitbucket io SchemDraw https cdelker bitbucket io SchemDraw 我想在服务器中运行这段代码 这个想法是生成图像
  • 当你不需要Python中的索引时,如何创建For循环? [复制]

    这个问题在这里已经有答案了 如果我需要一个forPython 中的循环 for i in range 1 42 print spam 但不要使用i对于任何事情 pylint 都会抱怨未使用的变量 我应该如何处理这个问题 我知道你可以这样做
  • Google PubSub 在阻止和等待消息时没有标准输出

    我正在使用这个问题底部的 Python 代码监听 Google PubSub 消息 它实际上是来自 Google 的异步拉取示例 我运行我的程序并输出到文件 python my script py tee log txt 如果我在接收消息时
  • Redis SYNC 套接字上的错误情况:连接被拒绝

    在我的 django 应用程序中使用 celery 和 redis 一切都工作正常 直到我遇到了问题 redis 文件的位置已更改 redis 无法访问它们 经过查找 原来这是由于网络随机攻击造成的 需要添加confg 我添加文件后 一段时
  • 我应该如何优化这个文件系统 I/O 绑定程序?

    我有一个 python 程序 它执行如下操作 从 csv 文件中读取一行 对其进行一些变换 将其分解为实际的行 因为它们将被写入数据库 将这些行写入单独的 csv 文件 除非文件已完全读取 否则返回步骤 1 运行 SQL Loader 并将
  • 如何动态构造方法?

    我设计了一个类 它非常标准 具有一些方法属性 class foo def f1 self print f1 def f2 self print f2 def fn self print fn 现在我想创建一个包含一组 foo 实例的类 cl
  • 使用 openCV 和 python 检测物体

    我正在尝试使用 OpenCV 和 Python 检测下图中的白点 我尝试使用函数 cv2 HoughCircles 但没有成功 我需要使用不同的方法吗 这是我的代码 import cv2 cv import numpy as np impo
  • 如何使用生成器遍历文件系统?

    我正在尝试创建一个实用程序类来遍历目录中的所有文件 包括子目录和子子目录中的文件 我尝试使用发电机 因为发电机很酷 然而 我遇到了困难 def grab files directory for name in os listdir dire
  • Pymacs 助手在 30 秒后未启动

    我见过其他关于此的问题 但没有一个得到真正的回答 而且没有一个是我的问题 我有一个新系统 emacs 23 1 Centos 6 2 我认为 我下载了最新的 pymacs 并安装了它 但是 我得到 error Pymacs helper d
  • Apache2 mod_wsgi 403 禁止错误

    我已经正确配置了它 但后来我决定重新安装我的 Debian 顺便从 wheezy 切换到 jessie 版本 问题是这样的 我有一个 python mod wsgi 应用程序 mnt doc Python www index py ls l
  • 如何在 Ubuntu 上通过 pip 安装 python3 版本的软件包?

    我两者都有python2 7 and python3 2安装在Ubuntu 12 04 符号链接python链接到python2 7 当我输入 sudo pip install package name 它将默认安装python2的版本pa
  • 在 Python 中删除表达式树及其每个子表达式树中第一个元素周围的括号

    目标是实现简化操作 删除表达式树及其每个子表达式树中第一个元素周围的括号 其中表达式作为括在各个括号中的字符串输入给出 这必须适用于任意数量的括号 例如 12 3 45 6 gt 123 45 6 删除 12 周围的括号 然后删除 45 周
  • 抑制来自 python pandas 描述的名称 dtype

    可以说我有 r pd DataFrame A 1 B pd Series 1 index list range 4 dtype float32 And r B describe mean std min max 给出输出 mean 1 0
  • 带日志图的 Type 1 字体

    我正在尝试使用 Matplotlib 图表作为相机就绪的一部分 提交 出版社要求使用Type 1字体 仅有的 我发现 PDF 后端很乐意输出 Type 1 字体 具有线性 Y 轴的简单图形 但输出 Type 3 字体 对数 Y 轴 使用对数
  • numpy 沿第一个轴添加

    我想通过简单地沿第一个轴执行相同的加法来添加两个具有不同维度的数组 非矢量化解决方案 x np array 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 shape 4 3 2 y np a
  • Python:使用 FOR 循环插入字典

    我已经在论坛中进行了搜索 但不明白是否可以使用以下构造将新条目插入到我的 Python 字典中 而不将其转换为列表 for x in range 3 pupils dictionary new key input Enter new key

随机推荐