Calendar

December 2010
M T W T F S S
« Nov   Jan »
 12345
6789101112
13141516171819
20212223242526
2728293031  

ZBar でバーコード読み取り


はじめに

昔買った Webカメラ(USBカメラ)をバーコードリーダーとして使えるか試そうと、ちょっと実験してみました。
ZBar というバーコード読み取りライブラリ使うことで、簡単に実現出来ました。

ZBarとは

バーコードを読み取るためのオープンソースのライブラリです。

(Webサイト) – http://zbar.sourceforge.net/index.html

ZBar の Zの意味、ロゴマークを見て納得しました。 バーコードリーダーがスキャンしてる軌跡ですね。(たぶん)

(ZBarのロゴマーク)


ZBarには次のような特徴があります。

  1. 複数のバーコード規格に対応

    EAN-13/UPC-A(JANコード), UPC-E, EAN-8, Code 128, Code 39, Interleaved 2 of 5, QRコードに対応します。
    JANコード と QRコードに対応してるので、個人利用のほとんどのニーズを満たせると思います。


  2. クロスプラットホーム

    Linux/Unix, Windows, iPhone で動作します。

    Mac OS X 向けも予定されているようです。
    [参照] On the Horizon – http://sourceforge.net/apps/mediawiki/zbar/index.php?title=Development_Roadmap#On_the_Horizon


  3. 複数の入力方式に対応

    動画(ビデオストリーム)と画像ファイルからの入力に対応します。

    • 動画からバーコードを自動検出し、値を読み取ることが出来ます。

    • 画像は PNG, JPEG, TIFF, GIF, Postscript,etc… と多種多様なフォーマットに対応します。

      画像処理に ImageMagick を利用しているので、 ImageMagick が対応、 イコール ZBar も対応 という仕組みです。

      ImageMagickでは、

      variety of formats (over 100) including DPX, EXR, GIF, JPEG, JPEG-2000, PDF, PhotoCD, PNG, Postscript, SVG, and TIFF.

      と謳っているので、画像フォーマットで困る人は少ないと思います。


  4. 複数言語に対応

    C, C++, Python, Perl に対応します。 C++ にはクラスライブラリが用意されています。
    Pythonで使えるという事が、今回のライブラリ選択の決め手になりました。


  5. 組み込み用途を意識

    Webサイトでは “no floating point operations” と書いてあります。 組み込み用途で採用しやすいように、実数演算を避け、整数演算のみで処理してるようです。
    もっとも、近頃の組み込み向けCPUはどんどん高性能化してきてるので、あまりアピールポイントにはならないかも知れませんが…

    他にも、「高速」「省メモリ」ということですが、他のライブラリと比較したことがないので、私には判断出来ません。

    ただし、FAQのページ では、“Why does zbarimg use ImageMagick?”に対し、 “Yes it’s huge and slow, but ImageMagick is easy to integrate” と書いてあります。

    組み込み向けに使うときは、ZBar よりも ImageMagick をどうするかの方が課題かもしれません。


  6. ライセンスは LGPL2.1

    商用利用にもひとまず安心です。

準備

Ubuntu の場合

動作検証に使用した Ubuntu を例に説明します。 Ubuntu では ZBar のパッケージが用意されているので apt-get で簡単にインストール出来ます。

libzbar

まず、ライブラリ本体をインストールします。

$ sudo apt-get install libzbar0

ただし、これだけではライブラリ(/usr/lib/libzbar.so)がインストールされるだけで何も出来ないので、引き続き以下のパッケージもインストールします。

zbar-tools

ZBarを使ったバーコード読み取りツールをインストールします。

$ sudo apt-get install zbar-tools

次のツールがインストールされます。 今回はこのツールを使って動作確認を行います。

  • /usr/bin/zbarcam
    カメラ映像からバーコードを検出し、読み取るツールです。

  • /usr/bin/zbarimg
    画像ファイルからバーコードを検出し、読み取るツールです。
libzbar-dev

C/C++ から使う場合にインストールします。ヘッダファイルがインストールされます。

$ sudo apt-get install libzbar-dev
python-zbar

Python から使う場合にインストールします。

$ sudo apt-get install python-zbar
libbarcode-zbar-perl

Perl から使う場合にインストールします。

$ sudo apt-get install libbarcode-zbar-perl
zbarのソースコード

ドキュメントやヘッダファイルを読むより、サンプルコードを読んだ方がわかりやすいので、ソースコードも取得します。

