iOS で OCR を行ってみたかったので、有名な tesseract-ocr を自分でビルドしてみました。Windows はバイナリが提供されていたり、ビルド自体もシンプルだったりしますが、iOS で使う場合には複数のアーキテクチャに対応したライブラリを作る必要があるので手間がかかります。
その辺りの知識が不足していたので、まずは先人の知恵に頼ってビルドしてみることにしました。
Compile tesseract for iOS SDK 6.0 – Code-It
iOS 6 SDK を使ってビルドする手順を書いてくれているページを見つけたので、homebrew を使って必要なツールをインストールして、公開してくれているビルド用スクリプトを使って試してみました.
しかし、公開されているスクリプトでは C/C++ コンパイラが見つからないというエラーになってしまって、ビルドが上手くいきませんでした。
checking build system type... i386-apple-darwin13.3.0 checking host system type... arm-apple-darwin6 checking how to print strings... printf checking for arm-apple-darwin6-gcc... /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc checking whether the C compiler works... no configure: error: in `/Users/shibayan/Projects/tesseract-build/leptonica-1.71': configure: error: C compiler cannot create executables
エラーについて調べてみると、既に Objective-C でラップされた Tesseract-OCR iOS というライブラリがあるので、そこで公開されているビルド用スクリプトを使えば上手くいくとあったので試しました。
gali8/Tesseract-OCR-iOS · GitHub
今度はビルドに成功して leptonica と tesseract-ocr のライブラリが無事に生成されましたが、このスクリプトそのままでは stdlibc++ を使ってビルドが行われるらしく、libc++ を使ってビルドされたライブラリとの競合が発生してしまいました。
setenv_all() { # Add internal libs .... # libc++ を使うように変更 export CPPFLAGS=$CFLAGS export CXXFLAGS="$CFLAGS -stdlib=libc++" }
CXXFLAGS に -stdlib=libc++ フラグを追加してビルドし直すことで、競合を解決することが出来ました。
実際に iOS で tesseract-ocr を使うサンプルコードを用意しました。tesseract-ocr は C++ なので Objective-C++ で書く必要がある点に注意が必要です。
// TESSDATA_PREFIX 環境変数を定義しておかないと死ぬ NSString *dataPath = [NSString stringWithFormat:@"%@/", [NSString stringWithString:[[NSBundle mainBundle] bundlePath]]]; setenv("TESSDATA_PREFIX", [dataPath UTF8String], 1); // OCR エンジンを初期化 tesseract::TessBaseAPI tessBaseApi; tessBaseApi.Init(nullptr, "eng"); // 対象の画像をセット tessBaseApi.SetImage(image.data, image.size().width, image.size().height, image.channels(), image.step1()); // 認識 tessBaseApi.Recognize(0); // OCR 結果を取得 auto result = tessBaseApi.GetUTF8Text();
今回はサンプル画像として抱かれたい男 No.1 の自己紹介が英語でいい感じだったので拾ってきました。
英語のみだとそれなりに認識精度が高そうですね。
次は日本語を試してみます。サンプルとしてかずあきさんの自己紹介を拾ってきました。
うーん、日本語はトレーニングが必要になりそうな精度ですね。所々しか正しく認識出来ていないので、日本語の OCR として使うためにはもう一手間加える必要がありそうです。