ラズパイカメラとPicamera2及びOpenCVを使ってQRコード読み取り

ラズパイカメラとPicamera2及びOpenCVを使ってQRコード読み取り

ここを参考にしました。

ラズパイOSのバージョンがBookworm以降ではラズパイにリボンケーブルで接続するカメラはUSBカメラのように/dev/video0などデバイスファイルを使ってアクセスできない。なので以下のようなpythonプログラムでは動かない。

cap = cv2.VideoCapture(0)

動かすにはPicamera2パッケージを使う。
github copilotを使いながら簡潔なプログラムを作れたので、とりあえず残しておく。

使ったもの

  • ラズベリーパイ4
    • OSバージョンはTrixie
    • カメラモジュールで写ったものを確認するのでLite版は止めておいた方が良い。
  • ラズベリーパイカメラモジュール(OV5647)
    • 互換品でも可。
    • 多分カメラモジュールv2, v3でも動くはず。

とりあえずラズパイOSをクリーンインストール。

SSHまたはGUIでのターミナルを開いて以下コマンドを実行してPythonパッケージを入れる。

sudo apt install python3-picamera2
sudo apt install python3-opencv

rpicam-helloコマンドを実行してちゃんとカメラモジュールで写るか確認もしておく。

メニューからThonnyを開いて以下プログラムをコピペして実行。
読み取り成功するとしたのShellタブに読み取り結果が出て来る。

from picamera2 import Picamera2
import cv2

# Picamera2 の初期化
picam2 = Picamera2()
picam2.configure(picam2.create_video_configuration())  # mode3: FHD
picam2.start()

# QRコード検出器を初期化
qrCodeDetector = cv2.QRCodeDetector()

while True:
    frame = picam2.capture_array()

    # QRコードを検出し、その位置を取得
    decodedText, points, _ = qrCodeDetector.detectAndDecode(frame)

    if points is not None:
        points = points[0]

        # Debugging: Print the points to check their structure.
        #print(f"Points: {points}")

        # Validate and draw lines around QR code
        if len(points) == 4 and all(len(point) == 2 for point in points):
            for i in range(len(points)):
                start_point = tuple(map(int, points[i]))
                end_point = tuple(map(int, points[(i + 1) % len(points)]))
                cv2.line(frame, start_point, end_point, (0, 255, 0), 3)

        # デコードされたテキストを表示
        print(decodedText)

    # フレームを表示
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    display_frame = cv2.resize(frame_rgb, (960, 540), interpolation=cv2.INTER_AREA)  # Quarter HDにリサイズ
    cv2.imshow('QR Code Scanner', display_frame)

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

cv2.destroyAllWindows()
picam2.stop()

<追記>

・create_preview_configuration() とやると640x480の解像度のフレームとなる。解像度が低くてLNURLがやっと検出できるぐらい。つらい。
サンプルプログラムにあるcreate_video_configuration()だと1920x1080のFHDになる。ただこのサイズだとimshow()でウィンドウに表示するとデカすぎるのでresize()でアスペクト比そのまま小さくしてる。

<おまけ>

Thonnyを仮想環境で使うには

GUIでPythonプログラミングできるThonnyはOS側のパッケージしか使えないし、pipでパッケージを入れることもできない。
仮想環境を作り、さらにシステム側パッケージも使えるようにしてThonnyを動かせば便利。そのやり方は以下。

1. Thonnyを終了させる。

2. 仮想環境を作る

--system-site-packageによって仮想環境からOS側パッケージが使えるようになる。

cd ~
python3 -m venv --system-site-packages ~/python-env

3. Thonnyを起動し、仮想環境のインタプリタを使うように設定

ツール > 設定 > インタープリタ
「カスタムインタープリタを使用する」を選択し、仮想環境の Python インタープリタを指定。/home/<ユーザー名>/python-env/bin/python3

4. Thonnyをいったん終了、起動してShellタブで以下コマンド実行して確認

import sys
print(sys.prefix) 

/home/<ユーザー名>/python-env が表示されたらOK

ツール > パッケージの管理で任意のパッケージをインストール可能になる。

※個人的意見だが、仮想環境と聞くと仮想マシンとか仮想化みたいな事を連想する。そうじゃなくてOS側パッケージ管理とは別のパッケージ管理の状態を指すみたいな。そこならOS側からpipでパッケージいれるな!と怒られずに任意のパッケージを使ってプログラミングできる。apt installで入れるpythonパッケージはOSやデバイスに依存するものに限定して、その他は仮想環境でpipで入れて使うのが良さそう。

pipで入れ放題になったのでOpenCVのQRコード検出より高性能pyzbarを使ったプログラムがこれ。やってみたところOpenCVでは読めないライトニングインボイスがpyzbarだとすぐ読めた。すごい。

from picamera2 import Picamera2
from pyzbar.pyzbar import decode
import cv2

# Picamera2 の初期化
picam2 = Picamera2()
picam2.configure(picam2.create_video_configuration())  # mode3: FHD
picam2.start()

while True:
    # Picamera2 からフレームを取得
    frame = picam2.capture_array()

    # QR コードを検出してデコード
    qr_codes = decode(frame)  # `pyzbar` を使用してデコード

    for qr in qr_codes:
        # デコードされたデータを取得
        decoded_text = qr.data.decode('utf-8')  # QR コードの中身
        print(f"QRコードのデータ: {decoded_text}")

        # QR コードの位置情報を取得
        points = qr.polygon
        # QR コールにポリゴンを描く
        if len(points) == 4:  # ポリゴンが正方形であるか確認
            for i in range(len(points)):
                start_point = tuple(points[i])  # 始点
                end_point = tuple(points[(i + 1) % len(points)])  # 次の点
                cv2.line(frame, start_point, end_point, (0, 255, 0), 3)  # 線を描画

    # フレームを表示
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    display_frame = cv2.resize(frame_rgb, (960, 540), interpolation=cv2.INTER_AREA)  # Quarter HDにリサイズ
    cv2.imshow('QR Code Scanner', display_frame)

    # 'q' キーでプログラムを終了
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# リソースを解放
picam2.stop()  # Picamera2 を停止
cv2.destroyAllWindows()

有料パートには上記のpyzbarのプログラムに読み取ったインボイスをwebhookで飛ばす機能を追加したプログラムがあります。

この続き : 2414字 / 画像 0枚
100

会員登録 / ログインして続きを読む

関連記事

記事を書いた人

甘いもの大好きメタボ猫。マイペースなのはしょうがない。 nostr:npub10zeurmg22wc89l8m3npw9cyu45cun0lvs6w3ep69cdpa25pna65s0994qz

SNSにシェア

このクリエイターの人気記事

【Umbrel】BlueWallet Lightning & tailscaleで便利で快適なLightningウォレットを作ろう!

594

【Umbrel】OCEANからマイニング報酬をライトニングで受け取るには【Sparrow Wallet】

382

Bitcoin CPUソロマイニング(マイニングプール無し)

357