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

プログラミング

PythonによるQRコードの読み取り

Pythonを使ってQRコードを読み取ることは、様々なアプリケーション開発において非常に有用な機能です。例えば、商品の在庫管理、イベントのチケット認証、情報共有など、QRコードにエンコードされた情報をプログラムで活用したい場面は数多く存在します。

PythonでQRコードを読み取るためには、主に外部ライブラリを利用します。中でも最も一般的で強力なライブラリは、Pillow (PILのフォーク) と pyzbar です。Pillowは画像処理ライブラリであり、QRコードが含まれる画像を扱うために使用されます。pyzbarは、QRコードを含むさまざまなバーコードをデコード(読み取り)する機能を提供します。

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

これらのライブラリをインストールするには、pipコマンドを使用します。ターミナルまたはコマンドプロンプトを開き、以下のコマンドを実行してください。

pip install Pillow pyzbar

もし、zbarライブラリ自体のシステムへのインストールが必要な場合は、お使いのオペレーティングシステムに合わせて追加の手順が必要になることがあります。例えば、Debian/Ubuntu系ではsudo apt-get install zbar-tools、macOSではbrew install zbarといったコマンドになります。

QRコード読み取りの基本的な流れ

PythonでQRコードを読み取る基本的な手順は以下のようになります。

  1. 画像の読み込み: QRコードが含まれている画像をPythonで開きます。
  2. QRコードの検出とデコード: 画像の中からQRコードを検出し、そこにエンコードされている情報を読み取ります。
  3. 情報の利用: 読み取った情報をプログラム内で利用します。

Pillowとpyzbarを用いたQRコード読み取りの実装例

以下に、Pillowとpyzbarを使用してQRコードを読み取る具体的なPythonコードを示します。

from PIL import Image
from pyzbar.pyzbar import decode

def read_qr_code(image_path):
    """
    指定された画像ファイルからQRコードを読み取る関数。

    Args:
        image_path (str): QRコード画像ファイルのパス。

    Returns:
        list: 検出されたQRコードのデータ(デコードされた文字列)のリスト。
              QRコードが見つからない場合は空のリストを返します。
    """
    try:
        # 画像を読み込む
        img = Image.open(image_path)

        # QRコードをデコードする
        decoded_objects = decode(img)

        # 検出されたQRコードのデータをリストに格納する
        qr_data_list = []
        for obj in decoded_objects:
            # デコードされたデータはバイト列なので、UTF-8で文字列に変換する
            qr_data = obj.data.decode('utf-8')
            qr_data_list.append(qr_data)

        return qr_data_list

    except FileNotFoundError:
        print(f"エラー: ファイル '{image_path}' が見つかりません。")
        return []
    except Exception as e:
        print(f"QRコードの読み取り中にエラーが発生しました: {e}")
        return []

# --- 実行例 ---
if __name__ == "__main__":
    # ここに、実際にQRコード画像ファイルのパスを指定してください
    # 例: image_file = "path/to/your/qrcode.png"
    image_file = "your_qrcode_image.png" # このファイル名を実際の画像ファイル名に置き換えてください

    qr_codes = read_qr_code(image_file)

    if qr_codes:
        print("検出されたQRコードデータ:")
        for data in qr_codes:
            print(f"- {data}")
    else:
        print("画像からQRコードは検出されませんでした。")

コードの解説

  • from PIL import Image: PillowライブラリからImageモジュールをインポートし、画像ファイルの操作を可能にします。
  • from pyzbar.pyzbar import decode: pyzbarライブラリからdecode関数をインポートします。この関数がQRコード(およびその他のバーコード)のデコード処理を行います。
  • Image.open(image_path): 指定されたパスの画像ファイルをPillowのImageオブジェクトとして開きます。
  • decode(img): 開いた画像オブジェクトimgを引数としてdecode関数を呼び出します。この関数は、画像内に検出されたバーコード(QRコードを含む)のリストを返します。各要素はDecodedオブジェクトです。
  • obj.data.decode('utf-8'): decode関数が返すDecodedオブジェクトのdata属性には、デコードされた情報がバイト列として格納されています。これをUTF-8エンコーディングで通常の文字列に変換しています。
  • エラーハンドリング: try...exceptブロックを使用して、ファイルが見つからない場合や、その他の予期せぬエラーが発生した場合に対処しています。

ウェブカメラからのリアルタイムQRコード読み取り

QRコードを画像ファイルとしてではなく、ウェブカメラからの映像ストリームからリアルタイムで読み取ることも可能です。この場合、OpenCVライブラリを併用することが一般的です。

OpenCVとpyzbarを用いたリアルタイム読み取りの実装例

