编写Tesseract的Python扩大
添加时间:2013-7-18 点击量:
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);
[]utf8_text;
it->Next(tesseract::RIL_TEXTLINE);
}
api->End();
PyObject o = Py_BuildValue(O, l);
return o;
返回的是一个list,其每个元素都是一个tuple,代表辨认出来的文字行,包含文字、地位和可托度。
最后不要忘了include须要的头文件,并在链接选项里参加须要的库。
#include Python.h
#include <tesseract/baseapi.h>
#include <tesseract/resultiterator.h>
具体如何编译tesseract可以参考https://code.google.com/p/tesseract-ocr/wiki/Compiling/
在示例代码里我们并没有效到任何图形库。然则因为要应用Tesseract就必须链接leptonica库,所以须要参加链接选项-llept。
若是你想在扩大里应用leptonica的功能可以include <leptonica/allheaders.h>。或者你想应用openCV,可以include <opencv2/opencv.hpp>并链接-lopencv_XXXXX。
如许代码项目组算是完成了。不过接下来还有一步,我们须要打包完成一个Python扩大使之轻易编译和安装。可以应用distutils模块。
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中斗劲便利地辨认图像中的文字以及地位,对基于图像识此外主动化测试是很有帮助的。
彼此相爱,却不要让爱成了束缚:不如让它成为涌动的大海,两岸乃是你们的灵魂。互斟满杯,却不要同饮一杯。相赠面包,却不要共食一个。一起歌舞欢喜,却依然各自独立,相互交心,却不是让对方收藏。因为唯有生命之手,方能收容你们的心。站在一起却不要过于靠近。—— 纪伯伦《先知》
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);
[]utf8_text;
it->Next(tesseract::RIL_TEXTLINE);
}
api->End();
PyObject o = Py_BuildValue(O, l);
return o;
返回的是一个list,其每个元素都是一个tuple,代表辨认出来的文字行,包含文字、地位和可托度。
最后不要忘了include须要的头文件,并在链接选项里参加须要的库。
#include Python.h
#include <tesseract/baseapi.h>
#include <tesseract/resultiterator.h>
具体如何编译tesseract可以参考https://code.google.com/p/tesseract-ocr/wiki/Compiling/
在示例代码里我们并没有效到任何图形库。然则因为要应用Tesseract就必须链接leptonica库,所以须要参加链接选项-llept。
若是你想在扩大里应用leptonica的功能可以include <leptonica/allheaders.h>。或者你想应用openCV,可以include <opencv2/opencv.hpp>并链接-lopencv_XXXXX。
如许代码项目组算是完成了。不过接下来还有一步,我们须要打包完成一个Python扩大使之轻易编译和安装。可以应用distutils模块。
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中斗劲便利地辨认图像中的文字以及地位,对基于图像识此外主动化测试是很有帮助的。
彼此相爱,却不要让爱成了束缚:不如让它成为涌动的大海,两岸乃是你们的灵魂。互斟满杯,却不要同饮一杯。相赠面包,却不要共食一个。一起歌舞欢喜,却依然各自独立,相互交心,却不是让对方收藏。因为唯有生命之手,方能收容你们的心。站在一起却不要过于靠近。—— 纪伯伦《先知》