TesseractのPython拡張の作成

12635 ワード

Tesseractは、画像中の文字を識別して出力するためのオープンソースのOCR(光学文字認識)エンジンである.ビジネスソフトウェアに比べて認識精度は高くありませんが、無料のオープンソースのOCRエンジンを探すなら、Tesseractが唯一の選択かもしれません.Tesseractは使いやすいです.簡単なコマンドラインツールを提供しており、多くのオプションがなく、入力画像の出力は文字です.オープンソースなので、C++ベースのライブラリを直接コンパイルして使用することもできます.
最近Pythonに大きな興味を持ちました.Pythonでできる仕事さえあれば、他のプログラミング言語を使うのがおっくうで効率的です.だからTesseractを応用する時私はまずGoogleに行ってPython bindingがあるかどうかを考えました.確かにswigを使ってtesseractのパッケージを作った人もいますが、残念なことに実際の応用には多くの問題があります.まず、インストールが不便で、特にmacでのインストールがクラッシュします.インストールが完了しても、なぜかfaultがsegmentされます.次に、多くの方法は簡単なパッケージを作っただけで、ドキュメントが欠けていて、例えば出力文字の図の中の位置を深く応用したいと思って、手がつけられないような気がします.むしろ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メソッドは2つのパラメータを伝えることができることを知っています.1つは無名で、1つは有名で、それぞれMETHに対応しています.VARRGSおよびMETH_KEYWORDS.完璧主義的な傾向のある人として、私は2つの選択肢をチェックしました.次に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);

認識結果の処理はやや複雑である.一般的なアプリケーションではすべての文字を取得したい場合はGetUTF 8 Text()を呼び出すだけで済みます.しかし、各行の文字、それらの具体的な位置、信頼性を知りたいのですが、識別結果の詳細な分析が必要です.幸いなことに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ライブラリをリンクする必要があるため、リンクオプション-llepを追加する必要があります.
拡張で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では画像中の文字や位置を比較的容易に認識でき,画像認識に基づく自動化テストに役立つ.