ImageMagick
PDF
QRcode
zbar
xpdf

PDFファイル上のQRコードを認識させる際のひと工夫

More than 1 year has passed since last update.

このご時世になってもキーボード入力は苦手という方が多く、多くの人に使ってもらうシステムを作る際は、この辺がすごく障害になります。ということでそのような方もサポートすべく、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は必須ではないですが、後の記事中に出てくるのでインストールしてあります。

サンプルQRコード

Qiita_QR.png

使い方は簡単で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連休がこんな作業でつぶれてしまった。。。





  1. そもそも「PDFファイルそのもの」に「解像度」という概念がないようです http://blog.antenna.co.jp/PDFTool/archives/2007/01/25/