11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-03-20

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

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?