post-cover

本記事で紹介するプログラムは以下の GitHub リポジトリで公開しています

GitHub - isec-promotion/lamp-monitor

記事一覧

本連載は全3回構成です。各ステップでシステムの構築から実機運用までを解説しています。

はじめに

第 2 回では Windows + Web カメラで ROI 設定 → 実映像検知 → Workers 経由 Discord 通知 まで確認しました。 最終回となる本記事では、Raspberry Pi 5 へ移植し、 常時監視 を実現します。

  • 使うプログラム:Raspberry Pi 版(V4L2 明示、バッチ通知、HMAC 署名)
  • ROI は第 2 回の ROI ツール roi_tool.py で作成した config.yaml をそのまま流用可能(必要なら再調整)

lamp-monitor-01-description


セットアップ手順(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-pythonpip で入れるとビルドに時間がかかるため、まずは 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_URLLAMP_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]
  ...

.envconfig.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 で調整
  • 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 実機で達成です。

SNSでシェアしよう

この記事が役に立ったら、ぜひシェアしてください