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

tesseract-ocr の言語データ(jpn.traineddata)について(その1)

OCR tesseract

ブログのテーマを変えました。以前のテーマだと表が見づらかったので。

引き続きフリーのOCRエンジン、tesseact-ocr について。プログラミングがらみの記事です。かなりグダグダです。

アルゴリズムはさっぱりわからないので、言語データ(辞書データ)の方を調べてみる。

具体的には、GitHubで公開されている、langdata配下のファイル。このファイルをもとに各言語のtraineddataファイルが作成されるという認識であってるはず。

目次

調査対象と情報源

調査対象

tesseract-ocr · GitHubのlangdata、tessdata。langdataのファイルから生成されたものがtessdata 配下のXXX.traineddata のはず。

基本的にはlangdata/jpn が重要だが、langdata 直下にもひらがな・カタカナ・漢字用*.xheightsのファイル*1など共通のファイルが存在する。

情報源

GitHubにプロジェクトが移動した関係で、基本的にGitHubWikiを参照すればいい。tesseract配下にあるtraining ディレクトリ配下にある辞書データビルド用のスクリプトと内部で呼び出されているコマンドのmanページ。

github リポジトリ

日本語向けのデータに限定します。

langdata/jpn

どうみてもここがご本尊。

ファイルは以下のとおり。よく分からないファイルは対応するほかの言語のファイルと比較してみた。

ファイル名 変換後のファイル 備考
desired_characters ? 半角英数字と○囲み数字が列挙されている。
forbidden_characters ? 16進でコードポイントが列挙されている。
jpn.config as is アジア系の言語はそれぞれ設定ファイルが用意されている模様。
jpn.numbers jpn.number-dawg 数詞(単位とか)。日本語用のファイルには空白文字だけの行が4行…?
jpn.params-model as is パラメータが列挙されている。どうやって生成するかは不明。
jpn.punc jpn.punc-dawg 単語を囲むタイプの記号のリスト。 日本語向けにはなっていない模様。
jpn.training_text ? 学習用のテキスト。半角スペース区切りで変な単語が列挙されている
jpn.training_text.bigram_freqs jpn.bigram-dawg jpn.training_text についてN-gram(N=2における)で分割した単語の出現頻度データか?
jpn.training_text.unigram_freqs ? jpn.training_text について N-gram(N=1における)で分割した単語(文字)の出現頻度データか?
jpn.unicharambigs as is 認識結果の変換マッピング。ファイル形式にv1とv2がある。例えばシングルクォートが2個連続した場合はダブルクォートに置換する等。必ず置換するかどうかは指定可能。
jpn.wordlist jpn.word-dawg? 単語リスト。これは単純に追加すればよさそう。

jpn.numbers、jpn.punc 、jpn.unicharambigs はwordlist2dwag コマンドでオプション辞書化される。dwag(directed acyclic word graphs) というのは辞書データ構造の一つで、メモリ消費量の少ないTRIE(トライ木)と理解しておけばよさそう。

個別ファイルについて

desired_charakters と forbidden_characters は触らないことにする。jpn.configは後回し。

jpn.numbers

英語用のファイルと比較すると、数字の前後に来る文字列を列挙するファイルらしい。 数字が来る部分を半角スペースで表現するっぽい。「年」「月」「日」とか「個」とか「冊」を指定すればいいはず。ただし、数値(数字)の桁数に応じて半角スペースの数を変える必要がある。

追加するとすれば、

  日
  月
    年
第 章
   円
 ,   円

みたいに書けばいい。ただ、何でもかんでも追加していいのかは疑問。

jpn.params-model

詳細不詳。Googlebotの集めたデータを解析したのだろうか? それともGoogle日本語入力? 解析結果の精度向上には寄与しているとみてよさそう。

jpn.punc

組版用語でいうところの約物(</rpやくもの)</rpか。 要領はjpn.numbersと同じ。書式としては、単語を囲む記号の間に半角スペースを入れればいい。例えば以下のようにする。

( )
「 」
『 』

ただ、tesseract 3.03 or 3.04 で使う分には鉤括弧の認識率は悪くなさそうなので、特に追加する必要はない、かな。

jpn.training_text

これも詳細不詳。このファイルを画像化し、さらになんらかの方法でboxファイルを生成してフォントを学習させているハズ。 要件として、対象言語において使われるすべての文字が最低一度は出現するようなテキストでが要求されているのは理解できるが…。

