主模型(CNN / YOLO cascade)先偵測 → 對需要複核的偵測結果,把該 person 區域餵給 VLM 問一個是非題 → VLM 的判斷與主模型對照,作為「二次確認 / FP 過濾」。不是取代主模型,是接在後面當守門員。
| 環節 | 結論 | 備註 |
|---|---|---|
| VLM 模型 | Qwen2.5-VL-7B | gx10/4t 已部署可跑。研究首選原為 InternVL3-8B,但大樣本證明兩者差異 ~2pp、CI 重疊不顯著,且 InternVL3 在 prod transformers 5.9 跑不動 → 實務用 Qwen |
| 視覺標記 | crop 放大 / context-margin crop | 完勝「整張+黃框」。per-person 小目標要給 VLM 更多頭部像素;整張+框只適合 scene-level(雜物偵測) |
| Prompt | 英文 yes/no 短問句 | 例:Is the person inside the box wearing a hard hat? Answer yes/no/uncertain + one reason。CoT / JSON / 中文都沒更好還更慢 |
| 速度 | gx10 Qwen ~15s/張(warm)/ ~105s(cold 首次載入) | 研究報的 0.7s 是 InternVL3 在別張卡;DGX Spark GB10 的 VLM 推論本來就慢 |
| 用途 | 數字 | 意義 |
|---|---|---|
| 當 FP 過濾器:抓回主模型假陽性 | 64.7% | 主模型誤判「違規」的,VLM 抓出約 2/3 |
| 救回主模型假陰性 | ~70% | 主模型漏判的也能補一部分 |
| 與人工判讀一致率 | 90.6% | 去掉 cvat 標註噪音後 |
| 屬性 | VLM vs 專用 CNN | 結論 |
|---|---|---|
| hard_hat 安全帽(模糊區) | 77.5 vs 57.3 | 值得VLM 強,語意判讀補 CNN 不足 |
| 反光衣 safety_vest | 95.4 vs 96.9 | 不需CNN 已強、打平 |
| 護目鏡 safety_glasses | 69.2 vs 89.2 | 別用小目標 VLM 弱 |
| 口罩 face_mask | 75.4 vs 96.2 | 別用CNN 大勝 |
→ VLM verifier 不是萬用。價值集中在「語意可混淆 + 目標夠大」的屬性。CNN 已做得好的(小目標、清晰特徵)VLM 補不了,加上去純浪費算力。iSeek 降誤報第一個、也可能是唯一一個值得接 VLM 的 = hard_hat。
誤報就發生在 app.py 的 iSeek alert state machine(約 line 2466–2509):對 hard_hat < thr 持續 sustained 秒 → fire alert + send_webhook("iseek_alert") 通報 ISMS。主模型在 sustained 期間一直把「有戴」誤判成 <thr,就誤報。
關鍵:只在 sustained 達標、即將通報的那一刻觸發一次 VLM(不是每幀),成本可控;~15s 延遲對「持續數秒才報」的告警完全可接受。
live / 影片 /result viewer 每個 person 旁「🔍 問 VLM(安全帽)」鈕 → 後端 context-margin crop → Qwen → 回 verdict + 理由。純人工輔助、不自動改判定。
⚠️ 已知 bug 修復中:/result viewer 的鈕 onclick handler vlmVerifyHardHat 漏定義在前端 template(後端 API 100% 正常,已 browser 實測 verdict=no/19s/200)。
iSeek rule 加 vlm_verify flag(UI checkbox,只 hard_hat)。alert fire 前把違規 person crop 丟背景 bounded queue(500) + worker thread(不阻塞 inference_loop)→ VLM 判讀 → 寫 data/vlm_shadow.jsonl。
看數據 API:GET /api/vlm-shadow(n / by_verdict / queue_pending / 估算「開否決會降多少 FP、誤殺多少」)。
| 資產 | 位置 / 介面 | 狀態 |
|---|---|---|
| 單張驗證 API | POST /api/verify_attr{source: live|job|cvat, file_id, frame_number, bbox, attr:"hard_hat"} → {verdict, reason, latency_s} | ✅ 兩台上線 |
| 影子統計 API | GET /api/vlm-shadow | ✅ 兩台上線 |
| iSeek rule VLM flag | rule dict 加 vlm_verify + UI checkbox(只 hard_hat) | ✅ |
| 背景 verify queue + worker | bounded(500),alert fire 非阻塞 enqueue | ✅ |
| 影子 log | data/vlm_shadow.jsonl(ts, attr, model_prob, vlm_verdict, reason, agree) | ✅ |
| VLM backend | ClutterVLMHandler._vlm_load + Qwen2.5-VL 單槽 cache(按需載入,與雜物偵測共用) | ✅ |
| 前端 verify 鈕 | RESULT_HTML / live sidebar 「問 VLM」鈕 | ⚠️ JS handler 修復中 |
Source repo:5090 ~/rai-model-viewer(commit e85d7a5 階段1 / c469a34 階段2)。部署:scp app.py → gx10 docker cp + restart → gx10-4t 同步。VLM 推論在 gx10/4t production 機按需載入。
vlm_shadow.jsonl/api/vlm-shadow:看 agree-rate、看「VLM 否決會降多少 FP / 誤殺多少」的場域實數(不是研究的 dataset 數字)