読者です 読者をやめる 読者になる 読者になる

開発版のTesseract 4.0 alphaをためしてみる(macOS)

OCR tesseract

この記事は開発中のアルファ版を対象にしてます。その点には十分注意してください。要するに自己責任でどうぞって話です*1

github.com

微妙に出遅れている感じがありますが……。

11月中旬ごろからメイン開発者のRay Smith氏によるバージョン 4.x のコードがgithubにコミットされています。

2、3日前からで各言語のXXX.traineddataファイルもアップロードされており*2ひとまず試せる状態。

まだ全ての言語が出揃っていませんが、英語などの主要言語はアップロードされているようです。

日本語用の言語別のデータもアップロードされています。


正式リリースがいつになるのかは不透明ですが、バージョン4.x の最大の特徴は今流行りのニューラルネットワーク技術の採用とのことです。 要するに深層学習とか強化学習とか言ってるアレ。

Long short-term memory(LSTM)による新認識エンジン*3

参考:4.0 with LSTM · tesseract-ocr/tesseract Wiki · GitHub

Ray Smithの講演資料:docs/das_tutorial2016 at master · tesseract-ocr/docs · GitHub

そもそもLSTM自体の仕組みがよくわかっていないので、OCR処理のどの部分にどういう形で組み込まれているのかはよくわかりません。


もう一つの新機能はTSV出力。地味だけど表形式のデータを読み取る場合には便利なはず。一応3.05ブランチ*4で入った新機能。

ただし、3.05というバージョンは今のところリリースされていません。されるかどうかは不明です。

macOS へのインストール

横着ですがHomebrew でインストールします。ビルドツールとして今までのautoconfとは別にcmakeも使えるようです。

依存ライブラリとしてOpenMPが必要になっています。そのため何も考えずに開発版をインストールしようとすると余裕で失敗します。

$ brew install tesseract --HEAD --with-training-tools
<skip>
lstm.cpp:22:10: fatal error: 'omp.h' file not found
#include <omp.h>
         ^
1 error generated.
make[2]: *** [lstm.lo] Error 1
make[2]: *** Waiting for unfinished jobs....
<skip>

ヘッダファイルが見つからないというエラーですが、そもそもmacOS 付属のllvmOpenMPに対応していないようです。
対処法は、ビルド用のコンパイラとしてgccをインストールするか、llvmの最新版をインストールするか、です*5

Homebrew で使用するコンパイラを切り替える最も簡単な方法として、--ccオプションにコンパイラのパッケージ名を指定する方法を利用します。

パッケージ名としてllvmを指定しても受け付けてくれないのでgcc6をインストールしました。本来であれば、brew edit tesseractするか、横着せずにgit cloneしてビルドする方が望ましいはずですが、面倒なので……。

$ brew install homebrew/versions/gcc6

非常に時間がかかります。泣きたくなります。バージョン番号なしのgccパッケージの場合、brewコマンド側がパッケージ名として認識しないので苦肉の策です。

依存ライブラリだけHomebrewでインストールして、コンパイラ環境変数CCとかCXX)で切り替える方が短時間で済んだような気もします。


さて本命。

$ brew install tesseract --HEAD --with-training-tools --cc=gcc-6

ビルドにさほど時間はかからないはずですが、--HEADを指定すると各言語用のデータを全部ダウンロードする*6のでそれなりに時間がかかります。

バージョンの確認

お約束。

$ tesseract -v
tesseract 4.00.00alpha
 leptonica-1.73
  libjpeg 8d : libpng 1.6.26 : libtiff 4.0.7 : zlib 1.2.8

やたらゼロの数が多い。


オプションを眺めてみる。

$ tesseract -h
Usage:
  tesseract --help | --help-psm | --help-oem | --version
  tesseract --list-langs [--tessdata-dir PATH]
  tesseract --print-parameters [options...] [configfile...]
  tesseract imagename|stdin outputbase|stdout [options...] [configfile...]

