技术好文共享:编写Tesseract的Python扩展

简介: 技术好文共享:编写Tesseract的Python扩展

Tesseract是一个开源的OCR(光学字符识别)引擎,用于识别并输出图片中的文字。虽然和商业软件比起来识别精度不算很高,但是如果你要寻找免费开源的OCR引擎,可能Tesseract就是唯一的选择了。Tesseract用起来还算是比较方便。它提供了一个简单的命令行工具,没有很多选项,输入图片输出就是文字。因为是开源的,你也可以直接编译使用它基于C++的库。


最近一段时间我对Python产生了很大的兴趣。它是如此的简洁高效,只要可以用Python完成的工作就懒得使用其他编程语言。所以到了应用Tesseract的时候我首先想到了去Google一下有没有Python binding。确实有人使用swig做了个tesseract的封装,不过不幸的是实际应用存在不少问题。首先是安装不便,尤其在mac上的安装令人崩溃。即使完成安装,不知为何又segment fault。其次,很多方法只做了简单的封装,又缺乏文档,想做深入一点的应用例如输出文字在图中的位置,感觉无从着手。不如从Tesseract的源代码入手,自己编写python的扩展,对tesseract的某些感兴趣的方法做个封装,也顺便熟悉下Python和C/C++集成的方法。可以在扩展里为所欲为,真是令人心情愉快。


首先,新建一个cpp源文件,然后为这个新模块想个名字,比如 tessex。然后,需要定义这个新模块,以及模块里需要暴露出来的方法。这样在Python里就可以用import tessex来载入模块。


static PyMethodDef tessexMethods【】 = {


{"recognize", (PyCFunction)tessex_recognize,


METH_VARARGS|METH_KEYWORDS,


"recognize text in an image."},


{NULL, NULL, 0, NULL}


};


PyMODINIT_FUNC inittessex(void) {


(void) Py_InitModule("tessex", tessexMethods);


}


这里,我们暴露一个方法recognize,用来扫描给定图片然后返回识别的文字以及位置。大家知道Python方法可以传两种参数,一种是无名的,一种是有名的,分别对应METH_VARARGS以及METH_KEYWORDS。作为一个有点完美主义倾向的人,我把两个选项都勾上了。然后我们看下recognize方法的定义。正如之前讲的,需要声明参数args以及kw。


