PythonでQRコードを読み取る方法

プログラミング

PythonでQRコードを読み取る方法

Pythonを使用してQRコードを読み取ることは、様々なアプリケーション開発において非常に有用な機能です。例えば、商品の在庫管理、イベントでのチケット認証、情報共有の簡略化など、QRコードは私たちの身の回りの多くの場面で活用されています。Pythonは、その豊富なライブラリと直感的な文法により、QRコードの読み取り処理を比較的容易に実現できる強力なプログラミング言語です。

QRコードの読み取りには、主に画像処理ライブラリとQRコードデコーディングライブラリの組み合わせが用いられます。ここでは、最も一般的で推奨される方法として、Pillow(PILの後継)とpyzbarライブラリを使用する手順を解説します。これらのライブラリは、QRコードを含む画像の読み込みと、その画像からQRコードのデータを抽出する役割を担います。

必要なライブラリのインストール

まず、QRコードの読み取りに必要なライブラリをインストールします。ターミナルまたはコマンドプロンプトを開き、以下のコマンドを実行してください。

pip install pillow pyzbar opencv-python
  • Pillow: 画像ファイルの読み込みや操作に使用します。
  • pyzbar: QRコードを含む画像からバーコードやQRコードをデコード(解析)します。
  • opencv-python: 高度な画像処理機能を提供し、QRコードの検出精度を高めるのに役立ちます。必須ではありませんが、より堅牢な読み取りを可能にします。

QRコード画像の読み取りとデコード

以下に、QRコードの画像を読み込み、その内容をデコードするPythonコードの例を示します。


from PIL import Image
from pyzbar.pyzbar import decode
import cv2

def read_qr_code(image_path):
    # OpenCVを使用して画像を読み込む (グレースケールに変換)
    img = cv2.imread(image_path)
    if img is None:
        print(f"Error: Could not open or find the image at {image_path}")
        return

    # pyzbarはグレースケール画像での処理が効率的
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # QRコードをデコード
    decoded_objects = decode(gray_img)

    if not decoded_objects:
        print("No QR code found in the image.")
        return

    for obj in decoded_objects:
        # デコードされたデータのバイト列を文字列に変換
        data = obj.data.decode('utf-8')
        print(f"Decoded Data: {data}")
        # QRコードの位置情報も取得可能
        # print(f"Location: {obj.rect}")
        #QRコードのタイプも取得可能
        # print(f"Type: {obj.type}")

if __name__ == "__main__":
    # 読み込みたいQRコード画像のパスを指定してください
    qr_image_file = "your_qr_code.png" # 例: "qr_code.jpg", "scan_result.png"
    read_qr_code(qr_image_file)

コードの解説

  • from PIL import Image: PillowライブラリからImageモジュールをインポートしますが、この例ではcv2.imreadを使用するため、直接は使用しません。ただし、pyzbarはPillowオブジェクトも受け付けるため、代替手段として利用できます。
  • from pyzbar.pyzbar import decode: QRコードのデコードを行うためのdecode関数をインポートします。
  • import cv2: OpenCVライブラリをインポートします。
  • cv2.imread(image_path): 指定されたパスの画像を読み込みます。OpenCVは画像をNumPy配列として返します。
  • cv2.cvtColor(img, cv2.COLOR_BGR2GRAY): 画像をBGR(青、緑、赤)カラーフォーマットからグレースケールに変換します。pyzbarはグレースケール画像での処理がより効率的で、ノイズの影響も受けにくくなります。
  • decode(gray_img): グレースケール化された画像を入力として受け取り、画像内に存在するQRコードやバーコードを検出し、デコードします。検出された各オブジェクトはDecodedオブジェクトのリストとして返されます。
  • for obj in decoded_objects:: 検出された各QRコードオブジェクトに対してループ処理を行います。
  • obj.data.decode('utf-8'): デコードされたQRコードのデータはバイト列で返されるため、utf-8エンコーディングを使用して文字列に変換します。QRコードに格納されている情報に応じて、必要であれば別のエンコーディングを指定してください。
  • print(f"Decoded Data: {data}"): 抽出されたQRコードのデータをコンソールに出力します。

ウェブカメラからのQRコード読み取り

静止画像だけでなく、ウェブカメラからのリアルタイムでQRコードを読み取ることも可能です。以下はその実装例です。


import cv2
from pyzbar.pyzbar import decode

