使用 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 进行数字识别 的相关文章

  • 类型错误:object.__new__(int) 不安全,请使用 int.__new__()

    阅读本文时 Python 中的元类是什么 https stackoverflow com questions 100003 what is a metaclass in python 我正在学习使用 new 使用以下代码片段 class a
  • 当参数为 0 与任何其他整数时,如何为返回不同类型的函数创建重载注释?

    是否可以为当参数为时返回不同类型的函数创建重载注释0与任何其他整数 def foo val int gt MyObjectA MyObjectB if val 0 return MyObjectA return MyObjectB 有没有办
  • 如何向未知用户目录读取/写入文件?

    我正在尝试从用户目录 C Users USERNAME Test Source 读取和写入文件 但我未能成功找到任何有关如何自动检测用户名的资源 其中的 USERNAME上面的例子 或者无论如何 我可以让它读取和写入目录 而不需要知道用户名
  • 如何分组显示argparse子命令?

    对于具有许多子命令的程序 我想在 help 输出中显示它们按逻辑分组 Python argparse 有一个add argument group http docs python org library argparse html argp
  • pandas 系列值之间的过滤

    If s is a pandas Series http pandas pydata org pandas docs stable dsintro html series 我知道我可以这样做 b s lt 4 or b s gt 0 但我做
  • 代码运行时出现内存问题(Python、Networkx)

    我编写了一个代码来生成具有 379613734 条边的图 但由于内存问题 代码无法完成 当经过 6200 万行时 大约会占用服务器内存的 97 所以我杀了它 您有解决这个问题的想法吗 我的代码是这样的 import os sys impor
  • 为什么 Python 中的无分支函数和内置函数速度较慢?

    我发现了 2 个无分支函数 它们可以在 python 中查找两个数字的最大值 并将它们与 if 语句和内置 max 函数进行比较 我认为无分支或内置函数将是最快的 但最快的是 if 语句函数 有人知道这是为什么吗 以下是功能 If 语句 2
  • 合并一个对(元组)列表?

    从链接对的列表中 我想将这些对组合成公共 ID 组 这样我就可以将 group ids 写回数据库 例如 UPDATE table SET group n WHERE id IN Example 1 2 3 4 1 5 6 3 7 8 be
  • time.sleep - TypeError:需要一个浮点[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 time sleep 2 TypeError a float is required 我该如何解决 我不确定我应该在这里做什么 您
  • 如何检查Docker中是否安装了python包?

    我使用Dockerfile成功构建了一个容器 但是 我的代码在容器中不起作用 如果我手动安装所有软件包 它确实有效 我假设我搞砸了一些导致 docker 没有正确安装软件包的事情 所以 我想检查Docker容器中是否安装了python包 最
  • python下安装xgboost 32位msys失败

    尝试安装 xgboost 失败 Windows 和企业版版本为 Anaconda 2 1 0 64 位 我该如何继续 我一直在使用 R 似乎从 RStudio 在 R 中安装新包相当容易 但在间谍程序中则不然 因为我需要进入命令窗口来执行此
  • Python 结构的 PHP 替代品

    我很高兴在我的 Python 项目中使用 Fabric 进行部署 现在我正在从事一个更大的 PHP 项目 想知道是否有类似 PHP 的 Fabric 之类的东西 唔 为什么这有关系 Fabric 只是 python 脚本 所以它与项目语言无
  • python 3 configparser.read() 在给定不存在的文件时不会引发异常

    当我尝试使用 configparser read 读取不存在的文件时 我认为它应该引发异常 事实并非如此 它返回一个空列表 显然 我可以测试空列表并引发异常 在我看来 如果 configparser read 引发 FileNotFound
  • 当输入是 DataFrame 时,在seaborn中对箱线图进行分组

    我打算在一个图中绘制多个列pandas dataframe 全部按另一列分组 使用groupby inside seaborn boxplot 对于类似的问题 这里有一个很好的答案matplotlib matplotlib 分组箱线图 ht
  • Tesseract OCR 培训的替代方案?

    在过去的三个月里我一直在尝试训练 Tesseract通过识别我拥有的图像集合 由于真正的缺乏适当的文档 以及非常高的复杂性 我开始放弃 Tesseract 作为解决方案 我正在寻找一种相对无痛的替代方案对于训练 我不想在这里重新发现轮子 如
  • 如何导入 boto3 ssm ParameterNotFound 异常?

    我想import the exception当一个boto3 ssm找不到参数get parameter 我正在尝试添加一些额外的内容ssm的功能moto图书馆 但我现在很困惑 gt gt gt import boto3 gt gt gt
  • Django model.foreignKey 并返回 self.text 错误

    所以我正在 Django 中处理 model py 但遇到了 2 个 pylint 错误 我不明白为什么 这是 pylint 的问题还是我在代码中做错了什么 E1120 No value for argument on delete in
  • 当没有 main 函数时,为什么 sys.settrace 不触发?

    import sys def printer frame event arg print frame event arg return printer sys settrace printer x 1 sys settrace None 上
  • Pandas 数据透视表同时包含多列

    我怀疑是否pandas pivot table可以一次接受两列并单独处理它们 而不是分层处理 假设我有以下数据框 id date day val 101 11 1 1 1 2 1 101 11 1 2 2 2 2 101 11 1 3 3
  • Python 3d 金字塔

    我是 3D 绘图新手 我只想用 5 个点建造一个金字塔并通过它切出一个平面 我的问题是我不知道如何填充两侧 points np array 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 fig plt figure ax fi

随机推荐