OCR options:
  --tessdata-dir PATH   Specify the location of tessdata path.
  --user-words PATH     Specify the location of user words file.
  --user-patterns PATH  Specify the location of user patterns file.
  -l LANG[+LANG]        Specify language(s) used for OCR.
  -c VAR=VALUE          Set value for config variables.
                        Multiple -c arguments are allowed.
  -psm NUM              Specify page segmentation mode.
  -oem NUM              Specify OCR Engine mode.
NOTE: These options must occur before any configfile.

Page segmentation modes:
  0    Orientation and script detection (OSD) only.
  1    Automatic page segmentation with OSD.
  2    Automatic page segmentation, but no OSD, or OCR.
  3    Fully automatic page segmentation, but no OSD. (Default)
  4    Assume a single column of text of variable sizes.
  5    Assume a single uniform block of vertically aligned text.
  6    Assume a single uniform block of text.
  7    Treat the image as a single text line.
  8    Treat the image as a single word.
  9    Treat the image as a single word in a circle.
 10    Treat the image as a single character.
 11    Sparse text. Find as much text as possible in no particular order.
 12    Sparse text with OSD.
 13    Raw line. Treat the image as a single text line,
            bypassing hacks that are Tesseract-specific.
OCR Engine modes:
  0    Original Tesseract only.
  1    Cube only.
  2    Tesseract + cube.
  3    Default, based on what is available.
  4    Neural nets (LSTM) only.

Single options:
  -h, --help            Show this help message.
  --help-psm            Show page segmentation modes.
  --help-oem            Show OCR Engine modes.
  -v, --version         Show version information.
  --list-langs          List available languages for tesseract engine.
  --print-parameters    Print tesseract parameters to stdout.

Page segmentation mode(psm)として11、12、13が追加されています。11と12は以前から存在したみたいです(ドキュメント未記載の隠しオプション扱い)。Sparse text と言われてもピンと来ませんが、文字(文章)がページ内に散らばっているイメージだと思います*7

特筆すべきは-oemオプションの方。

$ tesseract --help-oem
OCR Engine modes:
  0    Original Tesseract only.
  1    Cube only.
  2    Tesseract + cube.
  3    Default, based on what is available.
  4    Neural nets (LSTM) only.

ただし、Cubeエンジンは日本語非対応です。Cubeエンジンは将来廃止するという話だったはずですが、どうなるのかはわかりません。

お試し

まだアルファ版なので旧バージョンとの比較は先送りにします。

画像は過去記事から流用。

その1

f:id:atuyosi:20161201000524j:plain

その2

f:id:atuyosi:20161201003810j:plain

従来の認識エンジン

$ tesseract -oem 0 -psm 6  -l jpn image.jpg default_output
Tesseract Open Source OCR Engine v4.00.00alpha with Leptonica

最後の引数は出力ファイルの接頭辞です。この記事を書いている最中に思い出しましたが、ファイル名の接頭辞を指定する代わりにstdoutを指定すると標準出力に結果を出力してくれます……。

なお、設定を切り替えたい場合はコマンドライン引数の最後に指定できます(ドキュメント参照)。

$ cat default_output.txt
こ れは 日本語の文章です。 随 ヽろ はに ほへ と

まあ、平常運転です。サボらずに画像を拡大すべきです。-psmは6ではなくて7の方がベターかも。

その2

$ tesseract -oem 0 -psm 6  -l jpn image2.jpg default_output2
Tesseract Open Source OCR Engine v4.00.00alpha with Leptonica
$ cat default_output2.txt
オープンソースの光学文字認識ライブラリを試してみます。 )
Tesseractー〇CR は600gーeの資金援助宣受けてゝ開発されてしヽるりししヽです。
英数字の認識率は97%とか。漢字や平仮名はどっでしよつか。

画像を拡大すればもっと良くなったはず。

新しい認識エンジン

$ tesseract -oem 4 -psm 6  -l jpn image.jpg lstm_output
Tesseract Open Source OCR Engine v4.00.00alpha with Leptonica
Warning in pixWriteMemPng: work-around: writing to a temp file
Warning in pixReadMemPng: work-around: writing to a temp file

警告メッセージから見ると、一時ファイルに書き出して読み込んでる?

結果その1

$cat lstm_output.txt
これ は 日本 語 の 文章 で す 。 いろは に ほ へ と

結果その2

