LoginSignup
67
71

More than 3 years have passed since last update.

【簡単】QRコードの作成と読み取り in Python

Last updated at Posted at 2021-03-04

➊:はじめに

Pythonで「QRコード作成、読み取り」が、簡単に実現できないかなと思って調べました。

・やりたいこと

やりたいことは、以下の3つです。

  • PNGのQRコード画像作成
  • 画像からのQRコード読み取り
  • webカメラからのQRコード読み取り

・ソリューションまとめ

やりたいことに対する解決策を、以下にまとめます。

やりたいこと 使用するモジュール 備考
QRコード画像作成 PyQRCode PNG化する場合はpypngも必要
QRコード読み取り1 (CV2) opencv-python Ver4.3以上で複数読込み可能
QRコード読み取り2 (pyzbar) pyzbar Macはzbar, Linuxはlibzbar0も必要

※本ページの開発環境:win10、Python 3.8.5
ということで、以下、実施していきます。

➋:QRコード作成

QRコードの作成は、QRコードジェネレーターであるpyqrcodeモジュールを使用します。QRコードは、SVG、PNG、およびプレーンテキストとして保存可能なようです。PNGで保存する場合は、別途、pypngモジュールを使用します。

・インストール

以下のコマンドにより、PyQRCodeモジュールをインストールします。また、今回はQRコードをPNG画像として保存するため、pypngモジュールもインストールします。

コマンドライン
pip install PyQRCode
pip install pypng

・プログラム

sample_qr_generator.py
import pyqrcode

FILE_PNG_A = 'qrcode_A.png'
FILE_PNG_B = 'qrcode_B.png'

# QRコード作成
code = pyqrcode.create('https://qiita.com/PoodleMaster', error='L', version=3, mode='binary')
code.png(FILE_PNG_A, scale=5, module_color=[0, 0, 0, 128], background=[255, 255, 255])

# QRコード作成
code = pyqrcode.create('https://github.com/PoodleMaster', error='L', version=3, mode='binary')
code.png(FILE_PNG_B, scale=5, module_color=[0, 0, 0, 128], background=[255, 255, 255])

・実行結果

File Image
qrcode_A.png qrcode_A.png
qrcode_B.png qrcode_B.png

➌:画像連結

こちらの作業は必須ではないですが、1枚の画像に複数QRコードがある状況を作っておきます。次章の「QRコード読込み」の際に、1枚の画像から複数のQRコードを読み込めることを確かめます。

・インストール

OpenCVモジュールを使用して画像を連結します。

pip install opencv-python

・プログラム

sample_hconcat.py
import cv2

FILE_PNG_A = 'qrcode_A.png'
FILE_PNG_B = 'qrcode_B.png'
FILE_PNG_AB = 'qrcode_AB.png'

im1 = cv2.imread(FILE_PNG_A)
im2 = cv2.imread(FILE_PNG_B)

im_h = cv2.hconcat([im1, im2])
cv2.imwrite(FILE_PNG_AB, im_h)

cv2.imshow('image', im_h)
cv2.waitKey(0)

・実施結果

File Image
qrcode_AB.png qrcode_AB.png

➍:QRコード読込み

QRコードの読込みは、OpenCVモジュール、またはpyzbarモジュールのどちらかを使用します。

➍-1:「OpenCV」によるQRコード読込み

・インストール

OpenCVバージョン4.3からdetectAndDecodeMultiメソッドがコール可能となり、1枚の画像から複数のQRコードを読み取ることができるようになりました。OpenCVは、バージョン4.3以上をインストールしてください。

pip install opencv-python

・プログラム

sample_qr_read_1.py
import cv2
import numpy as np


# -----------------------------------------------------------
# initial
# -----------------------------------------------------------
font = cv2.FONT_HERSHEY_SIMPLEX
FILE_PNG_AB = 'qrcode_AB.png'


# -----------------------------------------------------------
# function_qr_dec
# -----------------------------------------------------------
def function_qrdec_cv2(img_bgr):

    # QRCodeDetectorインスタンス生成
    qrd = cv2.QRCodeDetector()

    # QRコードデコード
    retval, decoded_info, points, straight_qrcode = qrd.detectAndDecodeMulti(img_bgr)

    if retval:
        points = points.astype(np.int)

        for dec_inf, point in zip(decoded_info, points):
            if dec_inf == '':
                continue

            # QRコード座標取得
            x = point[0][0]
            y = point[0][1]

            # QRコードデータ
            print('dec:', dec_inf)
            img_bgr = cv2.putText(img_bgr, dec_inf, (x, y-6), font, .3, (0, 0, 255), 1, cv2.LINE_AA)

            # バウンディングボックス
            img_bgr = cv2.polylines(img_bgr, [point], True, (0, 255, 0), 1, cv2.LINE_AA)

    cv2.imshow('image', img_bgr)
    cv2.waitKey(0)


# -----------------------------------------------------------
# sample program
# -----------------------------------------------------------
img_BGR = cv2.imread(FILE_PNG_AB, cv2.IMREAD_COLOR)
function_qrdec_cv2(img_BGR)

