2017-05-09

Python でバーコードをスキャン(ソースコード・ダウンロード可)

今回は、たくさんの商品画像の中にあるバーコードの内容をプログラムでスキャンして取得&その写真の分類ができるようにしてみたいと思います。
利用するのは次の3つです。

1.Python(2.7.12)
2.OpenCV2
3.Zbar

※実際のコードは GitHub からダウンロードできます。


【準備】

まずバーコードをスキャンするには zbar というパッケージが必要になりますのでインストールをしましょう。Ubuntu だと以下のコマンドで zbar をインストールできます。
 sudo apt-get install libzbar-dev  
そして、python から zbar が使えるようにするため pip でインストールです。
 pip install zbar  
はい。
これでインストールは完了です。(OpenCVはメジャーなのでインストールは省きます。)

【基本編】

では、zbar を使って画像の中にあるバーコードをスキャンする簡単なコードを作っていきましょう。
 import cv2  
 import zbar  

 scanner = zbar.ImageScanner()  
 scanner.parse_config('enable')  
必要なパッケージをインポートして、zbar のスキャナーを作成します。

 im = cv2.imread('images/barcode1.jpg')  
 gray_im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)  
OpenCV でスキャンしたい画像を読み込んでグレースケールに変換します。

 rows,cols = im.shape[:2]  
 image = zbar.Image(cols, rows, 'Y800', gray_im.tostring())  
 scanner.scan(image)  
ここで zbar の image を作成します。
1行目で画像のサイズとさっき作った gray_im をセットして実際にスキャンを開始します。

 for symbol in image:  
   print 'Type: %s, Data: %s' % (symbol.type, symbol.data)  
スキャンした結果を表示します。
type には 「qrcode」や「isbn10」などのデータタイプ、そして data には読み取ることができた値が入っています。

以上が簡単な例でした。
ただ、この例ではバーコードが斜めになっている場合は、検出できないことがあります。
そこで、次の応用編では斜めになったバーコードにも対応できるようにしてみましょう。

【応用編】

 import cv2  
 import zbar  

 scanner = zbar.ImageScanner()
 scanner.parse_config('enable')

 im = cv2.imread('images/barcode2.jpg')  
 gray_im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)  
 rows,cols = im.shape[:2]  
ここまでは基本編のおさらいです。
(ちなみに barcode2.jpg ではわざとバーコードがななめになっています。)

では、ここから斜めになったバーコードに対応するため輪郭を取得していきましょう。
 ret,threshold_im = cv2.threshold(gray_im, 150, 255, cv2.THRESH_BINARY)  
 im,contours,hierarchy = cv2.findContours(threshold_im, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  
まず、しきい値を使って画像を白と黒だけに変換します。
そして、findContours() で輪郭を取得します。

 for contour in contours:  
   rect = cv2.minAreaRect(contour)  
   center_pt = (int(rect[0][0]), int(rect[0][1]))
   w = int(rect[1][0])  
   h = int(rect[1][1])  
   angle = int(rect[2])
次に、取得した contours を for ループで回して一つ一つの長方形を取得しましょう。
minAreaRect がその部分になります。

rect は 中心座標、横幅、高さ、傾きのデータを持っているのでこれらをわかりやすいようにひとつひとつ変数(center_pt, w, h, angle)に格納していきます。

 M = cv2.getRotationMatrix2D(center_pt, angle, 1)
 rotated_im = cv2.warpAffine(im.copy(), M, (cols,rows))  
長方形の傾き(角度)が分かったのでこれを使って画像を回転させましょう。
一行目は行列を作って2行目で回転させた画像を取得しています。

 zbar_image = zbar.Image(cols, rows, 'Y800', rotated_im.tostring())  
 scanner.scan(zbar_image)  
そして、さっきと同じく zbar の image をつくります。

 for symbol in zbar_image:  
     symbol_type = symbol.type  
     symbol_data = symbol.data  
       if(symbol_type not in scanned_data.keys()):  
           scanned_data[symbol_type] = []  
           if symbol_data not in scanned_data[symbol_type]:  
               scanned_data[symbol_type].append(symbol_data)  
for ループで回して、もし scanned_data に type 別の値が入っていなければデータを格納。(←つまり、重複防止ですね)

これで、 scanned_data の中にスキャンされたバーコードの情報が入っていることになります。
あとは MySQL や JSON にデータを格納するなどして分類結果を保存するなどすればいいでしょう。

今回は以上です。












0 件のコメント:

コメントを投稿