本記事で紹介するプログラムは以下の GitHub リポジトリで公開しています
記事一覧
本連載は全3回構成です。各ステップでシステムの構築から実機運用までを解説しています。
はじめに
第 2 回では Windows + Web カメラで ROI 設定 → 実映像検知 → Workers 経由 Discord 通知 まで確認しました。 最終回となる本記事では、Raspberry Pi 5 へ移植し、 常時監視 を実現します。
- 使うプログラム:Raspberry Pi 版(V4L2 明示、バッチ通知、HMAC 署名)
- ROI は第 2 回の ROI ツール
roi_tool.pyで作成したconfig.yamlをそのまま流用可能(必要なら再調整)

セットアップ手順(Raspberry Pi OS, 64-bit)
1) 依存パッケージの導入
sudo apt update
sudo apt install -y python3-pip python3-opencv python3-numpy \
libatlas-base-dev v4l-utils git
メモ:
opencv-pythonをpipで入れるとビルドに時間がかかるため、まずは apt の python3-opencv を推奨。必要なら後でpip install opencv-pythonに切り替え。
2) カメラ権限とデバイス確認
# video グループに追加(再ログイン後に反映)
sudo usermod -aG video $USER
# /dev/video* の有無を確認(USB/UVC カメラ)
v4l2-ctl --list-devices
- USB/UVC カメラ:そのまま
/dev/video0として使用可能 - Raspberry Pi カメラ(libcamera 世代):
libcamera-vid等で映像確認のうえ、UVC ブリッジ経由か UVC カメラ採用を推奨(本構成は V4L2/UVC を前提)
3) プロジェクト配置
# 任意のディレクトリへ
mkdir -p ~/lamp-monitor && cd ~/lamp-monitor
このディレクトリに以下を配置します:
monitor_webcam-pi.py(本記事で紹介する Raspberry Pi 版スクリプト)config.yaml(ROI 含む設定ファイル).env(通知先 URL と Secret を格納する環境変数ファイル)
環境変数の設定
1) .env.example を用意
# Lamp Monitor Environment Variables
# このファイルを .env にコピーして実際の値を設定してください
# Cloudflare Workers URL
LAMP_MONITOR_WORKER_URL=https://your-worker.workers.dev
# 通知用の共通鍵(Cloudflare WorkersのSECRET_KEYと一致させる)
LAMP_MONITOR_SECRET=your_secret_key
2) .env ファイルを作成
cp .env.example .env
nano .env
必要に応じて LAMP_MONITOR_WORKER_URL と LAMP_MONITOR_SECRET を編集してください。
config.yaml の記述例
camera:
device_id: 0
size: [1280, 720]
fps: 20
notify:
# 値を直書きせず、環境変数を参照
worker_url: ${LAMP_MONITOR_WORKER_URL}
secret: ${LAMP_MONITOR_SECRET}
min_interval_sec: 5
# ここに lamp_1..lamp_12 の ROI を記述(ROIツールの出力を貼り付け)
rois:
lamp_1: [x, y, w, h]
...
.env → config.yaml の ${...} → Python コードで展開、という流れで
Workers URL と Secret を安全に読み込める仕組みになっています。
実行方法
python3 monitor_webcam-pi.py
起動すると:
V4L2 バックエンド(
cv2.CAP_V4L2)でカメラを初期化ROI ごとに HSV 解析 → RED/GREEN/UNKNOWN 判定
多数決(履歴窓+合意率) と 最小信頼度 でノイズ除去
近接検出はバッチ化して Workers→Discord にまとめて通知
- 例:
複数のランプが RED 状態になりました: ランプ 1, 6, 9 (3個)
- 例:
実行中の操作
q/ESC:終了s:現在フレームを保存(トラブル時の証跡)r:ランプ履歴をリセット(しきい値調整後の再収束に)
スクリプトのポイント(差分と最適化)
V4L2 明示指定:
cv2.VideoCapture(device_id, cv2.CAP_V4L2)Linux/Raspberry Pi では安定度・遅延の面で効果的低遅延設定:
CAP_PROP_BUFFERSIZE=1、フレームサイズ/ fps を過不足なく誤検知抑制:
- 履歴窓(
frames_window)+ 合意率 ≥ 0.6 - min_brightness_v で暗部ノイズ除去
- 形態学的処理(オープン)で小ノイズ除去
- 履歴窓(
バッチ通知: 短時間(デフォルト 2 秒)に複数の RED が発生したら 1 通で集約 Discord 側の通知スパム防止に有効
HMAC 署名(
X-Signature-256):json.dumps(..., sort_keys=True)で Workers 側と完全一致の文字列から署名生成(第 1 回と同じ作法)
現場チューニングのコツ
露出/ゲイン/ホワイトバランスは固定推奨(色が安定)
- UVC カメラ付属ユーティリティや
v4l2-ctlで調整
- UVC カメラ付属ユーティリティや
HSV しきい値(
logic.red_*,logic.green_*)は環境光で変わる- 実機のランプ色分布を見ながら微調整
frames_window / 合意率 / 最小信頼度は現場のノイズ量で調整
- 安定性 ↑ ↔ 応答遅延 ↑ のトレードオフ
電源・熱対策:5V/3A クラスの電源、ヒートシンク/ファンでスロットリング回避
- 低電圧や高温は FPS 低下・フレームドロップの原因に
常時運用(ヘッドレス)に向けて:systemd サービス化
モニタ無し・自動起動で運用する場合は systemd 化が便利です。
1) サービスファイル作成
sudo nano /etc/systemd/system/lamp-monitor.service
[Unit]
Description=Lamp Monitor (Raspberry Pi, V4L2)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/lamp-monitor
ExecStart=/usr/bin/python3 /home/pi/lamp-monitor/monitor_webcam-pi.py
Restart=always
RestartSec=5
Environment=PYTHONUNBUFFERED=1
# GUI が無い環境でも動くように(imshow を使わない構成で運用)
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
GUI なし運用では
cv2.imshowが使えないため、本番は 表示なし(保存ログ+ Discord 通知) で評価するのがシンプルです。必要ならフレーム保存機能(s)を活用。
2) 起動・自動起動設定
sudo systemctl daemon-reload
sudo systemctl enable lamp-monitor
sudo systemctl start lamp-monitor
# ステータス確認
sudo systemctl status lamp-monitor --no-pager
# ログ確認
journalctl -u lamp-monitor -f
まとめ
- Raspberry Pi 5 へ移植し、V4L2 +軽量ロジック+バッチ通知 で現場常時監視を実現しました。
- 第 1 回の Workers(HMAC 検証)と合わせて、安全に Discord へ通知。
- 第 2 回で作った Windows の流れをそのまま踏襲でき、設定(
config.yaml)を共有可能。
これで 要件「緑 → 赤の異常を確実に検知し、Discord に通知」 を Raspberry Pi 実機で達成です。