gpt4 book ai didi

python - 在 python 中将 tesseract 3.02 的 C API 与 ctypes 和 cv2 结合使用

转载 作者:太空狗 更新时间:2023-10-30 00:40:52 24 4
gpt4 key购买 nike

我正在尝试在 python 中将 Tesseract 3.02 与 ctypes 和 cv2 结合使用。 Tesseract 提供了一组 DLL 暴露的 C 风格 API,其中之一如下:

TESS_API void  TESS_CALL TessBaseAPISetImage(TessBaseAPI* handle, const unsigned char* imagedata, int width, int height, int bytes_per_pixel, int bytes_per_line);

到目前为止,我的代码如下:

tesseract = ctypes.cdll.LoadLibrary('libtesseract302.dll')
api = tesseract.TessBaseAPICreate()
tesseract.TessBaseAPIInit3(api, '', 'eng')
imcv = cv2.imread('test.bmp')
w, h, d = imcv.shape
ret = tesseract.TessBaseAPISetImage(api, ctypes.c_char_p(str(imcv.data)), w, h, d, w * d)
#ret = 44 here

最后一行返回错误代码 44,我在 Tesseract 提供的 errcode.h 中找不到任何地方。我不确定我在这里做错了什么。

我发现了类似的问题 How to recognize data not filename using ctypes and tesseract 3.0.2? ,但是问题没有解决。我也知道 https://code.google.com/p/python-tesseract/ , 我深入研究了这个项目的源代码,但没有找到我需要的信息。

我可以通过调用 cv2.imshow 确认 test.bmp 中的图像是合法且可读的。同样的图像也可以通过 Tesseract 在命令行上进行 OCR。

最佳答案

默认的restypec_int,默认的整数参数转换也是c_int。您会在 Web 上找到假设 32 位平台具有 sizeof(int) == sizeof(void *) 的示例。这从来都不是一个好的假设。要保护 64 位指针在与 Python 整数相互转换时不被截断,请设置函数指针的 argtypesrestype。无论如何这样做都是一个好主意,因为它允许 ctypes 在使用错误的类型或数量的参数时引发 ArgumentError

如果您不想为每个函数都定义原型(prototype),那么至少将 TessBaseAPICreate.restype 设置为一个不透明的指针类型。

以下 ctypes 定义基于 header api/capi.h .为方便起见,我将 API 打包到 Tesseract 类中。

import sys
import cv2
import ctypes
import ctypes.util

if sys.platform == 'win32':
LIBNAME = 'libtesseract302'
else:
LIBNAME = 'tesseract'

class TesseractError(Exception):
pass

class Tesseract(object):
_lib = None
_api = None

class TessBaseAPI(ctypes._Pointer):
_type_ = type('_TessBaseAPI', (ctypes.Structure,), {})

@classmethod
def setup_lib(cls, lib_path=None):
if cls._lib is not None:
return
if lib_path is None:
lib_path = ctypes.util.find_library(LIBNAME)
if lib_path is None:
raise TesseractError('tesseract library not found')
cls._lib = lib = ctypes.CDLL(lib_path)

# source:
# https://github.com/tesseract-ocr/tesseract/
# blob/3.02.02/api/capi.h

lib.TessBaseAPICreate.restype = cls.TessBaseAPI

lib.TessBaseAPIDelete.restype = None # void
lib.TessBaseAPIDelete.argtypes = (
cls.TessBaseAPI,) # handle

lib.TessBaseAPIInit3.argtypes = (
cls.TessBaseAPI, # handle
ctypes.c_char_p, # datapath
ctypes.c_char_p) # language

lib.TessBaseAPISetImage.restype = None
lib.TessBaseAPISetImage.argtypes = (
cls.TessBaseAPI, # handle
ctypes.c_void_p, # imagedata
ctypes.c_int, # width
ctypes.c_int, # height
ctypes.c_int, # bytes_per_pixel
ctypes.c_int) # bytes_per_line

lib.TessBaseAPIGetUTF8Text.restype = ctypes.c_char_p
lib.TessBaseAPIGetUTF8Text.argtypes = (
cls.TessBaseAPI,) # handle

def __init__(self, language='eng', datapath=None, lib_path=None):
if self._lib is None:
self.setup_lib(lib_path)
self._api = self._lib.TessBaseAPICreate()
if self._lib.TessBaseAPIInit3(self._api, datapath, language):
raise TesseractError('initialization failed')

def __del__(self):
if not self._lib or not self._api:
return
if not getattr(self, 'closed', False):
self._lib.TessBaseAPIDelete(self._api)
self.closed = True

def _check_setup(self):
if not self._lib:
raise TesseractError('lib not configured')
if not self._api:
raise TesseractError('api not created')

def set_image(self, imagedata, width, height,
bytes_per_pixel, bytes_per_line=None):
self._check_setup()
if bytes_per_line is None:
bytes_per_line = width * bytes_per_pixel
self._lib.TessBaseAPISetImage(self._api,
imagedata, width, height,
bytes_per_pixel, bytes_per_line)

def get_utf8_text(self):
self._check_setup()
return self._lib.TessBaseAPIGetUTF8Text(self._api)

def get_text(self):
self._check_setup()
result = self._lib.TessBaseAPIGetUTF8Text(self._api)
if result:
return result.decode('utf-8')

示例用法:

if __name__ == '__main__':
imcv = cv2.imread('ocrtest.png')
height, width, depth = imcv.shape

tess = Tesseract()
tess.set_image(imcv.ctypes, width, height, depth)
text = tess.get_text()

print text.strip()

我在 Linux 上使用 libtesseract.so.3 对此进行了测试。请注意,cv2.imread 返回一个 NumPy 数组。这有一个 ctypes 属性,其中包括 _as_parameter_ Hook ,设置为指向数组的 c_void_p 指针。另请注意,问题中显示的代码的宽度和高度已调换。它应该是 h, w, d = imcv.shape

ocrtest.png:

ocrtest

输出:

I am trying to use Tesseract 3.02 with ctypes and cv2 in python. Tesseract
provides a DLL exposed set of C style APIs, one of them is as following:

关于python - 在 python 中将 tesseract 3.02 的 C API 与 ctypes 和 cv2 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21745205/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com