【python】zbarでバーコードを読み取る(画像→数列) 【お家IT#17】
本件の実装の一部
motojapan.hateblo.jp
前回の続き
motojapan.hateblo.jp
目次
前回まででフロントエンド・バックエンドの整備が終わった。
以降は、画像処理部分を進める。
今回は食品名(商品名)を取得するために、バーコード情報の読み取りをしたい。
バーコードとは
ふと、そもそもバーコードが何かをちゃんとわかっていなかったので調べる。
「黒いバーと空白の組み合わせで、数字、文字、記号を読み込めるデータ形式」であり、一般的に縞模様を光学系認識機器で読み取る。
一般に普及している縞模様の一次元バーコードや、QRコードに体表される二次元バーコードをよく目にしている。
今回は食品名を取得したいので、今回は一次元バーコードを中心に考える。
バーコードの詳細は次が参考になる。
バーコードとは?|基礎知識|自動認識|デンソーウェーブ
バーコード種類は下記。
- 統一商品コード(ユニークコード)
- インストアコード(任意コード)
特にユニークコードで、日本で使われているのはJANコード。
JANコード桁数は下記。
- 標準タイプ(13桁)
- 先頭7桁 : JANメーカーコード
- 先頭9桁 : 国番号2桁 + JANメーカーコード7桁
- 短縮タイプ(8桁)
JANコード構成要素は下記。
- 国番号+メーカー番号
- 商品番号
- チェックデジット
また、特に気になるのは、両サイドにあるマージンと呼ばれる空白は、十分な領域が必要である。<ナローバー(最も小さい黒縞)の10倍> ★
バーコードを読み込む方法は2つ思いつく。
- バーコードリーダーといった専用機器で赤外線反射から読み取る
- カメラなどの汎用機器で画像から読み取る(今回はこっち)
まぁこんな感じのバーコードリーダーでの読み取りでもよい。
RAINLAX バーコードスキャナ 無線対応 Bluetooth対応 ワイヤレスバーコードリーダー レーザーバーコードリーダー 手持ち式バーコードスキャナ 2.4GHz
- 出版社/メーカー: RAINLAX
- メディア: オフィス用品
- この商品を含むブログを見る
ただ、それはあまりにつまらないし、「自宅で手軽に使う」というポリシーから外れるのでので今回は画像処理ベースで調べてみた。(スマホ一台で済ませたいし。)
zbarインストール
かなり簡単
//インストール $ sudo apt-get install libzbar-dev $ sudo apt-get install python-zbar ... //確認 $ python import zbar //error無しでOK
インストール時のトラブルシューティング
「error: command 'arm-linux-gnueabihf-gcc' failed with exit status 1」がインストール時に出る場合
下記インストール時にこんなエラーが出ることがある。
$ pip install zbar
対策 : module不足なので追加
$ sudo apt-get install python-dev
「segmentation fault」が実行時に出る場合
確認時(実行時)にこんなエラーが出ることがある。
$ python import zbar //segmentation fault
対策 : pipで入れたzbarがconflictしているようなのでpipはアンインストール、apt-getでインストール
$ pip uninstall zbar $ sudo apt-get install python-zbar
実装例
//img : cv2 image(numpy) def convert_image_to_code(img): print('=========== proc start =============') start_time = time.time() #init module scanner = zbar.ImageScanner() scanner.parse_config('enable') #image to gray gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) h = gray.shape[0] w = gray.shape[1] zimage = zbar.Image(w, h, 'Y800', gray.tostring()) #scan scanner.scan(zimage) result = [] for symbol in zimage: print('Type: {0} | Data: {1}'.format(symbol.type, symbol.data)) result.append({'type':symbol.type, 'data':symbol.data}) print 'proc_time {0:f} [ms] '.format((time.time() - start_time) * 1000) print('=========== proc end ===========') return result
結果
入力画像は★に注意して、実際にいくつか試してみるといい感じの結果となった。
平面紙印刷 |
レトレクパック印刷 |
曲面印刷 |
|
画像全体 |
|||
撮影領域 |
|||
結果 |
4970231640022 |
4902204411599 |
4902106232209 |
400 x 60 の画像に対して、処理速度は20-40[ms]程度。
曲面やぐにゃぐにゃ面でも割りとちゃんと認識できる。
以上。
次回はこのバーコードの数列から、食品名を取得する。