2012年8月25日土曜日

画像から文字抽出(ImageMagick Tesseractの利用)

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
スクワットのフォームが悪くて、膝を少し痛めてしまった、たなけんです。
本エントリではClojureを用いてシェルを操作し、画像データを加工し、必要となる文字列を抽出する方法を記載します。

事の発端

大学院の授業でシュミレーションゲームを行っており、そのデータをClojureを用いて分析していることを、以前の記事で紹介しました。
その後、あるチームメイトから「このpdfファイルのデータも使えない?」と聞かれ、『pdfなら文字情報を抽出するのも簡単だし、問題ない』と考え、二つ返事でデータの抽出を引き受けたのが、今回の事の発端です。
以前、利用したデータはcvs形式だったので、データ読み取りに何の工夫も必要ありませんでした。今回も、xpdfなど既存のソフトウェアを使えば、文字情報が簡単に取り出せると考えていたのですが、意外な落とし穴がありました。実は
ファイル拡張子はpdfであるものの、実際のデータは画像
だったのです。
(xpdfでテキスト抽出処理をした結果、一文字も抽出されませんでした。不審に思い、その後手動で文字をコピーしようと文字部分をマウスでドラッグしてみて、データが画像であることに気が付きました。。。)
以前より、画像から文字を抽出(OCR)することには関心があったので(※1)、ImageMagickとTesseractを利用して、画像データを抽出することにしました。

実装方針

翌日には結果を渡さないといけないという、時間的制約から、手作業で作業内容を確立し、プログラムでそれを自動化するという方針としました。

  • それぞれの処理(画像加工、OCR)はシェルからコマンドを実行する(作業内容)
  • シェルの起動や、コマンド発行をClojureから行う(自動化)


ImageMagickとTesseractのインストール

どちらもMacPortsからインストールしました。
Tesseractは本体だけではなく、英語バージョンの学習ファイル(辞書)もインストールしました。
特に問題なく、スムーズにインストールすることができました。
(パラメータなどは全てデフォルト値)

作業内容

作業内容および手順は、以下の通り。

  1. 複数ページを含むpdfファイルを、個別の画像ファイルに分割する(同時に解像度も上げる)
  2. 各画像ファイルから抽出対象の文字が含まれる部分を切り取る
  3. 切り取ったファイルの文字情報を読み取る
  4. 読み取った文字情報を整形し、レポートを出力する(本エントリでは記載を省略)


ソースコード

形式変換&ページ分割


ImageMagickのconvertコマンドで複数ページを含むpdfファイルを個別のpngファイルに変換します。(-formatオプションを付けなくてもフォーマット変換出来ました。。。)
解像度指定しなかった場合、画像が荒すぎてOCR精度が落ちるため、-densityオプションで解像度を設定、-unitsオプションで解像度の単位を指定しています。
Clojureで実装した際の注意点としては、clojure.java.shell/sh関数を利用する際、通常(clojure.java.shell/sh コマンド オプション1 オプション2 ...)のように、コマンドのオプションを(リストではなく)第2引数、第3引数...と指定する点があげられます。
今回の実装では、オプションを別関数で生成しているため、apply関数を用い、(apply clojure.java.shell/sh コマンド オプションのリスト)のように実行しました。
またオプションは一続きの文字列ではなく、それぞれのオプション(およびその値)が分割されている必要がある点も注意が必要でした。例えば、"-density 300x300 -units PixelsPerInch"を第2引数に渡すとエラーとなり、正しくは"-density" "300x300" "-units" "PixelsPerInch"をそれぞれ、第2引数、第3引数、第4引数、第5引数として渡さなくてはいけません。
上記の点さえ気をつければ、特に問題なくclojure.java.shell/sh関数を使うことが出来ます。(シェルコマンドをClojureで自動実行できれば、いろいろと便利ですね)

画像切り取り


形式変換&ページ分割と同様、切り取るサイズと位置を指定してconvertコマンドを実行します。ページ毎に切り取り部分が異なるため、ファイル名に応じた切り取りサイズ&位置を渡しています。

文字情報の読み取り


切り取り済みの画像ファイルを順に読み込み、テキストファイルを生成します。
オプションの-psmは画像の中でさらに読み取る部分を指定するオプションです。
画像全体を読み込み対象とするため、-psmに6を指定しています。

捕捉: psm (pagesegmode)一覧


上記のように、一行とみなしたり、円で囲った部分だけ読むなどのオプションがあります。

調査中に見つけたライブラリ

今回は、時間的制約から、プログラムの再利用性(汎用性)よりも、実装の手早さを重視しました。そのため、あまり調査に時間を掛けることはできませんでした。しかし、少しだけ行った調査の過程で、面白そうなライブラリを発見したので、この場を借りて紹介したいと思います。

im4java

ImageMagickのコマンドを網羅したJavaライブラリ。<im4javaのwebサイト>
複雑な処理を自動化するのであれば、使ってみたいといった印象。
学習コスト削減のため、今回は利用しませんでした。

Tess4J

TesseractのJNIラッパー。<Tess4Jのwebサイト>
まだMacでの動作に問題があるようだったので利用を回避。
2012年8月8日にversion 1.0 beta 5がリリースされたばかりの新しいライブラリの様なので、今後の成熟に期待。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間2時間(テキスト抽出後の処理は除く))

※1: OCRを組み込んだ、アプリケーション、サービスについての構想は別エントリにて紹介したいと思います。

0 件のコメント:

コメントを投稿