バーコードリーダー 【QRコード対応】

tkinter

バーコードリーダーの Python のプログラムをまとめ、公開しておきます。
USB カメラがあれば、リアルタイムで QR コードや1次元バーコードの読み取りが可能です。GUI は tkinter を使っています。

環境: Windows パソコン、USBカメラ(Web カメラ)、Python 3.x
OpenCV、pyzbar、Anaconda をインストールしています。

背景 ~ pyzbarでバーコード読み取りが実現!

パソコン1台と USB カメラ1つあれば、Python と pyzbar などの無料のパッケージを入れることで、QRコードや一般のバーコード読み取りが可能となります。
すでに持っている機器の活用範囲が格段に広がることになります。
また、バーコード認識は、画像認識の基本ともいえます。顔認識や機械学習による物体認識など、画像認識の分野に展開できる可能性も広がります。

pyzbar のインストール

pyzbar をインストールしていない場合は、以下でインストールをしてください。Windows の場合について記載しています。

pip install pyzbar 

加えて、OpenCV がインストールしてあることが必要です。OpenCV をインストールしていない場合は、以下の関連リンク(OpenCV のインストール)を参照してください。

サンプルコードの設定方法

・ barcode_reader1.py 等のテキストファイルを作成し下記のサンプルコードをコピー&ペーストで貼りつけて保存してください。
・ 下記の手順で起動してみてください。もし、USBカメラのカメラ番号がずれていたら修正してください。

使い方

① Webカメラ/USBカメラを PC に接続しておきます。
② Windows のコマンドプロンプトから、上で作成したサンプルコード(barcode_reader1.py)を実行してください。GUI が表示され、バーコードの読み取りが可能な状態になります。
③ QRコードや、商品についているバーコードをカメラで映してみてください。読み取ったバーコードデータを表示します。
※ [stop] /[start] ボタンをクリックすると、ライブカメラの画像の更新を停止/開始できます。
読み取ったバーコードのデータを保持したい場合は、[stop] ボタンをクリックして読み取りを停止してください。

※ USB カメラのライブ画像が取り込めない場合は、PC が認識しているカメラ番号が合っていない可能性があります。
スクリプトの camera number (カメラ番号)と記載している行で、値 “0” を “1”, “2” などに変更して、スクリプトを再度起動してみてください。
※ なお、カメラ番号についてよくわからない場合や、詳細を確認したい場合は、下記の関連リンクを参照してみてください。PC にカメラが複数つながっていてすべてのカメラ番号を抽出したいときや、カメラの動作チェックをしたいとき、活用できると思います。

仕様:読み取りができるバーコードの種類

動作確認をしたところ、読み取りができるバーコードの種類は以下となっています。

バーコードの種類
読み取りができるもの JAN (13桁)、JAN 短縮タイプ(8桁)
Code128
Code39
UPC-A (12桁)、UPC-E (8桁)
Codabar
ITF
QRコード model2
読み取りができないもの PDF417、DataMatrix

主要な一次元バーコードには、ほぼ対応しています。
二次元バーコードは QRコードだけ対応しています。

説明

サンプルコードの説明です。
・ 最初に、OpenCV、tkinter、pyzbar、PIL の Image をインポートしています。
・ def stop1() としている関数は、バーコードの読み取り、停止を設定するためのものです。
・ def decoder1() としている関数がバーコード読み取りのメインとなる部分です。
・ frame1 = tk1.Tk() としている行で、まず、GUI 画面となる frame1 を定義します。
つぎに、GUI 画面の画面サイズを設定します。
・ ラベル label1 と、読み取ったバーコードデータを表示するためのテキストボックス textbox1 (実際はエントリ)を定義します。
それぞれ、place() とした関数で、画面上で表示する位置と幅の調整をします。
・ cap1 = cv2.VideoCapture() としたところで、接続している USB 端子に対応したカメラ番号を設定しています。
カメラから画像が取得できない場合は、この番号 0 を修正します。
・ canvas1 = tk1.Canvas() としたところで、frame1 上に画像を表示するためのキャンバス Canvas を設定しています。Canvas の位置は place() で設定しています。
・ つぎにグローバルパラメータを設定し、decoder1() を実行します。
decoder1() は def で定義しており、末尾に frame1.after() を実行することで、一定時間おきに自分自身を繰り返し実行するようにしています。これにより、バーコード画像、QRコード画像を連続で読み取る動きになります。
・ frame1.mainloop() で GUI を表示します。
・ 前半の cap1 を定義したところで、カメラのハードウェアのリソースを取得しています。そこで、アプリの終了時に cap1.release() としてリソースを開放しておきます。

