设为首页 收藏本站
查看: 1465|回复: 0

[经验分享] 编写Tesseract的Python扩展

[复制链接]

尚未签到

发表于 2015-4-20 10:56:41 | 显示全部楼层 |阅读模式
  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。



    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可以参考https://code.google.com/p/tesseract-ocr/wiki/Compiling/
  在示例代码里我们并没有用到任何图形库。但是因为要使用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中比较方便地识别图像中的文字以及位置,对基于图像识别的自动化测试是很有帮助的。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-58730-1-1.html 上篇帖子: python版 百度签到 下篇帖子: Python修改Mp3文件名称
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表