Kikuchy's Second Memory

技術のこととか、技術以外のこととか、思ったことを書き留めています。

tesseract-orc で 自作プログラムに画像の文字を読ませてみた

作っているプログラムで画像の文字を読み込む必要が出て来たので、手軽にできる方法を探してみました。
画像から文字を読むとなると、 OCR (Optical Character Reader) のライブラリを使うのが手っ取り早そうです。

OCR ライブラリの導入から、実際にライブラリを使ったプログラムを動かすところまでやってみました。

今回使う OCR の要件

今回は以下の条件の画像を読みたいので、この性能を満たしてくれる OCR があればバッチリ、ということになります。

  • 画像には文字のみが書かれている
  • 文字は単色、背景はほぼ単色
  • 文字種は、数字とコロンのみの 11 種
  • 文字は特定のフォントを使ってコンピューターで書かれたもので、印刷物でも手書きでもない

要するにこんな画像です。

f:id:kikuchy:20130825173105p:plain

見覚えがある? さあ、何の事やら。

OCR の選定

調べてみた所以下の二種類が有名なようです。

tesseract-ocr

どうやら Google 先生が開発を支援しているらしい OCR
言語(日本語や英語など)ごとに辞書が用意されているため、それを切り替える事でさまざまな言語の文字読み取りに対応できるらしい。

nhocr

日本製で、日本語の読み取り精度は上の tesseract-ocr より良い様子。


今回は使用する文字種が少ない上、日本語を読ませる予定は無いので、Homebrewですぐにインストールできそうな tesserct-ocr を使ってみることにしました。

環境
インストール

至極簡単でした。以下のコマンドで一発です。

brew install tesseract

tesseract は leptonica という画像解析ライブラリに依存しており、leptonica は libpng, libtiff, libjpeg などに依存しているため、かなり沢山のライブラリが導入されるかも知れません。

とりあえずテストしてみましょう。 tesseract はコマンドラインのツールも付属していて、このプログラムに画像を食わせると、解析結果をテキストファイルにして吐き出してくれます。

冒頭の画像を time.png として、以下のコマンドを叩きます。

tesseract time.png result -l eng

すると result.txt が出来ているので中を開くと、結果が書かれています。

f:id:kikuchy:20130825174157p:plain

ちゃんと読めてますね。後はライブラリとして使えればOKです。

使ってみる

こちらのページを参考に以下のソースを打ち込みました。

#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>

int main(){
    tesseract::TessBaseAPI *myOCR = 
                new tesseract::TessBaseAPI();
    if (myOCR->Init(NULL, "eng")) {
          fprintf(stderr, "Could not initialize tesseract.\n");
          exit(1);
    }

    Pix *pix = pixRead("time.png"); // <- 今回入力するファイル名
    myOCR->SetImage(pix);

    char* outText = myOCR->GetUTF8Text();
    printf("入渠時間 残り:\n\n");
    printf(outText);

    myOCR->Clear();
    myOCR->End();
    delete [] outText;
    pixDestroy(&pix);

    return 0;
}

1, 2行目で、 tesseract と leptonica のヘッダーを読み込んでいます。私は leptonica のヘッダーを読み忘れてエラったので、忘れないようにしてください。
これを tess.cpp として保存、コンパイルします。

$ g++ g++ -llept -ltesseract -I/usr/local/include -L/usr/local/lib tess.cpp

ライブラリのリンクが必要なので -l オプションが必要です。また、-I と -L オプションで、ライブラリの本体とヘッダーファイルの保管場所も指定しましょう(-I と -L は、PATHが通っていれば必要ありません)。
Homebrewは、デフォルトで /usr/local/ 以下にインストールしたファイルが置かれますので、そこを指定してあります(MacPorts だと /opt/local/ 以下だったかな)。

読ませたい画像ファイルは、実行ファイルと同じディレクトリに置いておきます。
さて、実行結果はどうでしょう。

$ ./a.out 
入渠時間 残り:

07:05:34

成功です! これで自作のプログラムで、画像からの文字の読み込みができますね。
解析結果に改行コードが混じっているようですが、後で trim してやれば問題ないでしょう。