まず、OpenCVライブラリをインストールします。

pip install opencv-python

次に、リアルタイム読み取りのコード例を示します。

import cv2
from pyzbar.pyzbar import decode

def read_qr_code_from_webcam():
    """
    ウェブカメラからの映像ストリームでQRコードをリアルタイムに読み取る関数。
    'q' キーを押すと終了します。
    """
    # ウェブカメラを開く (0は通常、デフォルトのカメラを指します)
    cap = cv2.VideoCapture(0)

    if not cap.isOpened():
        print("エラー: ウェブカメラを開けませんでした。")
        return

    print("ウェブカメラを開きました。QRコードをカメラに向けてください。'q' キーで終了します。")

    while True:
        # フレームを1枚読み込む
        ret, frame = cap.read()

        if not ret:
            print("フレームを読み込めませんでした。終了します。")
            break

        # QRコードをデコードする
        # decode関数はNumPy配列(OpenCVのフレーム)を直接受け取ることができます
        decoded_objects = decode(frame)

        # 検出されたQRコードの情報をフレーム上に表示する
        for obj in decoded_objects:
            # QRコードの境界線を描画
            points = obj.polygon
            if len(points) == 4:
                pts = [(points[i][0], points[i][1]) for i in range(4)]
                cv2.polylines(frame, [np.array(pts, np.int32)], True, (0, 255, 0), 2)

            # デコードされたデータを文字列として取得
            qr_data = obj.data.decode('utf-8')
            print(f"検出されたQRコード: {qr_data}")

            # QRコードのデータとタイプを画像上に表示
            text = f"{qr_data}"
            cv2.putText(frame, text, (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__":
    # numpyも使用するためインポート
    import numpy as np
    read_qr_code_from_webcam()

リアルタイム読み取りコードの解説

  • cv2.VideoCapture(0): デフォルトのウェブカメラ(通常はインデックス0)を開きます。複数のカメラがある場合は、インデックスを変更してみてください。
  • cap.read(): カメラから1フレーム(画像)を読み込みます。retは読み込みが成功したかどうかを示すブール値、frameは読み込まれた画像データ(NumPy配列)です。
  • decode(frame): 読み込んだフレームをdecode関数に渡します。pyzbarはOpenCVのフレーム形式(NumPy配列)を直接扱えます。
  • cv2.polylines(...): 検出されたQRコードの周囲に緑色の枠線を描画します。
  • cv2.putText(...): 検出されたQRコードのデータを画像上にテキストとして表示します。
  • cv2.imshow(...): 処理済みのフレームを「QR Code Scanner」というタイトルのウィンドウに表示します。
  • cv2.waitKey(1) & 0xFF == ord('q'): 1ミリ秒ごとにキー入力を待ちます。もし’q’キーが押されたら、ループを終了します。
  • cap.release()cv2.destroyAllWindows(): プログラム終了時に、カメラリソースを解放し、開いたすべてのOpenCVウィンドウを閉じます。

その他考慮事項

  • QRコードの品質: QRコードの読み取り精度は、画像の解像度、明るさ、コントラスト、QRコード自体の印刷品質、そしてカメラの性能に大きく依存します。ぼやけた画像や、光の反射が強い画像では、読み取りが困難になる場合があります。
  • 複数のQRコード: 1つの画像に複数のQRコードが含まれている場合でも、`decode`関数はそれらすべてを検出してリストで返します。
  • エンコーディング: QRコードに格納されているデータはバイト列であるため、通常は.decode('utf-8')のように、適切なエンコーディング(多くの場合UTF-8)で文字列に変換する必要があります。
  • エラー処理: 実際のアプリケーションでは、ファイルが存在しない場合、画像形式が不正な場合、QRコードが検出されない場合など、さまざまなエラーケースを想定した堅牢なエラーハンドリングを実装することが重要です。
  • パフォーマンス: 高解像度の画像を扱う場合や、リアルタイム処理では、パフォーマンスが問題になることがあります。画像のサイズを調整したり、処理を最適化したりする必要があるかもしれません。

これらのライブラリと実装例を基に、PythonでQRコードを読み取る様々なアプリケーションを開発することができます。

まとめ

PythonでQRコードを読み取るには、Pillowとpyzbarライブラリを使用するのが一般的です。Pillowは画像の読み込みと前処理を、pyzbarはQRコードの検出とデコードを担当します。画像ファイルからの読み取りだけでなく、OpenCVを併用することでウェブカメラからのリアルタイム読み取りも実現可能です。QRコードの品質や画像の状態によって読み取り精度は変動するため、実用的なアプリケーション開発では、これらの要素を考慮したエラーハンドリングや画像処理が重要となります。