ソースコードを展開するディレクトリに移動して、次のコマンドを実行します。

$ apt-get source libzbar0

apt-getが使えない場合、以下のページからダウンロード出来ます。

http://zbar.sourceforge.net/download.html

ライブラリ本体のソースだけでなく、サンプルコード、及び、zbar-tools でインストールしたツール類のソースもあるので参考になります。

qrencode

QRコードの画像ファイル(PNG形式)を作成するツールです。 自分でQRコードを作りたい人はインストールして下さい。

$ sudo apt-get install python-zbar

次のように使用します。

(使い方)

qrencode -o [画像ファイル名] [メッセージ]

画像ファイルはPNG形式のみです。

メッセージには日本語(UTF-8)も使用出来ました。-kオプションでシフトJISも対応するようです。 その他、詳細は manページを参照して下さい。

Webカメラ(USBカメラ)

これがないと始まりません。 手持ちのWebカメラをPCに繋いで下さい。 私は logitech の V-UAV35 という古いWebカメラを使用しました。

デバイスを認識出来たかどうかは、次のように確認します。

ビデオのデバイスファイルが有るか調べる

カメラが正しく認識されると、/dev/video* という名前のデバイスファイルが作成されます。(* は 0,1,2… と認識順に付番)

(カメラが有る時)

$ ls -l /dev/video*
crw-rw----+ 1 root video 81, 0 2010-12-14 01:39 /dev/video0

(カメラが無い時)

$ ls -l /dev/video*
ls: /dev/video*にアクセスできません: No such file or directory
デバイスファイルが無い場合

デバイスの認識に失敗している可能性が高いです。dmesg等で原因を調べて下さい。

(dmesg出力例:認識成功時)

[63741.240470] usb 3-3: new full speed USB device using ohci_hcd and address 5      <--- 新しいデバイスを検出
[63741.431643] gspca: probing 046d:08a9
[63742.746355] zc3xx: probe 2wr ov vga 0x0000
[63742.796340] zc3xx: probe sensor -> 0011
[63742.796347] zc3xx: Find Sensor HV7131R(c)
[63742.800566] input: zc3xx as /devices/pci0000:00/0000:00:12.0/usb3/3-3/input/input11
[63742.800784] gspca: video0 created     <--- Videoデバイスとして認識
[63742.800790] gspca: found int in endpoint: 0x82, buffer_len=8, interval=10
[63742.800934] gspca: probing 046d:08a9

(lsusb出力例:認識成功時)

$ lsusb
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 002: ID 03f0:171d Hewlett-Packard Wireless (Bluetooth + WLAN) Interface [Integrated Module]
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 005: ID 046d:08a9 Logitech, Inc. Notebook Deluxe    <--- カメラデバイス
Bus 003 Device 002: ID 0d8c:0103 C-Media Electronics, Inc. CM102-A+/102S+ Audio Controller
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Windows の場合

ダウンロードのページ にある Windows用インストーラを使うのが無難です。
ただし、ソースコードはコピーされないので、別途、ダウンロードのページ からソースコードのアーカイブをダウンロードします。

iPhone の場合

持ってないので試してません。(欲しいけど)
iPhone Appのページに解説記事があります。 iPhone用のZBar SDK は PC版と別になっていて こちら からダウンロードできます。

動作確認

Webカメラから読み取り

zbar-tools パッケージでインストールした zbarcam を使ってみます。

起動する前に手元にバーコードをご用意下さい。 本の裏や、お菓子の箱に書いてあるバーコードでOKです。

次のように起動します。

(zbarcam – 起動方法)

$ zbarcam

ウインドウが現れカメラの映像が表示されたら、バーコードをカメラの前に置き、ピントを合わせます。

バーコードを検出すると、バーコード部に緑色の表示がされます。

(zbarcam – バーコード検出画面)

多少斜めでも検出しました。


バーコードを読み取る度に、結果がコンソールに出力されます。

(zbarcam – バーコード読み取り結果)

$ zbarcam
EAN-13:4987188150474           <--- 上の画像、久光製薬「のびのびサロンシップ」の箱
CODE-128:SDsnxjhn8R            <--- amazonの納品書 (さすが物流系、Code-128)
QR-Code:stop making sense      <--- qrencode で自作したQRコードをプリントアウトしたもの
EAN-13:9784048741354           <--- 本のバーコード(上段)
EAN-13:1920093017008           <--- 本のバーコード(下段)

