编写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++集成的方法??梢栽跀U展里為所欲為,真是令人心情愉快。
首先,新建一個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 <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>?;蛘吣阆胧褂胦penCV,可以include <opencv2/opencv.hpp>并鏈接-lopencv_XXXXX。
?
這樣代碼部分算是完成了。不過接下來還有一步,我們需要打包完成一個Python擴展使之容易編譯和安裝??梢允褂胐istutils模塊。
from distutils.core import setup, Extensiontessenigma = 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 tesseximport 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中比較方便地識別圖像中的文字以及位置,對基于圖像識別的自動化測試是很有幫助的。
?
轉載于:https://www.cnblogs.com/silmerusse/p/3196301.html
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的编写Tesseract的Python扩展的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSS 编码中超级有用的工具集合
- 下一篇: 偶数字记数