この記事の概要
StreamlitとOpenCVを組み合わせることで、Webカメラで撮影した写真内のQRコードを読み取る機能を手軽に実装することができます。
サンプルコード
サンプルコードは以下の通りです。
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コードが見つかりませんでした")
実際に動作するアプリはこちらです。
ポイント解説
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パーティーコンポーネントを利用するのがよさそうです。
ぜひチャレンジしてみてください!