バーコードの値だけが欲しい人は、次の様に起動してみて下さい

(zbarcam – 起動方法#2)

$ zbarcam |awk '{print substr($0,index($0,":")+1)}'
補足
  • オートフォーカス機能付きのWebカメラの方が良いと思います。

    使ったWebカメラはオートフォーカス無しだったため、 テスト中、フォーカスが合ってない状態で読み取ってしまい、誤認識することがありました。

  • zbarcam起動中はCPUコアの1つをほぼ占有します。

    使ってないときは、停止させておいた方が良いと思います。

画像ファイルから読み取り

次は zbarimg コマンドを使い、画像ファイルからバーコードを読み取ります。

手元にテスト用のバーコード画像ファイルを用意して下さい。 無い時は次のような方法で画像を入手して下さい。

  • qrencode で QRコード画像を作成
  • Googleの画像検索で “barcode” をキーワードに検索
  • バーコード作成サイトで画像を作成

(zbarimg – 実行例)

$ zbarimg -q sms.gif
QR-Code:stop making sense

上で使った画像ファイルはこれです。 値は “stop making sense” です。

補足
  • PNG, TIFF, JPGE, GIF, BMP, Postscript 形式の画像から読み取れることを確認しました。
  • 画像の中に複数のバーコードがあっても、1つしか検出しないようです。 (左上の1つだけ認識して終了)

サンプルコードを読む

ソースコードの展開先に examples というディレクトリがあります。その中に、C, C++, Python, Perl のサンプルコードがあります。
今回は Python のコードを見てみます。

read_one.py

カメラの映像からバーコードを読み取るアプリです。 名前の通り、1回読み取ると終了します。 Python版zbarcam ですね。

#!/usr/bin/python
from sys import argv
import zbar

# create a Processor
proc = zbar.Processor()

# configure the Processor
proc.parse_config('enable')

# initialize the Processor
device = '/dev/video0'
if len(argv) > 1:
    device = argv[1]
proc.init(device)

# enable the preview window
proc.visible = True

# read at least one barcode (or until window closed)
proc.process_one()

# hide the preview window
proc.visible = False

# extract results
for symbol in proc.results:
    # do something useful with results
    print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data

import文を含めても、有効行はたったの13行です。 見た瞬間「たったこんだけ?」と驚きました。

下手な解説は不要なくらいシンプルです。(なので解説は省略)

scan_image.py

画像ファイルからバーコードを読み取るアプリです。Python版zbarimg ですね。

#!/usr/bin/python
from sys import argv
import zbar
import Image

if len(argv) < 2: exit(1)

# create a reader
scanner = zbar.ImageScanner()

# configure the reader
scanner.parse_config('enable')

# obtain image data
pil = Image.open(argv[1]).convert('L')
width, height = pil.size
raw = pil.tostring()

# wrap image data
image = zbar.Image(width, height, 'Y800', raw)

# scan the image for barcodes
scanner.scan(image)

# extract results
for symbol in image:
    # do something useful with results
    print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data

# clean up
del(image)

こちらは、import文を含めて有効行は14行です。

同じ examplesディレクトリに同機能の C版, C++版のソースコードもあります。行数はそれぞれ次の通り。

  • C版:scan_iamge.c – 90行
  • C++版:scan_image.cpp – 54行

これでも十分短いと思いますが、Python版には及びません。

zbarcam, zbarimg

動作確認に使った zbarcam, zbarimg のソースコードも、ツールと同名のフォルダにあります。

こちらもそれほど大きくありません。
どちらも引数の解析に100行ぐらい要しているので getopt() を使えばもっと簡潔に出来そうだけどなぁ、と思いましたが、VC++ には getopt()が無いので互換性のために敢えて使ってないのかもしれません。

最後に

コードを1行も書かずにバーコード読み取りが出来てしまい、ちょっと拍子抜けでした。 それだけライブラリとツールが良くできてると言えますが。

さすがに流通やFAなどの分野では専用のバーコードリーダーが必用と思いますが、それほど使用頻度の高くない業務や、個人ユースでは Webカメラで十分代用出来そうです。 (ガンタイプじゃなきゃダメという人を除く)


(おまけ)

そのうち、オートフォーカスのWebカメラを入手してもう一度試してみようと思ったけど、…何に使おう?

Comments are closed.