程序员

Python:文本识别抛弃pytesser,直接使用Tesser

2019-09-30  本文已影响0人  59aa689f8c96

Update

本文最初写于2015年5月,最近Tesseract推出了3.05版,加入了一些新的特性;且原文存在一些纰漏,现重新编写。

PyTesser

PyTesser在Python Package Index中的版本仍为最初的2007年的0.0.1版,怀疑是不是已经不再维护。PyTesser似乎仅仅是在Tesseract的可执行程序tesseract.exe基础上写了一个面向Python的接口,就是通过shell执行tesseract命令获取返回值。

对于Tesseract这种C++编写的库采用可执行文件方式通过shell来建立库和Python的通信似乎无可厚非,但PyTesser在这里就犯了几个致命的错误:

直接集成tesseract.exe,导致x64不兼容,Linux不兼容等问题;

Tesseract版本过老且不可手动替换文件升级,其Tesseract版本为2007年之前版本;

PyTesser提供的接口代码效率不高(当时Tesseract支持度不高的原因)。

总的来说,除非PyTesser作出升级,否则PyTesser是基本没有价值的,不推荐使用。

关于Tesseract

Tesseract是一个流行的OCR(Optical Character Recognition,光学字符识别)库,通俗来说就是文本识别。Tesseract最初由HP(就是惠普啦)在1985年开始研发,后面貌似就没啥太重大的进展了;直到2005年HP将Tesseract开源,2006年开始交给Google维护。

Tesseract在进入3.0版本后各方面功能都有了长足的发展,尤其是3.02.02版本开始提供C-API,使得通过动态链接库与其他编程语言混合开发成为了可能。

直接使用Tesseract

这里介绍两种方法,一种是类似PyTesser的通过shell与tesseract通信完成识别过程;另一种是通过动态链接库(Windows下即DLL)实现。

shell

tesseract命令的格式为

Bash

tesseract imagename outputbase[-l lang][-psm pagesegmode][configfile...]

其中imagename为输入图片路径,outputbase为输出文本文件路径,此文本文件内容为图片文本识别结果。

所以通过shell实现的简单步骤就是

在Python中通过shell接口执行tesseract命令,指定输入和输出路径

读取输出文本文件内容

返回识别结果

安装Tesseract

首先安装Tesseract,参考官方wiki。Linux下直接通过包管理器安装(如apt-get install tesseract);Windows下3.02之后版本不提供安装包,但有一个3.05版的非官方安装包,点击这里直接下载,安装时记得展开“Registry settings”选项,在“Add to Path”前打钩。

安装完成后在shell中输入

Bash

tesseract -v

即可看到如下信息:

tesseract 3.05.00dev

leptonica-1.73

libgif 4.1.6(?) : libjpeg 8d (libjpeg-turbo 1.4.2) : libpng 1.6.20 : libtiff 4.0.6 : zlib 1.2.8 : libwebp 0.4.3 : libopenjp2 2.1.0

注意:安装得到的Tesseract自带英文语言包,本文仅演示英文效果;如需中文请自行下载中文语言包,并修改相关命令。

封装

现在将Tesseract封装为一个Python函数。

Python

importos

importsubprocess

defimage_to_string(img,cleanup=True,plus=''):

# cleanup为True则识别完成后删除生成的文本文件

# plus参数为给tesseract的附加高级参数

subprocess.check_output('tesseract '+img+' '+

img+' '+plus,shell=True)# 生成同名txt文件

text=''

withopen(img+'.txt','r')asf:

text=f.read().strip()

ifcleanup:

os.remove(img+'.txt')

returntext

这里解决了之前代码使用os.popen()不等待返回的bug,subprocess.check_output()会等待tesseract命令运行完成再返回。

运行

Python

print(image_to_string('./phototest.tif'))# 打印识别出的文本,删除txt文件

print(image_to_string('./phototest.tif',False))# 打印识别出的文本,不删除txt文件