def read_qr_code_from_camera():
    # ウェブカメラを開く (0は通常、デフォルトのカメラを指します)
    cap = cv2.VideoCapture(0)

    if not cap.isOpened():
        print("Error: Could not open webcam.")
        return

    print("Press 'q' to quit.")

    while True:
        # カメラからフレームを読み込む
        ret, frame = cap.read()

        if not ret:
            print("Error: Can't receive frame (stream end?). Exiting ...")
            break

        # フレームをグレースケールに変換
        gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # QRコードをデコード
        decoded_objects = decode(gray_frame)

        for obj in decoded_objects:
            # 検出されたQRコードの周囲に矩形を描画
            points = obj.polygon
            if len(points) == 4:
                pts = np.array(points, np.int32)
                pts = pts.reshape((-1, 1, 2))
                cv2.polylines(frame, [pts], True, (0, 255, 0), 2) # 緑色の線で囲む

            data = obj.data.decode('utf-8')
            print(f"Decoded Data: {data}")
            # QRコードのデータ自体をフレーム上に表示
            cv2.putText(frame, data, (obj.rect.left, obj.rect.top - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

        # 結果のフレームを表示
        cv2.imshow("QR Code Scanner", frame)

        # 'q'キーが押されたらループを抜ける
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    # キャプチャを解放し、ウィンドウを閉じる
    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    # npをインポートする必要があるため、コードの冒頭に追加してください。
    import numpy as np
    read_qr_code_from_camera()

コードの解説

  • cv2.VideoCapture(0): ウェブカメラデバイスを開きます。通常、0はシステムに接続されている最初のカメラを指します。複数のカメラがある場合は、12などの数値に変更してみてください。
  • cap.isOpened(): カメラが正常に開かれたかどうかを確認します。
  • cap.read(): カメラから1フレームを読み込みます。retはフレームの読み込みが成功したかどうかを示すブール値、frameは読み込まれた画像データ(NumPy配列)です。
  • cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY): 読み込んだフレームをグレースケールに変換します。
  • decode(gray_frame): グレースケール化されたフレームからQRコードを検出・デコードします。
  • obj.polygon: 検出されたQRコードの4つの角の座標を取得します。
  • cv2.polylines(...): 検出されたQRコードの周囲に緑色の線で矩形を描画し、視覚的に分かりやすくします。
  • cv2.putText(...): デコードされたQRコードのデータを、画像上にテキストとして表示します。
  • cv2.imshow("QR Code Scanner", frame): 処理されたフレームを「QR Code Scanner」というタイトルのウィンドウに表示します。
  • cv2.waitKey(1) & 0xFF == ord('q'): キー入力を1ミリ秒間待ちます。もしqキーが押された場合、ループが終了します。
  • cap.release(): ウェブカメラデバイスを解放します。
  • cv2.destroyAllWindows(): 開かれているすべてのOpenCVウィンドウを閉じます。

注意点と応用

  • 画像の品質: QRコードの読み取り精度は、画像の解像度、明るさ、コントラスト、QRコード自体の鮮明さに大きく依存します。ぼやけた画像や、照明条件が悪い環境では、読み取りが困難になることがあります。
  • QRコードのサイズ: QRコードが画像内で小さすぎると、検出が難しくなります。必要に応じて、画像を拡大したり、カメラのズーム機能を使用したりすることを検討してください。
  • 複数のQRコード: 1つの画像に複数のQRコードが存在する場合、pyzbarはそれらをすべて検出して返します。上記のコード例では、検出されたすべてのQRコードのデータを処理します。
  • エラーハンドリング: 実際のアプリケーションでは、ファイルの存在確認、カメラの接続確認、デコードエラーなど、より堅牢なエラーハンドリングを実装することが重要です。
  • GUIアプリケーションへの組み込み: Tkinter、PyQt、KivyなどのGUIライブラリと組み合わせることで、よりユーザーフレンドリーなQRコードスキャナーアプリケーションを作成できます。
  • 高度な画像処理: QRコードが歪んでいたり、部分的に隠れていたりする場合、OpenCVの画像処理機能(例:二値化、ノイズ除去、透視変換など)を駆使することで、読み取り成功率を向上させることができます。

まとめ

PythonとPillowpyzbar(そして必要に応じてopencv-python)ライブラリを使用することで、QRコードの読み取りは非常に効率的に行うことができます。静止画像からの読み取りはもちろん、ウェブカメラからのリアルタイム処理も容易に実装可能です。これらの技術は、自動化、情報管理、ユーザーインターフェースの強化など、多様な分野で活用できるポテンシャルを秘めています。QRコードの読み取り機能をあなたのPythonプロジェクトに組み込むことで、よりインタラクティブで便利なアプリケーションが実現できるでしょう。