$ tesseract -oem 4 -psm 6  -l jpn image2.jpg lstm_output2
Tesseract Open Source OCR Engine v4.00.00alpha with Leptonica
Warning in pixWriteMemPng: work-around: writing to a temp file
Warning in pixReadMemPng: work-around: writing to a temp file
Warning in pixWriteMemPng: work-around: writing to a temp file
Warning in pixReadMemPng: work-around: writing to a temp file
Warning in pixWriteMemPng: work-around: writing to a temp file
Warning in pixReadMemPng: work-around: writing to a temp file

認識対象の行数が増えると警告メッセージの行数も増えるの?

$ cat lstm_output2.txt
オープン ソ ー ス の 光 学 文 字 認 識 ラ イブ ラ リ を 試し て み ま す 。 。 _
TesseractLOCR は Google の 賄 金 援 助 を 受 け て 開発 され て いる ら し いで す 。
英 数 字 の 認 識 率 は 9700 と か 。 漆 字 や 平仮名 は どう で しょ うか 。

文字間のスペースが気になりますが、許容範囲でしょう。2行目は格段に良くなっているように見えます。3行目は"%"と”漢”を ミスってます。

いままでイマイチだった日本語中の英単語の認識率が改善しているかも。

警告メッセージが気になりますが、認識率自体は改善しそうです。


せっかくなので画像を拡大してみます。

$ convert -geometry 120% image.jpg image2_large.jpg
$ tesseract -oem 4 -psm 6  -l jpn image2_large.jpg lstm_output2
Tesseract Open Source OCR Engine v4.00.00alpha with Leptonica
Warning in pixWriteMemPng: work-around: writing to a temp file
Warning in pixReadMemPng: work-around: writing to a temp file
Warning in pixWriteMemPng: work-around: writing to a temp file
Warning in pixReadMemPng: work-around: writing to a temp file
Warning in pixWriteMemPng: work-around: writing to a temp file
Warning in pixReadMemPng: work-around: writing to a temp file

さて、結果はどうか。

$ cat lstm_output3.txt
オ ー プ ブ プ ブン ソース の 光 学 文字 認識 ラ イ ブラ リ を 試し て み ます 。 。 __
TesseracrOCR は Google の 賞 金 援 助 を 受 け て 開発 され て いる らし い です 。
英 数字 の 認識 率 は 979%% と か 。 漢 字 や 平仮名 は ど う でしょ うか 。

1行目と3行目が不思議な出力になっています……。Google 翻訳も謎の文字列の繰り返しを出力するケースがあるので同じようなもの?


他にも試したいことはありますが、ひとまずここまで。

追記

tesseractコマンドのオプション形式が変化するようです。

Support standard parameter form --oem, --psm for tesseract executable by stweil · Pull Request #515 · tesseract-ocr/tesseract · GitHub

当面は 従来と同じ形式も使用できるようですが、今後は-psm(ハイフンは1つ)から--psm(ハイフンは2つ)になるようです。

一般的なGNUのコマンドと形式を合わせましょう、という変更です。影響の大きい変更はメジャーバージョンアップの時にやった方がいいよねとかなんとか。

まとめ

新しいOCRエンジンはこれまでよりは期待できるのではないでしょうか。

Google group のやり取りを読む限りでは従来の認識エンジンをどうするか、とか、メジャー番号が上がるついでに互換性のない変更を入れようとか色々と議論がされいます。

バージョン 4.0の前に3.05 をリリースするとかしないとか。

個人的にはTSVファイル出力機能だけでいいので3.05がリリースされる方がいいと思っています。


githubwikiにはSSE命令がどうのこうのという記述があるのでiOS用のライブラリへの移植は時間がかかりそうな雰囲気。

かなり適当なエントリになってますが以上です。

*1:安定版リリースだろうと転んでも泣かないのがOSS

*2:tessdata リポジトリの方を参照

*3:ニューラルネットワーク関連の技術を活用したということしか理解していないです

*4:いつのまにか3.05devから3.05にリネームされてる

*5:llvm の clang 3.9 からOpenMPに対応したとのこと

*6:tesseractのFormulaがそうなっているせいです

*7:試してないです