このご時世になってもキーボード入力は苦手という方が多く、多くの人に使ってもらうシステムを作る際は、この辺がすごく障害になります。ということでそのような方もサポートすべく、QRコードが記載されているPDFファイルを認識させてサーバに取り込むような機能を作ろうか、と思い立ち色々実験していたら以外と嵌まったので、ここで共有しておこうと思います。
QRコードの生成方法は色々ありますのでここでは触れません。
なお、QRコードは(株)デンソーウェーブの登録商標です。使い方などの注意事項は
http://www.qrcode.com/faq.html
を参考にしてください。
QRコードの認識自体はZBarを使えばすごく簡単
すべてCentOS7上で実行しております。まずは、zbarという先人が作ってくれた素晴らしいツールをインストールすることから始まります。EPELリポジトリにありますので、EPELが使えない人はまずはこの作業を行います。(必要に応じてrootになるなり、sudo付けるなりしてください)
$ yum install epel-release
EPELが使える状態になれば、以下のコマンドで一発でZBarが入ります。
$ yum install zbar ImageMagick ImageMagick-devel
imagemagickは必須ではないですが、後の記事中に出てくるのでインストールしてあります。
使い方は簡単でzbarimgというコマンドに画像ファイルを指定するだけです。
$ zbarimg Qiita_QR.png
[ここに認識した内容が表示される]
scanned 1 barcode symbols from 1 images in 0 seconds
画像ファイルに複数のQRコードが入っていれば、複数分出力してくれます。認識順はイマイチよく分からなかったので、その辺も対応するならあらかじめimagemagickでcropするなどが必要かもしれませんが、今回の私の作業の要件では不要だったので確認してません。
スキャナから取り込んだPDFファイルでQRを認識させようとすると認識率がガッツリ下がる
いやー、QRの認識なんて簡単w 楽勝w(自分で作ったツールでもないのにw)なんて思いつつ、PDFファイルを認識させる実装を進めていったところ、途中で上手く認識しないことが出てくることに気づきました。
$ zbarimg scan.pdf
scanned 0 barcode symbols from 3 images in 0.25 seconds
WARNING: barcode data was not detected in some image(s)
things to check:
- is the barcode type supported? currently supported symbologies are:
EAN/UPC (EAN-13, EAN-8, EAN-2, EAN-5, UPC-A, UPC-E,
ISBN-10, ISBN-13), Code 128, Code 93, Code 39, Codabar,
DataBar, DataBar Expanded, and Interleaved 2 of 5
- is the barcode large enough in the image?
- is the barcode mostly in focus?
- is there sufficient contrast/illumination?
コンピュータ上で直接出力したQRコード入りのPDFは認識できるのですが、スキャナで取り込み解像度300dpiで取り込んだQRコード入りのPDFだと認識できなくなるのです。QRコードを大きくしたり、imagemagickで無理やり画像を補正すると認識できるようにはなるのですが、それでも異様に認識率が悪い。そもそも取り込んだPDFファイルも若干コントラストは低いが、見た感じ解像度も十分足りているし。。。Zbarimgコマンド自体に調整するオプションもないようですし、困った…
なんとなくPDF画像自体が悪いのか?と思ってimagemagickについてるidentifyという画像を調べるコマンドに-verboseオプションを付けて見てみると
$ identify -verbose QiitaQR.pdf
Image: QiitaQR.pdf
Format: PDF (Portable Document Format)
Class: DirectClass
Geometry: 842x595+0+0
Resolution: 72x72
Print size: 11.6944x8.26389
Units: Undefined
Type: TrueColorAlpha
Endianess: Undefined
Colorspace: sRGB
Depth: 16/8-bit
あれ? 画像のPixcel数が842x595になってる。PDF内に埋め込まれてる画像はAdobeのPhotoshop上で見ると3506×2480なんですが、なにゆえ??? Unitsの項目がUndefinedってのも??? たしかにimagemagickでconvertしただけで極端に画像がぼやける。ZBarも内部でimagemagickと同じ画像解析エンジンを使ってるようですので、どうもPDF内の解像度?1を正しく認識できず、粗い画像で解析してしまうためQRコードを認識できないようです。AdobeのAcrobatなどで正しく設定することは可能かもしれませんが、すべてのPDFファイルにこれを期待するのも無理な話です。もし、この辺で正しくPDFファイルを認識できる方法をご存じの方は教えてください(以下の手順が面倒なのでw)
違うアプローチでトライ 〜画像を抜き出す〜
しかたないので、違う方向からゴールを目指すことにしました。PDFファイル内の画像を抜き出して、それをZBarにかければどうか?と。PDFから画像を抜き出すのはpdfimageというコマンドを使えば良いようで、xpdfをインストールすれば使えます。
$ yum install xpdf
これでPDFファイルから画像を抜き出します。今回はスキャナから取り込んだ3ページ分連結しているPDFファイルを使います。
$ pdfimages scan.pdf out -png
$ ls -al
-rw-r--r-- 1 root root 26110061 3月 20 14:43 scan.pdf
-rw-r--r-- 1 root root 5664271 3月 20 14:49 out-000.png
-rw-r--r-- 1 root root 5663376 3月 20 14:49 out-001.png
-rw-r--r-- 1 root root 5665273 3月 20 14:49 out-002.png
とやると、out-000.png、out-001.png、out-002.pngと3ページ分のpngファイルができあがります。ちなにみ -png オプションを付けないと.ppmというビットマップフォーマットの画像になります。処理時間は圧倒的に.ppmの方が早いですが、ファイルサイズは数倍になります。この辺はお好みで。
できあがったpngもしくはppmファイルをZbarにかけると、問題なくQRコードが認識されます。複数ページのファイルはちょっと手間ですが、なにかしらのスクリプトをかませばなんとかなりそうです。
ああ、3連休がこんな作業でつぶれてしまった。。。
-
そもそも「PDFファイルそのもの」に「解像度」という概念がないようです http://blog.antenna.co.jp/PDFTool/archives/2007/01/25/ ↩