1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Streamlit×OpenCVでQRコードを読み取る

Posted at

この記事の概要

StreamlitとOpenCVを組み合わせることで、Webカメラで撮影した写真内のQRコードを読み取る機能を手軽に実装することができます。

サンプルコード

サンプルコードは以下の通りです。

st_qrcode.py
import streamlit as st
import cv2
import numpy as np

# QRコード検出器をロード
@st.cache_resource
def load_qrcode_detector():
    qrcode_detector = cv2.QRCodeDetector()
    return qrcode_detector

# カメラから画像を取得
img_file_buffer = st.camera_input("ボタンを押してQRコードをスキャンしてください", label_visibility="collapsed")

if img_file_buffer is not None:
    # OpenCV形式の画像データに変換する
    bytes_data = img_file_buffer.getvalue()
    cv2_img = cv2.imdecode(np.frombuffer(bytes_data, np.uint8), cv2.IMREAD_COLOR)

    # QRコードを検出
    qrcode_detector = load_qrcode_detector()
    detected, decoded_info, points, _ = qrcode_detector.detectAndDecodeMulti(cv2_img)

    if detected:
        # QRコードの情報が読み取れているかどうか確認
        count = 0
        for data in decoded_info:
            if data == "":
                continue
            count += 1
        if count == 0:
            st.warning("QRコードが見つかりませんでした")
            st.stop()

        st.caption("QRコードに含まれている情報")
        idx = 0
        for data in decoded_info:
            if data == "":
                continue
            idx += 1
            st.write(f"{idx}: ", data)

        img = cv2.polylines(cv2_img, points.astype(int), True, (0, 255, 0), 3)
        st.caption("QRコードの検出結果")
        st.image(img)
    else:
        st.warning("QRコードが見つかりませんでした")

実際に動作するアプリはこちらです。

Example

ポイント解説

Webカメラによる撮影

StreamlitではWebカメラによる撮影のためにst.camera_inputが用意されています。
これはユーザがボタンを押したときに画像を返してくれる関数です。

img_file_buffer = st.camera_input("ボタンを押してQRコードをスキャンしてください", label_visibility="collapsed")

QRコードの読み取り

OpenCVではQRコードを読み取るためにcv2.QRCodeDetectorという検出器が準備されています。
この検出器にOpenCV形式の画像データを渡すことで、QRコードを検出して、QRコードに含まれる情報を読み取ることができます。

detected, decoded_info, points, _ = qrcode_detector.detectAndDecodeMulti(cv2_img)
  • detected: QRコードを検出したかどうか
  • decoded_info: QRコードからデコードした文字列。複数のQRコードの同時読み取りに対応していて、文字列の配列が返してくれる
  • points: 画像の中のどこからQRコードを検出したかを示す座標

画像フォーマットの変換

st.camera_inputが返す画像をOpenCV形式の画像データに変換する必要があります。

bytes_data = img_file_buffer.getvalue()
cv2_img = cv2.imdecode(np.frombuffer(bytes_data, np.uint8), cv2.IMREAD_COLOR)

詳細はStremalitのドキュメントを確認してください。
OpenCV以外に、Pillow、TensorFlow、Torchvision、PyTorchで画像を扱うサンプルが掲載されています。

ライブラリのインストール

必要なライブラリは以下の通りです。

pip install streamlit opencv-python numpy

Streamlit Community Cloudのようなデスクトップがない環境だとOpenGLなどが使えないため、以下のように別のライブラリを用いる必要があるようです。

pip install streamlit opencv-python-headless numpy

まとめ

StreamlitでWebカメラによる撮影ができるようになったことで、OpenCVの豊富な機能を活かした色んなアプリが作れそうですね!
今回はシンプルなQRコードリーダーを実装してみました。

ちなみに、今回はユーザがボタンを押したときにQRコードを読み取るというものでしたが、Webカメラに写っているものをリアルタイムにチェックして自動的にQRコードを読み取りたいというときはstreamlit-webrtcという3rdパーティーコンポーネントを利用するのがよさそうです。
ぜひチャレンジしてみてください!

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?