static PyObject tessex_recognize(PyObject self, PyObject args, PyObject kw){


接下来是展开从Python调用传进来的参数。要使用有名参数,需要把所有参数名都先列出来。


  static const char kwlist【】={"data", "w", "h", "channels", "step", NULL};


然后调用PyArg_ParseTupleAndKeywords展开有名参数。一个格式字符串用于声明参数的类型。data是图像的像素buffer,适用S类型。w、h、channels、step分别是图像的宽度、高度、信道数、步长,都是整型变量,适用i类型。


PyStringObject data;


int w=0;


int h=0;


int channels=0;


int step=0;


if (!PyArg_ParseTupleAndKeywords(args, kw, "Siiii", (char*)(kwlist),


&data, &w, &h, &channels, &step)) {


PyErr_SetString(PyExc_Exception, "Tessex: Failed to parse arguments.");


return NULL;


}


我们要开始使用Tesseract的API了。Tesseract支持多种语言,不过语言包要分别下载安装。这里我们使用英语。


tesseract::TessBaseAPI api = new tesseract::TessBaseAPI();


if (api->Init(NULL, "eng")) {


PyErr_SetString(PyExc_Exception, "Tessex: Failed to initialize tesseract API.");


return NULL;


}


把传入的图像数据传递给Tesseract,然后进行识别。


api->SetImage((const unsigned char)PyString_AS_STRING(data),


w, h, channels, step);


api->Recognize(0);


识别结果的处理稍微复杂点。一般的应用如果只想得到所有文字,只要调用GetUTF8Text()就完了。但是我想知道每一行的文字,它们的具体位置以及可信度,就需要对识别结果进行详细的分析。幸运的是Tesseract提供了iterator接口,可以返回不同粒度的数据。这里我选择了按行输出,即RIL_TEXTLINE。

//代码效果参考:http://hnjlyzjd.com/xl/wz_25244.html


PyObject l = PyList_New(0);


tesseract::ResultIterator it = api->GetIterator();


it->Begin();


while(1) {


char utf8_text;


int left, top, right, bottom;


int confidence = 0;


utf8_text = it->GetUTF8Text(tesseract::RIL_TEXTLINE);


if (utf8_text == NULL)


break;


confidence = it->Confidence(tesseract::RIL_TEXTLINE);


it->BoundingBox(tesseract::RIL_TEXTLINE, &left, &top, &right, &bottom);


PyObject t = Py_BuildValue("(siiiii)", utf8_text,


left, top, right, bottom, confidence);


PyList_Append(l, t);


delete 【】utf8_text;


it->Next(tesseract::RIL_TEXTLINE);


}


api->End();


PyObject o = Py_BuildValue("O", l);


return o;


返回的是一个list,其每个元素都是一个tuple,代表识别出来的文字行,包括文字、位置和可信度。


最后不要忘了include需要的头文件,并在链接选项里加入需要的库。


#include "Python.h"


#include


#include


具体如何编译tesseract可以参考


在示例代码里我们并没有用到任何图形库。但是因为要使用Tesseract就必须链接leptonica库,所以需要加入链接选项-llept。


如果你想在扩展里使用leptonica的功能可以include 。或者你想使用openCV,可以include 并链接-lopencv_XXXXX。


这样代码部分算是完成了。不过接下来还有一步,我们需要打包完成一个Python扩展使之容易编译和安装。可以使用distutils模块。


from distutils.core import setup, Extension


tessenigma = Extension (


'tessex',


sources=【'tessex.cpp'】,


include_dirs = 【'/usr/local/include'】,


libraries=【 'tesseract'】,


library_dirs=【'/usr/local/lib'】


)


setup (name='tessex',


version='1.0',


description='This is a tesseract extensiion.',


ext_modules = 【tessex】)


把这些定义写入一个setup.py文件里。这样我们就可以用通常的方式编译和安装模块了。编译用setup.py build。一个动态链接库会生成。例如在Linux下面就是tessex.so。安装模块使用setup.py install。前面生成的库文件会被复制到Python的site-packages下面。当然你也可以手动复制到$PYTHONPATH路径下面,一样能被Python找到。


安装好扩展后,在Python里是这样调用的,假定我们使用一个openCV图像:


import tessex


import cv


cv_img = cv.LoadImage(path, cv.CV_LOAD_IMAGE_COLOR)


lines = tessex.recognize(


data=cv_img.tostring(),


w=cv_img.width,


h=cv_img.height,


channels=cv_img.nChannels,


step=cv_img.width cv_img.nChannels cv_img.depth / 8)


for line in lines:


  line_text, left, top, right, bottom, confidence = line


通过Tesseract扩展,可以在Python中比较方便地识别图像中的文字以及位置,对基于图像识别的自动化测试是很有帮助的。

相关文章
|
2月前
|
存储 监控 API
Python实战:跨平台电商数据聚合系统的技术实现
本文介绍如何通过标准化API调用协议,实现淘宝、京东、拼多多等电商平台的商品数据自动化采集、清洗与存储。内容涵盖技术架构设计、Python代码示例及高阶应用(如价格监控系统),提供可直接落地的技术方案,帮助开发者解决多平台数据同步难题。
|
1月前
|
数据可视化 大数据 关系型数据库
基于python大数据技术的医疗数据分析与研究
在数字化时代,医疗数据呈爆炸式增长,涵盖患者信息、检查指标、生活方式等。大数据技术助力疾病预测、资源优化与智慧医疗发展,结合Python、MySQL与B/S架构,推动医疗系统高效实现。
|
2月前
|
数据采集 存储 XML
Python爬虫技术:从基础到实战的完整教程
最后强调: 父母法律法规限制下进行网络抓取活动; 不得侵犯他人版权隐私利益; 同时也要注意个人安全防止泄露敏感信息.
676 19
|
3月前
|
数据采集 机器学习/深度学习 数据可视化
Python量化交易:结合爬虫与TA-Lib技术指标分析
Python量化交易:结合爬虫与TA-Lib技术指标分析
|
分布式计算 JavaScript NoSQL
Python 2013 精彩回顾:新闻、好文和资源
没想到2013年这么快就过去了,但是2013留给我们的却是互联网上很多优秀的文章、教程、经验以及开源项目。现在,就让我们来回顾一下2013年有关于Python的精彩的开发文章吧。趁着这些文章还没有过时,Python开发者们赶紧看过来了。
280 0
|
2月前
|
数据采集 机器学习/深度学习 人工智能
Python:现代编程的首选语言
Python:现代编程的首选语言
278 102
|
2月前
|
数据采集 机器学习/深度学习 算法框架/工具
Python:现代编程的瑞士军刀
Python:现代编程的瑞士军刀
301 104
|
2月前
|
人工智能 自然语言处理 算法框架/工具
Python:现代编程的首选语言
Python:现代编程的首选语言
253 103
|
2月前
|
机器学习/深度学习 人工智能 数据挖掘
Python:现代编程的首选语言
Python:现代编程的首选语言
191 82
|
1月前
|
Python
Python编程:运算符详解
本文全面详解Python各类运算符,涵盖算术、比较、逻辑、赋值、位、身份、成员运算符及优先级规则,结合实例代码与运行结果,助你深入掌握Python运算符的使用方法与应用场景。
175 3

推荐镜像

更多