zinniaでお手軽手書き文字認識

@haoyayoi さんから引き続き iOS Advent Calendar 14日目の記事です。

アプリ自体はまだ2本しか出していないわたなべです。
iOS Advent Calendar はそうそうたるメンバーがとても参考になる記事を書かれているのでいろいろ勉強させてもらってます(><)!
こんな私ですが、@k_katsumiさんに背中を押されたので、最近試している手書き文字認識エンジン zinniaについて書いてみます

zinnia ってなに?

zinnia は Taku Kudoさんが作成された「手書き文字認識エンジン」です。このエンジンに文字のストローク座標の連続データを渡すことで、高速に文字を認識することができます。確からしさ順にN個の結果を取得することができるので、変換候補を表示したりも出来ます。

iPhone上で動かすには...

@FLCLjp さんが作成されたサンプルが Githubで公開されているのでそれを見るのが一番だと思います。
実際に動かしてみると以下のようにしっかり認識できるはずです。


f:id:kaz_29:20111214124235p:image:w360

で、これだけだと全く中身がない話になってしまうので(^^; もう少し書きますよ〜。

認識率は...

zinniaのサイト上で配布されれいる 認識用モデルファイル(Zinnia-Tomoe) を使って試用した感じではかなり認識率は高いと思います。ただ画数の少ない文字はどうしても正しく認識してくれないケースが多かったです。まぁ、仕方が無いですね。

ですが、特定の文字種に限って(たとえば数字だけとか...)認識できればいいのであれば、自前で認識用モデルファイルを作ってしまえばかなり認識率を高めることはできそうです。

実際、私を含め身近な数人に数字のストロークを入力してもらい作成した認識用モデルファイルを使うと、ほぼ100%に近い確率で認識できました!

認識用モデルファイル

認識用モデルファイルはS式で記述された学習データを元に、zinnia付属のコマンドで作成します。公式ページにも記述がありますが実際の形式は以下のような形式です。

S式フォーマット

(character
 (value 認識したい文字)
 (width キャンバス幅)
 (height キャンバス高さ)
 (strokes
   ((0画目x 0画目y) ... (0画目x 0画目y))
   ((1画目x 0画目y) ... (1画目x 1画目y))
   ((2画目x 2画目y) ... (2画目x 2画目y))
   ...))


フォーマット自体はとてもシンプルなのですが、このデータを作るには実際に認識させるデバイス上で文字のストローク情報を集める必要があります。おそらくzinniaを使っている方はみんな何らかの文字収集ツールを書いてるんじゃないかなぁと思います。


ということで、自分用にiPhoneで動作するアプリを書いたので解説します。

手書きストローク収集ツール(TegakiStroke)

iPhone-Zinnia-TegakiStroke@GitHub


もともと自分用に収集アプリを書いていたのですが、不特定多数の人のストロークを集めたかったので、データをサーバーに上げる方式で作っていました。これだとお手軽に試してもらうわけにはいかないので、すべてのデータをローカルなsqlitedbに保存する形で作り直しました。テーブル構成は以下のようなとても簡単な作りになっているので、、付属のtemplate.dbを覗いてもらえればわかるかと思います。

モデル情報(models) => モデルに含まれる文字情報(characters) => 実際のストローク情報(strokes)


以下がschema構築用のsqlファイルです。

CREATE TABLE models (
id INTEGER PRIMARY KEY,
name TEXT,
created
);

CREATE TABLE characters (
id INTEGER PRIMARY KEY,
model_id INTEGER,
character TEXT,
created
);

CREATE TABLE strokes (
id INTEGER PRIMARY KEY,
character_id INTEGER,
strokes TEXT,
created
);

INSERT INTO models (name,created) values ('number', '2011/12/13');

INSERT INTO characters(model_id,character, created) values(1,'0','2011/12/13');
INSERT INTO characters(model_id,character, created) values(1,'1','2011/12/13');
... 以下略

実際の動作は...

まず入力するモデルを選んで...

f:id:kaz_29:20111214141228p:image:w360

「文字入力」ボタンを押して....

f:id:kaz_29:20111214141229p:image:w360


実際に文字を入力します....

f:id:kaz_29:20111214141230p:image:w360


登録されている文字の入力が終わると、文字一覧に戻ってくるので「S式書出し」ボタンを押せば完了です。

f:id:kaz_29:20111214141229p:image:w360


書きだしたデータは、Documentsフォルダに保存されていますのでiTunes ファイル共有か何かで取り出してください。


f:id:kaz_29:20111214141231p:image:w360


吐き出された、*.sファイルをzinnia付属の zinnia_learn にかければ実際に使えるモデルファイルが出来上がります。
またアプリ内部で使用している sqliteのファイルもDocumentsフォルダに保存してあるので、適宜モデルや文字を追加するなり、自前でstrokeデータを抜き出して加工するなり、いろいろできるのではないかと思います。

まとめ

zinniaを使うと非常に簡単に手書き文字認識を実装できます。実際のアプリで使うには色々と工夫が必要かと思いますが...。

ソースはGitHubに上げてありますので、試してみてください!
若干やっつけ感が漂っているところもありますが(^^; 、時間ができたら機能を追加していこうと思ってます。

明日は @hIDDEN_xv さんです!