文字の出現頻度を元にランダムに生成したのかもしれない。

また、jpn.training_text.bigram_freqsはともかく、jpn.training_text.unigram_freqsの方はどういう役割なのか不明。

jpn.unicharambigs

まぎらわしい文字についてのマッピングルール。本来一文字のものが2文字に認識されるようなケースに対応させるもの。シングルクォートが2つ連続したらダブルクォートに置き換えるとか、漢字の「へん」と「つくり」が分断されてしまう場合など。書式がv1とv2の2種類ある。

v1
1        は        1        ば        2

一行目がv1ならv1フォーマット。書式は、タブ区切りで、

置換前の文字数        置換前の文字        置換後の文字数        置換後の文字        フラグ

最後のフラグは必ず置換するかどうかのフラグ。"1"なら必ず置き換えるが(mandatory)、”0"の場合は単語辞書にあるかどうかで判断する(optional)と書いてあるように読めるが、実際は違う模様。ソースを見ると値が拡張されている。

ソースコードにリンク貼ってあるのはいいけど、素直にドキュメントの修正をお願いしたい。以下、githubより転載。

enum AmbigType {
  NOT_AMBIG,        // the ngram pair is not ambiguous 
  REPLACE_AMBIG,    // ocred ngram should always be substituted with correct
  DEFINITE_AMBIG,   // add correct ngram to the classifier results (1-1)
  SIMILAR_AMBIG,    // use pairwise classifier for ocred/correct pair (1-1) 
  CASE_AMBIG,       // this is a case ambiguity (1-1) 

  AMBIG_TYPE_COUNT  // number of enum entries
};

上記を踏まえると、必ず置換させたいなら"1"、曖昧さを示したいなら、REPLACE_AMBIG(2)、対応関係?で扱わせたいなら SIMILAR_AMBIG (3)、大文字小文字に対する曖昧さ?がCASE_AMBIG (4) か。配布されている jpn.unicharambigs、ズレてないか。REPLACE_AMBIGとSIMILAR_AMBIGはレイヤが違うということか?。また、日本語のひらがなにおける「あ」と「ぁ」の関係は英語の"A"と"a"の関係とは文法上意味合いが違うはずなんだろうが、大丈夫なのかこれ。

v2フォーマットの場合はもっと簡単で、以下のようになる。(ver. 3.03以降か)。

v2
置換前の文字        置換後の文字       フラグ

フラグはv1と公式wikiでは"1" の場合は必須(mandatory)、"0"なら単語辞書を検索したうえで判断(optional)と書いてあるように読めるが、実際は違う模様。風通に拡張されているのであろう。

仮に追加するなら、

2         し ゝ        1        い        2
2         丿 ヾ        1        パ        2
2         か ゝ        1        が       2

とかひらがなの認識ミス対策だろうか*2。 また、数字の"1"や"|"など縦の線に似た文字や記号をハイフンやマイナスに対応させるマッピング(jpn.unicharambigs 20-24行目下記参照)は削除した方がいいかもしれない*3。というか、横書き文書の場合はブラックリスト指定するか、縦書き用と横書き用で言語データを分ける必要があると思う。

1       l       1       ー      1
1       |      1       ー      1
1       I       1       ー      1
1       1       1       ー      1      ← 少なくともこのフラグの値は2。
1       |       1       ー      1

極め付けにこのファイルはそのうち廃止するとかwikiに書いてあるような。

jpn.wordlist

なんかこう編た単語の羅列? 謎な単語がまざっている。「ITmedia」とか「ホリエモン」とか結構今時な単語をセレクトしているあたり、ちょっと面白い。yjulmWidgetMdsとか謎すぎる。CSSのクラス名だろうか。

「Institute」とかなぜか合字(リガチャ:Ligature)使ってたり??? 同じ単語で合字を使った表記と、そうでないものが結構あるので意図的なのか。確かにマトモに組版された印刷物なら必要になるか。ただYosemiteのiTerm2で"ct"の合字?が化けてるという。

Googleがスポンサーなので検索インデックスから頻度を割り出した単語なんだろうか。

そのほか

Tesseract 4.0系で仕様が変わるようなのでリライトするか、別途整理し直す。


とりあえずここまで。

*1:mftrainingコマンド用のようだが参照されていない?

*2:文字サイズ次第なところはある

*3:縦書き文書用なのだろうか?