まとめ

これで 一次元バーコード、QRコードの読み取りも自由にできるようになりました。
使っていない USB カメラ、Web カメラがあれば、有効活用できます。

なお、動作確認が取れている USB カメラの機種や、カメラ番号の自動抽出など、以下の関連リンクにまとめていますので、もしも興味があるようでしたら、参考にしてみてください。

関連リンク
・ バーコード作成ソフトウェア 【Python & Tkinter】
・ QRコード作成ソフトウェア 【Python & Tkinter】
・ 仮想環境での OpenCV のインストール方法 & エラー時の対処方法 【Anaconda】
・ 動作確認済み USB カメラ 【おすすめ】
・ 接続中のカメラ番号を抽出する 【OpenCV & Python】
・ スマホ議決権行使をパソコンで行う方法
・ 顔認識ソフトウェア 【OpenCV】
・ バーコードリーダ Web アプリ 【Raspberry Pi & Flask】
・ バーコード作成 Web アプリ 【Raspberry Pi & Flask】

サンプルスクリプト

バーコードリーダー barcode_reader1.py

#!/usr/bin/env python
# -*- coding: utf8 -*-
import cv2
from pyzbar.pyzbar import decode 
import tkinter as tk1 
from PIL import Image, ImageTk

def stop1(): 
    global stp1 
    if stp1 == 0: 
        stp1 = 1 
        button1["text"] = "start" 
    else: 
        stp1 = 0 
        button1["text"] = "stop" 

def decoder1(): 
    global cap1 
    global frame1 
    global canvas1 
    global img1 
    global cnt1 
    global stp1 
    if stp1 == 0: 
        result0, img0 = cap1.read()
        if result0:
            decode0 = decode( cv2.cvtColor( img0, cv2.COLOR_RGBA2GRAY )  ) 
            img1 = cv2.cvtColor( img0, cv2.COLOR_BGR2RGB ) 
            if len( decode0 ) > 0: 
                str1 = decode0[0].data.decode("utf-8") 
                rect1 = decode0[0].rect
                textbox1.delete( 0, tk1.END ) 
                textbox1.insert( 0, str1 ) 
                cv2.rectangle( img1, ( rect1.left, rect1.top ), ( rect1.left + rect1.width, rect1.top + rect1.height ), ( 0, 0, 255 ), thickness = 1 ) 
                cnt1 = 0 
            else: 
                cnt1 = cnt1 + 1 
                if cnt1 > 5: 
                    textbox1.delete( 0, tk1.END ) 
            img1 = ImageTk.PhotoImage( image= Image.fromarray( img1 ) ) 
            canvas1.create_image( 0, 0, anchor=tk1.NW, image=img1 ) 
    frame1.after( 3000, decoder1 ) 

frame1 = tk1.Tk()
frame1.title(u"barcode_reader v0.1")
frame1.geometry("680x550")

label1 = tk1.Label(text='barcode data')
label1.place(x=10, y=10, width = 100) 

textbox1 = tk1.Entry( master=frame1 ) 
textbox1.place(x=110, y=10, width=400) 

button1 = tk1.Button( frame1, text='stop', command=stop1 )
button1.place(x=560, y=10, width=100)

cap1 = cv2.VideoCapture( 0, cv2.CAP_DSHOW )   # camera number 

canvas1 = tk1.Canvas( frame1, width=cap1.get( cv2.CAP_PROP_FRAME_WIDTH ), height=cap1.get( cv2.CAP_PROP_FRAME_HEIGHT ), bg='white' )
canvas1.place(x=20, y=50) 

img1 = 0 
cnt1 = 0 
stp1 = 0 
decoder1() 

frame1.mainloop()
cap1.release()
タイトルとURLをコピーしました