目的
tess-twoを使ってテキストの検出を実際に行ってみる。 Making a Simple OCR Android App using Tesseract を参考にした。
実験でカメラを使う必要はないので、手元にあった本の画像をあらかじめ撮影し、左上の ISBNコードを読みとってみる。
プロジェクトの準備
- ウィザードで空のプロジェクトを作る。
Java Build Pathに tess-two.jarを追加
※ 今回のサンプルでは共有ライブラリのコピーは必要なかった。どういうときに必要になるのかまだ理解できていないeng.traineddataを assetsに追加
上の画像を sample.jpgとして assetsに追加
Manifestに WRITE_EXTERNAL_STORAGEパーミッションを追加
あとは MainActivity.javaを書く。面倒なのでUIには何も出さない。結果を LogCatに出力するだけ。
→ https://gist.github.com/Nunocky/5d43d0ec4b2270927446
解説
限定的な利用なら本当に簡単。
- 画像を用意する
- TessBaseAPIのインスタンスを作る
- 画像を指定する
- 調査範囲を指定する
- テキストを取得する
それを行っているのが MainActivityの onResumeの中。
AssetManager assetManager = getResources().getAssets();
InputStream is = assetManager.open(TARGET_IMAGE);
Bitmap bitmap = BitmapFactory.decodeStream(is);
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
TessBaseAPI baseApi = new TessBaseAPI();
baseApi.init(EXSTORAGE_PATH, "eng");
baseApi.setImage(bitmap);
baseApi.setRectangle(56, 81, 230, 22);
String recognizedText = baseApi.getUTF8Text();
baseApi.end();
Log.d(TAG, "Recognized: " + recognizedText);
これだけ。
setRectangleで指定する範囲は GIMPで適当に調べた。
baseApi.initで trainedデータを指定する際に assetsを直接指定することができないので、onCreateで外部ストレージにコピーしている(prepareTrainedFileIfNotExistメソッド)。あんまりかっこよくないが、とりあえずはこれでOK。
なお、 「traineddataはtessdataの下に置く」、 「initに渡すディレクトリはtessdataの一個上を指定する」 というルールがある。traineddataを tessdata以外の場所に置いても、以下のような Exceptionが発生してしまう。
java.lang.IllegalArgumentException: Data path must contain subfolder tessdata!
※ もう一個細かいことで、 initに渡すディレクトリはスラッシュで終えること、と javadocで書かれている。なので EXSTORAGE_PATHはそのように書いているが、スラッシュを書かなくても特に影響はないようだ。ライブラリ側で補完してくれているのかも。
実行
Jolly Good.
次は?
疑問に思うところは色々ある。
- 複数テキストの同時検出はできるのか? StringとRectangleのセットみたいなものが手に入る?
- 本の見開き全体を一度にスキャンするようなことはできるのか?
- 使ってみるとわかるが、初期化などは結構重たい処理なのでマルチスレッド化した方が良さそう。理想的な構成は?
- 縦書きにも対応している? → APIリファレンスを見るとできるっぽい
等々。