print(image_to_string('./phototest.tif',False,'-l eng'))# 打印识别出的文本,不删除txt文件,同时提供高级参数

上述3中调用方式得到相同的结果。

DLL

通过动态链接库相对与shell方式有几个优点:

无需安装Tesseract(一般由自身自带DLL文件)

无需生成文本文件再读取,直接调用方法返回识别得到的字符串

更丰富的API支持

DLL方法即通过加载DLL文件,直接利用Tesseract C-API,在Python中调用此API完成识别。

DLL文件

DLL文件通常需要编译得到,编译Tesseract参考官方wiki。Linux下得到libtesseract.so,Windows下得到libtesseract.dll。

Windows下编译得到DLL文件也可以参考我的这篇文章:Tesseract 3.05及之后版本编译生成动态链接库DLL。

封装和运行

对加载DLL和调用API作封装。

x86

Python

importctypes

DLL_PATH='C:/tesseract/build/bin/Release/tesseract305.dll'

TESSDATA_PREFIX=b'./tessdata'

lang=b'eng'

tesseract=ctypes.cdll.LoadLibrary(DLL_PATH)

api=tesseract.TessBaseAPICreate()

rc=tesseract.TessBaseAPIInit3(api,TESSDATA_PREFIX,lang)

ifrc:

tesseract.TessBaseAPIDelete(api)

print('Could not initialize tesseract.\n')

exit(3)

deffrom_file(path):

tesseract.TessBaseAPIProcessPages(api,path,None,0,None)

text_out=tesseract.TessBaseAPIGetUTF8Text(api)

returnctypes.string_at(text_out)

if__name__=='__main__':

image_file_path=b'./phototest.tif'

result=from_file(image_file_path)

print(result)

x64

Python

importctypes

DLL_PATH='C:/tesseract/build/bin/Release/tesseract305.dll'

TESSDATA_PREFIX=b'./tessdata'

lang=b'eng'

tesseract=ctypes.cdll.LoadLibrary(DLL_PATH)

tesseract.TessBaseAPICreate.restype=ctypes.c_uint64

api=tesseract.TessBaseAPICreate()

rc=tesseract.TessBaseAPIInit3(ctypes.c_uint64(api),TESSDATA_PREFIX,lang)

ifrc:

tesseract.TessBaseAPIDelete(ctypes.c_uint64(api))

print('Could not initialize tesseract.\n')

exit(3)

deffrom_file(path):

tesseract.TessBaseAPIProcessPages(

ctypes.c_uint64(api),path,None,0,None)

tesseract.TessBaseAPIGetUTF8Text.restype=ctypes.c_uint64

text_out=tesseract.TessBaseAPIGetUTF8Text(ctypes.c_uint64(api))

returnctypes.string_at(text_out)

if__name__=='__main__':

image_file_path=b'./phototest.tif'

result=from_file(image_file_path)

print(result)

关于对x86和x64进行区分的原因,参见我的另一篇文章Python x64下ctypes动态链接库出现access violation的原因分析。

关于更多的API调用方法,还请自行寻找。

小结

对比来说,shell方法和DLL方法各有优劣,但总的来说DLL方法更胜一筹,由于少了一次磁盘写入和读取,在性能上也更优。不管怎样,PyTesser实在是没有继续用下去的意义了。

在介绍DLL方法的时候本来想介绍直接向API传入图片数据(不读取文件)进行识别的,但折腾PIL库没有成功,不过网上倒有通过opencv成功的例子,但opencv太过重量级这里就不介绍了,感兴趣的话可以看参考链接。

参考

tesseract-ocr/tesseract: Tesseract Open Source OCR Engine (main repository)

PyTesser Home Page

python - How to recognize data not filename using ctypes and tesseract 3.0.2? - Stack Overflow

opencv - Using C API of tesseract 3.02 with ctypes and cv2 in python - Stack Overflow

上一篇下一篇

猜你喜欢

热点阅读