10.6.2 プロジェクト:スマート防犯システム
防犯プロジェクトは、「人を検出したら枠を描く」だけの demo になりがちです。
でも、本当に納品できる防犯システムが重視するのは、たいてい枠そのものではなく、次の点です。
- アラートが正確か
- 同じ内容を何度も報告しないか
- レイテンシが十分低いか
- 誤報で人をうんざりさせないか
なので、このレッスンでは単発の検出デモではなく、作品レベルのシステムプロジェクトにすることを重視します。
学習目標
- 納品可能な防犯検知タスクの境界を定義できるようになる
- 検出、ルール、アラート、重複排除を一つの閉ループとしてつなげられるようになる
- 最低限の評価と失敗分析を設計できるようになる
- このプロジェクトを説得力のある作品集として見せられるようにする
一、まずプロジェクトのテーマをはっきり決める
練習にも向いていて、実務にも近いテーマとしては、次のようなものがあります。
「立ち入り禁止地域侵入アラートシステム」を作る。監視カメラのフレーム列を入力し、「アラートが発生したか + どのフレームで発生したか」を出力する。
このテーマの良いところは次のとおりです。
- 目的がシンプル
- ビジネス上の意味が分かりやすい
- 誤報と見逃しを説明しやすい
なぜ最初から大きくしすぎない方がいいの?
たとえば次のようなものです。
- 火災検知、転倒検知、安全ヘルメット検知、車両認識を同時にやる
このように範囲が広すぎると、プロジェクトが機能の寄せ集めになりやすく、一本のはっきりした主線がなくなってしまいます。
二、作品レベルの防犯プロジェクトの最小閉ループは何か?
- 監視対象と立ち入り禁止地域を定義する
- 検出する
- 検出ボックスをアラートロジックに変換する
- 重複排除 / トラッキングを行う
- アラート品質を評価する
- 成功例と失敗例を見せる
最初の2ステップだけなら、まだモデル demo に近いです。
その先までできて、はじめてシステムプロジェクトらしくなります。
実際のシステムらしいアラート閉ループ図
この図はとても重要です。なぜなら、次のことを思い出させてくれるからです。
- 防犯システムが本当に納品するのはアラート体験
- 単一画像上の枠ではない

