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

SwiftOCRというOCRライブラリを試してみた

Mac OCR Swift iOS

某所で紹介されていたSwiftOCRというライブラリ付属のサンプルを試してみたので一応?

Tesseract より高速、省メモリらしい。一応昨年末の時点でSwift 3にも対応している。

一行のテキスト、それもシリアルナンバーのようなランダム英数字に向いているとのこと。

github.com

githubのissueトラッカーを見る限り、複数行のテキストのOCRには対応していない模様。

日本語の解説は以下が詳しい(というか他に発見できず)。

Swiftで書かれたOCRライブラリ「SwiftOCR」をiOS実機で試してみた - Qiita

付属のプロジェクトを試す

まずは付属のサンプルを試す。shu223氏の記事によると、アルファベットの大文字と数字のみ学習した状態とのこと。

$ git clone https://github.com/garnele007/SwiftOCR.git
$ cd example/iOS/SwiftOCR\ Camera/
$ open SwiftOCR\ Camera.xcodeproj

Xcode が起動するので、スキーマSwiftOCR Cameraに切り替えてビルドしてやれば起動する。

f:id:atuyosi:20170311090752p:plain

下記のエラーに遭遇した場合は、プロジェクトナビゲーターの画面から"Provisioning Profile" を設定する。

Signing for "SwiftOCR Camera" requires a development team. Select a development team in the project editor.
Code signing is required for product type 'Application' in SDK 'iOS 10.2'
Code signing is required for product type 'Application' in SDK 'iOS 10.2'
Code signing is required for product type 'Application' in SDK 'iOS 10.2'

実行した結果。

f:id:atuyosi:20170311092018j:plain

薄いグレーの帯状のエリアにテキストが入るようにして"Take Photo"を押すと画面の上部に認識結果のテキストが表示される。

真ん中下のスライダで拡大倍率を調整できる。

“ISBN4"という文字列に対して"TSBN4"になっている。数字の"3"をすんなり読んでくれないなど不安定。

学習ツールと他の文字種

小文字アルファベット

一度Xcodeを閉じて、SwiftOCR\ Trainingに移動。

$ cd ../../OS\ X/SwiftOCR\ Training
$ open SwiftOCR\ Training.xcodeproj

テキストフィールドに文字列が入力されているのでアルファベットの小文字と数字ハイフン、円記号を追加。

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-¥0123456789

書体は"Times New Roman" とは “Tahoma” とかメジャーな英語用フォントのみ。

小文字と記号の一部を追加しておもむろに"Start Training"。終了すると表示が元に戻るので、"Test"を実行。

“Save"をクリックするとデスクトップにOCR-Networkというファイルが出力される。

むやみに書体を増やすと"Test"の時点で認識率が下がる……。

トレーニング時点で79.2%は不満だけどとりあえず小文字対応版のデータをコピーして実機テスト(斜体フォントなし)

$ cp ~/Desktop/OCR-Network ../../../framework/SwiftOCR/OCR-Network

パスは環境に応じて変更。

swiftOCR.swiftの開いて、 recognizableCharactersを修正

public var recognizableCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-¥0123456789"

必ずトレーニングした時と同じ文字列にすること。

f:id:atuyosi:20170312225113p:plain

文字の種類や順序が学習させた時と異なると、"Take Photo"の直後にエラーで落ちる。

f:id:atuyosi:20170312223615j:plain
イマイチ認識できていない上に、単語と単語のスペースを無視している。


f:id:atuyosi:20170312221251j:plain
数字はそこそこ認識するが、小文字との混同が発生している。

ただ、文字を認識した位置と、他の候補の情報を出力してくれるので、前後が数字なら数字の候補を優先するような後処理ロジックを仕込むことは可能。

SwiftOCR.SwiftOCRRecognizedBlob(charactersWithConfidence: [("a", 0.398129016), ("2", 0.382261425), ("3", 0.0667025894)], boundingBox: (262.0, 20.0, 19.0, 27.0)), 

カタカナ

この辺から文字のリストをサクッと借用。

ヒラギノフォントとか游明朝・游ゴシック体あたりを学習させてみた。

「ひらがな」は試す気が起きず。

ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ

長音符(ー)と中黒(・)が抜けているので注意。

f:id:atuyosi:20170312225037p:plain

トレーニングの時点で43%。小書きカナを除去すると改善するはずだけど、それはそれで違う気もする。

全部「ポ」になって使い物にならず。アルゴリズムの限界なのか?

気になった点

  • アルファベットの小文字を学習させると認識率が下がる(例えば"x"と"X"、"v"と”V”など形状が同じで大きさが違うもの)
  • イタリック体を学習させると認識率が下がる(特にBold Italic)
  • 数字とのゼロと小文字の"o"の判別ミス
  • 小文字を学習させると数字の認識率も下がる
  • 文字と文字がくっついていると認識できない
  • 文字と文字のスペースを認識していない
  • 文字列が複数行になっている場合、1行目しか認識しない

最大の欠点は複数行の認識に対応していない点。

まとめ

認識結果が安定しない印象。確かにメモリ消費も少ない。認識対象の文字がアルファベットの大文字と数字、記号の一部に限定できるケースならなんとか使えそう。ただし、二値化処理と行の検出を自力でやる必要がある。

ただ、Tesseract 3.x も単語辞書をオフにしてやれば似たような使い方はできるし、シリアルナンバー用の学習データも存在している*1

Tesseract もバージョン4系はLSTMベースのニューラルネットワークを採用した結果、高速化しているはずなのでリソース消費量だけが長所だとあまりメリットにはならない。


中途半端な記事になってしまったけど今後に期待。

それでは。

*1:Homebrew のtesseactパッケージのオプションで"snum.traineddata"というファイルをダウンロードできる