detectAndDecodeMultiの結果が、TrueretvalTrue)の場合でも、デコードデータが無い(dec_infNULL)ことがあったので、「dec_inf == ''」の場合は、continueさせています。

・実行結果

スクリーンショット 2021-03-04 162814.png

➍-2:「pyzbar」によるQRコード読込み

・インストール

Windows環境以外は、以下のモジュールをインストールしてください。

Mac
brew install zbar
Linux / GoogleColab
sudo apt-get install libzbar0

以下のコマンドでpyzbarモジュールをインストールします。

Mac / Linux / GoogleColab / Win
pip install pyzbar

・プログラム

sample_qr_read_2.py
import cv2
from pyzbar.pyzbar import decode, ZBarSymbol


# -----------------------------------------------------------
# initial
# -----------------------------------------------------------
font = cv2.FONT_HERSHEY_SIMPLEX
FILE_PNG_AB = 'qrcode_AB.png'


# -----------------------------------------------------------
# function_qr_dec
# -----------------------------------------------------------
def function_qrdec_pyzbar(img_bgr):

    # QRコードデコード
    value = decode(img_bgr, symbols=[ZBarSymbol.QRCODE])

    if value:
        for qrcode in value:

            # QRコード座標取得
            x, y, w, h = qrcode.rect

            # QRコードデータ
            dec_inf = qrcode.data.decode('utf-8')
            print('dec:', dec_inf)
            img_bgr = cv2.putText(img_bgr, dec_inf, (x, y - 6), font, .3, (255, 0, 0), 1, cv2.LINE_AA)

            # バウンディングボックス
            cv2.rectangle(img_bgr, (x, y), (x + w, y + h), (0, 255, 0), 2)

        cv2.imshow('image', img_bgr)
        cv2.waitKey(0)


# -----------------------------------------------------------
# sample program
# -----------------------------------------------------------
img_BGR = cv2.imread(FILE_PNG_AB, cv2.IMREAD_COLOR)
function_qrdec_pyzbar(img_BGR)

・実行結果

スクリーンショット 2021-03-04 162910.png

➎:webカメラでQRコード自動認識

最後にwebカメラでQRコードを自動認識するプログラムを載せておきます。

➎-1:「OpenCV」プログラム

プログラムは、'q'」キー押下でquitします。

sample_webcam_qrcode_cv2.py
import cv2
import numpy as np


# -----------------------------------------------------------
# Init
# -----------------------------------------------------------
font = cv2.FONT_HERSHEY_SIMPLEX

# -----------------------------------------------------------
# 画像キャプチャ
# -----------------------------------------------------------
# VideoCaptureインスタンス生成
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

# QRCodeDetectorインスタンス生成
qrd = cv2.QRCodeDetector()

while cap.isOpened():
    ret, frame = cap.read()

    if ret:
        # QRコードデコード
        retval, decoded_info, points, straight_qrcode = qrd.detectAndDecodeMulti(frame)

        if retval:
            points = points.astype(np.int32)

            for dec_inf, point in zip(decoded_info, points):
                if dec_inf == '':
                    continue

                # QRコード座標取得
                x = point[0][0]
                y = point[0][1]

                # QRコードデータ
                print('dec:', dec_inf)
                frame = cv2.putText(frame, dec_inf, (x, y - 6), font, .3, (0, 0, 255), 1, cv2.LINE_AA)

                # バウンディングボックス
                frame = cv2.polylines(frame, [point], True, (0, 255, 0), 1, cv2.LINE_AA)

        # 画像表示
        cv2.imshow('cv2', frame)

    # quit
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# キャプチャリソースリリース
cap.release()

➎-2:「pyzbar」プログラム

プログラムは、'q'」キー押下でquitします。

sample_webcam_qrcode_pyzbar.py
import cv2
from pyzbar.pyzbar import decode, ZBarSymbol


# -----------------------------------------------------------
# Init
# -----------------------------------------------------------
font = cv2.FONT_HERSHEY_SIMPLEX


# -----------------------------------------------------------
# 画像キャプチャ
# -----------------------------------------------------------
# VideoCaptureインスタンス生成
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

while cap.isOpened():
    ret, frame = cap.read()

    if ret:
        # デコード
        value = decode(frame, symbols=[ZBarSymbol.QRCODE])

        if value:
            for qrcode in value:

                # QRコード座標
                x, y, w, h = qrcode.rect

                # QRコードデータ
                dec_inf = qrcode.data.decode('utf-8')
                print('dec:', dec_inf)
                frame = cv2.putText(frame, dec_inf, (x, y-6), font, .3, (255, 0, 0), 1, cv2.LINE_AA)

                # バウンディングボックス
                cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 1)

        # 画像表示
        cv2.imshow('pyzbar', frame)

    # quit
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# キャプチャリソースリリース
cap.release()

➎-3:実行結果

OpenCV」の実行結果は割愛し、「pyzbar」の実行結果のみを載せます。「QRコードを表示した紙」をwebカメラで撮り検出させていますが、うまく認識しています!:thumbsup_tone1:

➏:以上

お疲れ様でした。
モジュールを使うことで、かなり簡単にQRコード作成・読込みツールを作ることができました。

67
71
2

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
67
71