防犯プロジェクトの出力は「枠を描くこと」ではなく、信頼できるアラートです。図を読むときは、検出結果がどのようにルール判定へ入り、track_id がどのように重複報告を防ぎ、最後に人手確認、ログ、失敗振り返りへつながるかを重点的に見てください。
三、まずは「検出 -> アラート -> 重複排除」の最小閉ループを動かす
次の例では、とても重要な3つの処理を行います。
- フレームごとの検出結果を読み込む
- 危険地域に入っているか判定する
- 同じ対象の連続複数フレーム命中をアラート重複排除する
detections = [
{"frame": 1, "track_id": 101, "label": "person", "box": (40, 40, 80, 120)},
{"frame": 2, "track_id": 101, "label": "person", "box": (42, 42, 82, 122)},
{"frame": 3, "track_id": 101, "label": "person", "box": (44, 45, 84, 125)},
{"frame": 4, "track_id": 202, "label": "person", "box": (150, 150, 180, 210)},
]
danger_zone = (30, 30, 100, 140)
def is_inside(box, zone):
bx1, by1, bx2, by2 = box
zx1, zy1, zx2, zy2 = zone
return bx1 >= zx1 and by1 >= zy1 and bx2 <= zx2 and by2 <= zy2
def build_alerts(detections, zone):
active_tracks = set()
alerts = []
for det in detections:
inside = det["label"] == "person" and is_inside(det["box"], zone)
if inside and det["track_id"] not in active_tracks:
alerts.append(
{
"frame": det["frame"],
"track_id": det["track_id"],
"alert": "intrusion",
}
)
active_tracks.add(det["track_id"])
elif not inside and det["track_id"] in active_tracks:
active_tracks.remove(det["track_id"])
return alerts
alerts = build_alerts(detections, danger_zone)
print(alerts)
実行結果の例:
[{'frame': 1, 'track_id': 101, 'alert': 'intrusion'}]
track 101 が初めて危険エリアに入ったときだけアラートが出ます。2フレーム目と3フレーム目は、同じ track がすでに active なので重複アラートになりません。
この例が「人を検出したらアラート」よりずっと強い理由
それは、防犯システムで最も重要な実務判断がすでに入っているからです。
- 同じ人が禁区内に3フレーム連続でいても
- 3回アラートを出してはいけない
なぜ track_id が重要なのか?
トラッキング情報がないと、次の区別が難しくなります。
- 同じ人なのか
- それとも3人の別人なのか
そのため、防犯プロジェクトが「検出」から「システム」へ進むとき、
よく詰まるのがこの層です。
四、作品レベルのプロジェクトは、どう評価するべきか?
検出精度だけを見ない
防犯プロジェクトは、少なくとも次の2層に分けて評価するのがおすすめです。
- 検出層
対象をちゃんと見つけられているか - アラート層
アラートの発火が適切か
最小のアラート評価例
pred_alerts = [
{"frame": 1, "track_id": 101, "alert": "intrusion"},
]
gold_alerts = [
{"frame": 1, "track_id": 101, "alert": "intrusion"},
{"frame": 8, "track_id": 303, "alert": "intrusion"},
]
def alert_recall(pred_alerts, gold_alerts):
gold_set = {(x["frame"], x["track_id"], x["alert"]) for x in gold_alerts}
pred_set = {(x["frame"], x["track_id"], x["alert"]) for x in pred_alerts}
hit = len(gold_set & pred_set)
return hit / len(gold_set) if gold_set else 1.0
print("alert_recall:", round(alert_recall(pred_alerts, gold_alerts), 4))
実行結果の例:
alert_recall: 0.5
必要な2つのアラートのうち、システムが捉えたのは1つだけです。だからこそ、アラート層の評価は、検出スクリーンショットだけでは見えない問題を明らかにできます。
なぜ「アラート層の指標」は mAP よりもプロジェクト価値に近いのか?
実際にユーザーへ納品されるのは、枠ではなく、
- アラート
だからです。
検出がかなり正確でも、アラートの出し方が悪ければ、
実際の体験はやはり良くなりません。
最小の「アラート疲れ」例も見てみる
alerts_per_hour = [1, 2, 18, 3, 21]
def alert_fatigue(hours):
too_many = sum(1 for x in hours if x >= 10)
return "アラートが多すぎて、ユーザーはそのうち無視し始める可能性が高い" if too_many >= 2 else "アラート密度はひとまず許容範囲"
print(alert_fatigue(alerts_per_hour))
実行結果の例:
アラートが多すぎて、ユーザーはそのうち無視し始める可能性が高い
ここではアラート数をユーザー体験のシグナルとして見ています。アラートが多すぎると、技術的には動いていても、実際には誰も信じなくなる可能性があります。
この例で伝えたいのは、正確な数式ではなく、かなり現実的なシステム上の問題です。
- アラートは多ければ多いほど良いわけではない
- 誤報が多いと、ユーザーは徐々にシステムを信用しなくなる
五、防犯プロジェクトで特に見せる価値がある失敗例
誤報
たとえば:
- 背景の人物ポスターを本物の人と誤認する
見逃し
たとえば:
- 暗い場所で侵入者を見逃す
重複報告
たとえば:
- 同じ対象に対して毎フレーム1回ずつ発火する
なぜこれらを個別に見せるのか?
こうした失敗は、まさに次の点を一番よく表してくれるからです。
- システム設計が成熟しているかどうか
六、このプロジェクトを作品レベルの展示にするには?
少なくとも、ページには次の内容を入れることをおすすめします。
- タスク定義
- 危険地域の図
- 検出結果とアラート結果の比較
- 連続動画クリップ中のアラート軌跡
- 誤報 / 見逃し / 重複報告の分析
こうすると、もはや「検出 demo」ではなく、完成した防犯システムに近づきます。
初めてこの種のプロジェクトを作るときの、いちばん安定した進め方
より安定した順番は、普通は次のとおりです。
- まずアラートの種類を1つに絞る
- 単一カメラ、単一シーンの baseline から始める
- 立ち入り禁止地域とルールをはっきり描く
- その後で重複排除と簡単なトラッキングを足す
- 最後にアラート品質の分析を行う
これなら、最初から次のようなことを全部やろうとするよりも、ずっと完成させやすいです。
- 複数カメラ
- 複数種類のアラート
- 複数ルールの連動
作品集として見せるなら、何を強調すべきか
強調すべきなのは、たいてい次のような点です。
- モデルがどれだけ派手か
ではなく、
- なぜそのアラートルールにしたのか
- どうやって重複報告を処理したのか
- 誤報と見逃しはどこから来るのか
- システムの境界はどこか
これがあると、プロジェクトが視覚デモではなく、実務システムに近く見えます。
七、よくある誤解
モデル精度だけを見て、アラート体験を見ない
重複排除ロジックがない
成功動画だけを見せる
まとめ
この節で最も大事なのは、作品レベルの見方を身につけることです。
防犯システムの価値は、どれだけ多くの枠を描けるかではなく、検出結果を安定して、誤報少なく、信頼できるアラートへ変換できるかにある。
この1層をしっかり作れれば、このプロジェクトはかなり実務に近いものになります。
この節で持ち帰るべきこと
- 防犯プロジェクトが本当に納品するのは検出ボックスではなくアラート
- 重複排除、トラッキング、ルール判定は、モデル本体と同じくらい重要
- まともな作品レベルの防犯プロジェクトでは、誤報、見逃し、アラート体験を必ず見せる
バージョンの進め方のおすすめ
| バージョン | 目標 | 納品の重点 |
|---|---|---|
| 基礎版 | 最小閉ループを通す | 入力できる、処理できる、出力できる、そして一組の例を残す |
| 標準版 | 見せられるプロジェクトにする | 設定、ログ、エラー処理、README、スクリーンショットを追加する |
| 挑戦版 | 作品集クオリティに近づける | 評価、比較実験、失敗サンプル分析、次のステップの方針を追加する |
まずは基礎版を完成させるのがおすすめです。最初から大きく広げすぎないでください。バージョンを1段階上げるたびに、「何が新しくできるようになったか、どう検証したか、まだ何が問題か」を README に書きましょう。
練習
- 例に
helmetカテゴリを追加して、「ヘルメット未着用」アラートを設計してください。 - 考えてみましょう。なぜ防犯プロジェクトは普通の検出プロジェクトよりも、トラッキングと重複排除が必要なのですか?
- 誤報が多いとき、まず確認するのはデータ、モデル、それともアラートロジックですか? その理由も考えてください。
- このプロジェクトを作品集として見せるなら、どの連続動画 trace を一番強調したいですか?