🚓 ai_police 登入

🚓 ai_police — 監控儀表板

即時鏡頭預覽

畫面上的框是 M3 在伺服器端直接燒進畫格的,跟畫面本身同步(不是前端事後疊加)。優先用 WebRTC 播放(延遲通常在 1 秒內),網路環境不支援時自動退回 HLS(延遲較高,通常好幾秒)。分割畫面會同時對每支啟用中的鏡頭各開一條連線,鏡頭一多會吃比較多頻寬/瀏覽器解碼資源。在人臉框附近按右鍵可以替該 Global ID 標記姓名/代號。

即時偵測記錄(M2 人流 / M3 人臉比對)

武器/暴力/火煙這三種才算「事件」,會出現在下面的「最近事件」;單純有人經過鏡頭前不算事件、不會觸發通知,但 M2/M3 其實一直在背景偵測,這裡把原始結果攤開來看。

各鏡頭目前人數

鏡頭人數更新時間

最近人臉比對

時間鏡頭Global ID信心分數

已知人員(近 10 分鐘,人臉縮圖 + 跨鏡頭紀錄)

每張卡片是一個 Global ID,縮圖是最新一次看到這個人的樣子。只顯示最近 10 分鐘內出現過的人——目前人臉比對還不夠穩定,同一個人有時會被誤判成新的 Global ID,只看「最近」可以避免清單一直累積一堆早就不在場的舊卡片。

Global ID 軌跡查詢(規格 M8)

最近事件

時間類型鏡頭信心分數優先級VLM複核人工審核

匯出訓練資料

只導出已經人工審核過(標記「確認」或「誤報」)的事件,沒審核過的原始偵測結果可能是雜訊,不會混進去。內容是一個 ZIP:manifest.json(每筆事件的完整中繼資料)+ 對應的錄影片段(如果那筆事件當時有錄到,不是每筆都有)。只做「收集/導出標註資料」,不含任何模型微調邏輯。只有 admin 能導出。

稽核日誌(規格 M15)— 誰查了軌跡

「操作者」欄是登入中的帳號(見「👤 帳號管理」);2026-07-16 前的舊紀錄沒有登入系統,這欄會是空的。
時間查詢內容目標 Global ID操作者

班次報告

選一段時間範圍,LLM 會彙整這段時間所有事件生成一份可讀的交班報告(沿用「AI 管理」頁設定的使用中模型)。產生時間視事件數量跟 LLM backend 速度而定,可能需要數十秒。

Email 通知

跟 LINE 是並行的兩個獨立管道,高優先級事件(武器/暴力/火煙/區域入侵/徘徊/跌倒/監控名單比對)都會兩邊各發一次。原本是 .env 設定,現在改到這裡管理,不用改設定重新部署。只有 admin 帳號能修改。

LINE 通知

跟 Email 是並行的兩個獨立管道,高優先級事件都會兩邊各發一次。4 個關鍵參數都要在 LINE Developers Console 建立 Messaging API channel 後取得:Channel ID(頻道識別碼,純參考用)、Channel Secret(驗證 webhook 簽章用)、Channel Access Token(呼叫推播 API 用,需在後台另外生成)、Webhook URL(下方已經幫你算好,複製貼到 LINE 後台的 Webhook URL 欄位並按「Verify」)。只有 admin 帳號能修改這裡的設定。

最近收到的 LINE ID

加 bot 好友或把 bot 拉進群組後,這裡會出現對應的使用者/群組 ID(webhook 收到 follow/join 事件才會有紀錄,記得先設定好 Channel Secret+Webhook URL)。點「使用這個」直接帶入上面的 Target ID 欄位。
類型ID名稱發現時間

Microsoft Teams 通知

跟 Email/LINE 是並行的獨立管道。注意:Teams 舊版「Incoming Webhook」連接器已於 2026 年 5 月停用,請改用 Workflows:在目標頻道打開「⋯」→「工作流程」,選「當收到 Webhook 要求時張貼到頻道」範本建立,完成後把產生的 URL 貼到下面。這裡送出的內容是最簡單的 {"text": "..."} 格式(Microsoft 官方快速入門範例也是這樣示範),如果你自訂的工作流程觸發條件沒有對應 text 欄位,測試會顯示連線成功但頻道實際上收不到訊息,請检查工作流程的欄位對應設定。只有 admin 帳號能修改。

Webhook 串接

給機器串接用(例如既有警政系統),跟 Email/LINE/Teams 給人看的文字訊息不同——送出結構化 JSON:{event_id, event_type, event_type_label, camera_id, confidence, vlm_verified, vlm_description, priority, created_at, message}。Secret 選填,設定後每次請求會附上 X-Signature: sha256=... header(HMAC-SHA256,key 是 secret、input 是原始 request body 位元組),你的系統可以用同樣方式計算比對,確認請求真的是這裡發出的,不是被冒名偽造。只有 admin 帳號能修改。

Slack 通知

跟 Email/LINE/Teams 是並行的獨立管道。請在目標 Slack workspace 的 App 設定裡開啟 Incoming Webhooks、選擇要貼文的頻道,複製產生的 https://hooks.slack.com/services/... URL 貼到下面即可,不需要額外的觸發條件設定。只有 admin 帳號能修改。

通知內容範本

Email 內文跟 LINE 推播文字共用同一份範本內容。可用欄位:。「預設範本」套用到所有沒有專屬範本的事件類型,也可以針對特定事件類型另外建立專屬範本(優先套用)。

新增鏡頭

新增後約 20 秒內,M2-M6 偵測服務會自動開始處理這支鏡頭,不需要重新部署。

鏡頭清單

名稱廠牌型號狀態啟用RTSP

已標記人員

在即時預覽畫面的人臉框附近按右鍵可以新增標記。這裡管理已經標記過的人員:修改姓名,或取消標記(只是移除姓名標籤,不影響 Re-ID 比對本身——下次比對到同一張臉,Global ID 還是同一個,只是不會再顯示姓名)。

比對測試 / 合併 / 拆分

AI 自動判斷不保證每次都對——同一人可能被拆成好幾個 Global ID(比對不到),或反過來兩個不同人被誤併成一個。這裡先用「比對測試」看兩個 ID 實際的相似度數據,確認後再決定要不要合併/拆分。Global ID 直接輸入完整 UUID(可以從已知人員卡片、或最近人臉比對紀錄裡複製)。

身份判斷紀錄

AI 自動重新比對改綁(auto_rebind)、操作者手動合併/拆分/改名,都記在這裡,方便回頭查一個 Global ID 為什麼變成現在這樣。
時間類型鏡頭分數備註

Re-ID 比對設定

調整 M3 人臉/身體比對的門檻與模型。門檻/重新比對頻率存檔後 M3 會在幾秒內自動套用,不用重啟;更換比對模型例外,一定要重新啟動 m3-reid 服務才會生效,而且會自動清空目前累積的身體外觀樣本(不同模型的向量沒辦法互相比較,混著比只會產生雜訊)。
設越低越容易跨鏡頭配對成功,但也越容易把不同人誤判成同一人;設越高越保守。實測參考:不同人身體外觀相似度通常在 0.3~0.55,同一人跨視角可以到 0.6~0.9 不等,依鏡頭角度差異而定。
設越低越容易跨角度/光線配對成功,但也越容易把不同人誤判成同一人。
如果一個人被同一支鏡頭連續追蹤、track_id 從沒斷過(例如坐著不動),身體比對就只有追蹤剛出現那一刻有機會跟別支鏡頭配對——這個頻率決定多久重新比對一次已經綁定的追蹤,抓到更好的跨鏡頭配對就會改綁。
重新比對配到「不一樣」的身份時,要連續配到同一個候選幾次才真的改綁——設 1 代表配到就馬上改,分數在門檻附近徘徊時容易反覆跳動;設高一點比較穩,但反應會慢一點。
超過這個天數沒更新的樣本會自動從資料庫清掉(換季換衣服後舊樣本反而可能誤導比對)。每小時清一次,不是存檔後立刻生效。

個別鏡頭配對門檻

同一組門檻不見得適合所有鏡頭組合——視角差很大的兩支鏡頭,身體外觀相似度天花板可能明顯比視角接近的組合低。這裡可以針對特定鏡頭配對覆蓋上面的全域身體比對門檻,沒設定的組合維持用全域值。
鏡頭 A鏡頭 B門檻

M3 效能狀態

這台主機 GPU 是多租戶共用(曾發生過過載事件),這裡可以快速確認 M3 自己的資源用量是否正常,不用每次都進容器查。
鏡頭狀態最後心跳目前追蹤人數GPU 記憶體

人臉追蹤

挑選一個人(已標記姓名的優先,也可以直接貼 Global ID),依日期時間查詢他經過哪些鏡頭(區域)、幾點到達、待了多久——底層資料跟「Global ID 軌跡查詢」共用,但這裡是給人直接看的清單,不是座標點。
鏡頭(區域)到達時間離開時間停留時長偵測次數

車牌讀取紀錄

M16(規格外新增)車牌辨識模組的出入紀錄,一律記錄(不管有沒有命中監控名單)。信心門檻/取樣間隔/冷卻時間在「🚨 危險識別」頁一起管理(module 名稱 m16_anpr)。
📥 匯出訓練資料
時間鏡頭圖片車牌號碼信心分數車種顏色人工複核

車牌監控名單

命中會自動寫一筆高優先級事件,觸發 Email 告警(沿用既有 M9 告警管線)。
車牌號碼標籤分類建立時間

影片測試(驗證真實準確率)

上傳行車紀錄器/路口影片,或貼一段 YouTube 網址,用真實畫面驗證模型準確率——這個環境沒有真實台灣車牌照片可測,這是目前唯一能用真實素材驗證的方式。這裡只回傳辨識結果供檢視,不會寫進上面的「車牌讀取紀錄」(那是正式監控的出入紀錄,測試資料不應該混進去)。影片較長時處理可能需要幾分鐘,請耐心等候;為了保護共用 GPU,單次最多處理 10 分鐘份的影片。
影片裡如果穿插不相關的畫面(例如車外景色、字卡),可以框選只要辨識車牌的範圍——上傳檔案先把預覽播放/拖曳到想要的畫面,YouTube 網址則輸入時間點後擷取;框選範圍會套用到整段影片,不框選就是分析整個畫面(原本的行為)。

📊 事件統計(D-013 P1)

查詢區間內 events 表的統計彙總。之後階段會再加通知發送報表 / 裝置稼動率報表 / 人流車流趨勢報表,見 docs/DECISIONS.md D-013。



🔔 通知發送統計(D-013 P2)

查詢區間內 alerts 表的發送結果。「延遲」是事件發生到 M9 處理到這筆的時間差(佇列輪詢延遲的代理指標),不是保證對方真的收到的端對端送達時間。



🖥️ 裝置稼動率(D-013 P3)

統計依據是 device_status_history 表——中控每 30 秒被動判斷一次「這台裝置的 last_heartbeat 是否超過 90 秒沒更新」,狀態真的改變(上線↔離線)才寫一筆,不主動對裝置發連線探測。這是被動統計,不是即時告警:只要裝置狀態監看是最近才啟用的,或查詢區間早於監看開始的時間,該裝置會顯示「資料不足」而不是假造一個數字。



🚗 人流 / 車流趨勢(D-013 P4)

person_counts(M2 人流)/plate_reads(M16 ANPR 車流)已轉成 TimescaleDB hypertable,彙總在資料庫層做。



⏰ 報表排程

到點自動重新彙總「事件統計/通知發送/裝置稼動率/人流車流趨勢」四種報表其中一種,用 Email 寄送 Excel/PDF 附件——不用每次都手動進來查詢。寄送時間是臺灣時間(UTC+8),daily 涵蓋昨天一整天、weekly 涵蓋過去 7 天、monthly 涵蓋上個完整月,範圍固定不能額外篩選鏡頭/裝置。
報表頻率時間(臺灣時間)格式收件人上次寄送啟用

新增排程

警戒線 / 區域

選鏡頭抓一張畫格當底圖,在上面點出警戒線(點 2 點)或區域(點多點,點完按「儲存」即封閉)。座標存成相對比例(0-1),鏡頭解析度改變也不用重畫。同一個區域可以同時當「虛擬警戒線/入侵偵測」跟「徘徊偵測」用(線只能做入侵偵測,徘徊偵測只對區域有意義)。「忽略煙火偵測」也只對區域有意義:框住畫面裡容易被誤判成火/煙的固定物件(例如螢幕、反光物),M6 就會跳過該區域,不受影響其他偵測模組。「違規停車偵測」(M23)一樣只對區域有意義:畫出禁停區,車輛停留超過門檻秒數才觸發,跟徘徊偵測是同一種邏輯換成偵測車輛。

此鏡頭現有的區域

名稱類型入侵偵測徘徊偵測徘徊門檻(秒)忽略煙火偵測違規停車偵測停車門檻(秒)冷卻(秒)啟用

一次性以圖搜圖

上傳照片,立即查詢過去是否有鏡頭拍到長得像的人(不會建立監控名單,查完就結束)。
Global ID / 姓名鏡頭最後出現時間相似度

新增監控名單(持續監控,之後任何鏡頭拍到會自動告警)

監控名單清單

危險識別

M4(武器)/M5(暴力)/M6(火煙)目前能識別的類別,可以個別開關(例如某個類別誤報太多,先關掉它,不用整組模組停用),也可以調整每個模組的信心門檻/冷卻時間等參數。存檔後幾秒內自動生效,不用重啟服務。

訓練工作觸發

匯出資料集/訓練不用再上主機打指令——按下面按鈕會送一筆工作進佇列,host 上的 training_job_runner 服務每 15 秒輪詢一次,確認 GPU 沒有被正式偵測服務吃滿才會真的開始跑(這台主機曾因 GPU 負載疊加當機過,寧可讓工作排隊等待也不要搶跑)。同一時間全系統只能有一個工作,訓練通常要跑好一段時間,離開這頁不會中斷。
#模組類型狀態建立時間結束時間備註/錯誤

模型版本管理

訓練平台第三層(`training/` 服務,`docker compose run --rm training python train.py ...`)產出的 fine-tune 權重會自動列在這裡(`is_active=false`,需要人工評估 metrics 後手動啟用)。 啟用後不會立刻生效,M4/M6 只在服務啟動時查一次要用哪個版本,切換後要重新啟動對應服務(docker compose restart m4-weaponm6-fire)才會真的套用新模型。

M4 武器偵測(weapon)

建立時間訓練/驗證樣本數EpochsMetrics備註狀態

M6 火煙偵測(fire_smoke)

建立時間訓練/驗證樣本數EpochsMetrics備註狀態

語音求救關鍵詞(M21)

USB 陣列麥克風轉出的語音文字只要包含這裡任一個詞就會送 VLM 複核(判斷畫面是否真的有呼救者/嫌犯互動的跡象),複核通過才會觸發錄影跟通知。自己新增/刪除,不寫死在程式碼裡。
關鍵詞啟用

觸發錄影設定

武器/暴力行為/火煙偵測經 VLM 複核確認後,自動錄一段片段(事件發生前後都錄,含 M3 疊的框),存進 MinIO。存檔後幾秒內自動生效,不用重啟服務。

片段清單

鏡頭類型信心分數時間複核說明人工審核

上傳樓層平面圖

樓層名稱要跟「鏡頭清單」裡填的「樓層/位置」欄位文字完全一致,鏡頭才能對應到平面圖(例如都填「3樓」)。同一個樓層名稱重新上傳會覆蓋舊圖,鏡頭定位資料不受影響。
樓層名稱鏡頭數更新時間

鏡頭定位

選一個樓層,從下面清單點選要定位的鏡頭(會反白),再直接點擊平面圖上對應的位置即可儲存座標。

VPN 伺服器資訊

M13 邊緣裝置(Jetson)透過 WireGuard 連進來的中心端。新增裝置要在主機上跑 ops/wireguard-add-jetson-peer.sh(這裡不能、也不該直接改 host 的 VPN 設定)。

連線設定

超過這麼久沒有 WireGuard 交握(handshake)就判定為離線。keepalive 預設每 25 秒一次,門檻不要設得太接近。

裝置連線狀態

裝置VPN IP連線來源狀態上次交握公鑰

感測器型號設定

一種 Modbus RTU 感測器型號的暫存器讀取設定(D-002)。新增一種新型號只是填一筆設定,不用改程式碼。
名稱暫存器資料型別位元組序scale單位

實體感測器指派

把一種型號指派到某台邊緣裝置的某個序列埠/slave address。同一條 RS-485 匯流排(同一個序列埠)可以掛多顆不同 slave address 的感測器。
名稱裝置型號序列埠Slave輪詢間隔啟用門檻告警(2026-07-21 新增,例如分貝計超過門檻寄通知)

感測器讀數

時間感測器裝置數值

邊緣裝置清單

M13 遠端 Jetson Orin NX gateway(透過 WireGuard 連回本機)。目前尚無實體硬體連線時,狀態一律誠實回報「無法連線」,不會假裝連線成功——裝置實際插電、連上 VPN 後在這裡登記 VPN IP 即可開始管理。
名稱目前運算位置VPN IP:Port狀態上次連線啟用

新增邊緣裝置

操作紀錄

連線測試/重啟/更新/停用啟用/憑證變更的歷史紀錄,方便事後追查是誰在什麼時候對哪台裝置做了什麼操作。
裝置動作結果詳情時間

🚀 佈署新的邊緣裝置(Jetson)

這裡是「現有 Jetson 掛了要換新機」或「要加第 2、3…台」時的完整 SOP。這個頁面只負責把指令組好方便複製,網頁本身不會替你連線 或執行任何東西——實際安裝仍在中控主機/新裝置的終端機進行, 理由是這一步要動到 root 權限、SSH 金鑰、WireGuard 設定,刻意不 讓網頁後端擁有這些權限(風險太集中,一旦網頁那層被攻破,後果會 從「資料被改」升級成「主機跟新裝置都被拿下」)。

前置需求(無法自動化,一定要先做一次)

  • Jetson 已燒錄好 JetPack 6(L4T R36.4.4),可開機、先接乙太網路/區網(還不用先連 WireGuard)
  • 佈署帳號(預設 korgsam)已建立、有 sudo 權限,且中控主機能用 SSH 金鑰登入這台新機器
  • 知道這台 Jetson 目前的區網 IP(例如 192.168.1.50

步驟 1:中控主機產生 WireGuard peer + 註冊裝置 + 推送檔案

中控主機(這台伺服器)的終端機執行,需要 root(要改 /etc/wireguard)跟 core-api admin 密碼(指令執行時互動輸入,不會存進任何檔案)。

步驟 2:在新 Jetson 上執行 bootstrap

步驟 1 完成後會自動把設定跟原始碼 rsync 到目標機器,這裡執行的是收尾:依序裝好 WireGuard/mediamtx/edge-agent/whisper.cpp(M21 語音求救用)/edge-inference,並啟用對應的 systemd 服務讓它們開機自動啟動。整段約需 20-40 分鐘(edge-inference 那段要編譯 CUDA whisper.cpp + 下載模型,最久)。

步驟 3:驗證

  • bootstrap 腳本結尾會自己做健康檢查,5 個服務都要顯示 ✓:wg-quick@wg0 / mediamtx / ai-police-edge-agent / ai-police-whisper / ai-police-edge-inference
  • 回到「🖥️ 邊緣運算」頁確認新裝置狀態變成 online(等下一次心跳,通常幾秒內)
  • 在「邊緣運算」頁展開該裝置的「鏡頭」面板,登記實際接的鏡頭 RTSP URL、勾選要開的偵測模組(人流/武器/名單/槍聲/爆炸聲/車禍聲/語音求救)

疑難排解

SSH 進中控主機或新裝置後可以用這些指令查狀況:
ssh <目標SSH位址> journalctl -u ai-police-edge-inference.service -f --no-pager
ssh <目標SSH位址> systemctl status ai-police-edge-agent ai-police-edge-inference ai-police-whisper mediamtx wg-quick@wg0 --no-pager
完整原始碼在中控主機 /srv/projects/ai_police/ops/provision-edge-device.sh(中控端協調)、jetson-bootstrap.sh(Jetson 端安裝,可重複執行)、templates/*.service(systemd unit 樣板)。這組腳本目前只在既有的 jetson-orin-01 上反推驗證過個別步驟,還沒有對一台全新機器跑過完整流程,第一次用時建議全程盯著、隨時能中斷排錯。

🎯 即時聲音雷達

D-003 擴充:USB 陣列麥克風的即時收音狀態。麥克風是線性陣列(一字排開),先天只能解析前方半圓(±90°),無法分辨正前方/正後方,相鄰間距是使用者現場量測的估計值(約 2 公分),方位角只能抓大致區間、不是精確角度。每 1 秒輪詢一次,不是即時串流。
尚無資料

🗺️ 地圖投影

裝置沒有 GPS,位置/朝向是人工在「邊緣運算」頁面設定的參考值(📍 按鈕)。紅色扇形是假設方向範圍,不是實測位置或距離 ——這副陣列本來就沒有測距能力,扇形只是把方位角疊到地圖上方便 判斷大概往哪個街道方向找。

🎙️ 異常聲音錄音

槍聲/爆炸聲/車禍碰撞聲經 VLM 複核確認後,自動錄下觸發前後的音訊(預設前 3 秒+後 5 秒)。跟「最近事件」頁的對應事件用時間/類型/裝置對照即可,資料庫沒有強制關聯。
時間類型裝置信心分數方位角播放

🕰️ 聲音事件時間軸

槍聲/爆炸聲/車禍碰撞聲三種音訊事件的歷史查詢,依時間/類型/鏡頭篩選。「視覺確認」欄是同一支鏡頭前後 10 秒內有沒有 M4/M5/M6 等視覺類危險事件也命中——兩者都命中可信度較高,但目前只做「音訊事件回頭找視覺事件」單方向比對,視覺事件比音訊晚到的情況不會補標記。「播放」是自動比對同裝置+同類型+前後 30 秒內最接近的錄音,資料庫沒有強制關聯,找不到是正常情況(不是每次事件都一定有錄到音)。
時間類型鏡頭信心分數方位角視覺確認優先級播放

本地模型

跑在這台主機上的模型服務(例如 llm-gateway)。M5(暴力二次複核)/M7(VLM複核) 會呼叫「使用中」那一筆。
名稱連線位址模型名稱狀態

新增本地模型

雲端模型

OpenAI 相容格式的雲端 API(OpenAI 本身、或其他相容服務)。M5(暴力二次複核)/M7(VLM複核) 會呼叫「使用中」那一筆——不管切成本地還是雲端,同一時間系統只有一筆是使用中的。
名稱連線位址模型名稱狀態

新增雲端模型

變更我的密碼

任何角色都可以在這裡改自己的密碼,需要輸入目前密碼確認身份。

帳號清單

個別操作者帳號(2026-07-16 新增登入系統)。「管理員」可以管理帳號/建立其他人的帳號/重設別人的密碼;「操作員」可以使用所有監控功能,但這個清單跟下面「新增帳號」只有管理員看得到(會顯示「需要管理員權限」)。停用一個帳號不會刪除歷史稽核紀錄,只是讓那組帳密無法再登入(正在登入中的 session 要等最長 8 小時後才會真的失效)。「管理員」角色只要填了 Email,登入時會強制多一道 Email 驗證碼(2026-07-21 新增,見下方「Email OTP」欄),沒填就維持原本純帳密登入。
帳號角色狀態Email OTP建立時間最後登入

新增帳號

⚙️ 系統設定

登入頁面標題、登入後右上角標題、系統 logo——只有管理員能修改,變更後所有使用者(含登入頁面,未登入也看得到)立即生效,不用重新部署。留空欄位儲存=還原成預設文字。

系統 Logo

支援 PNG/JPEG/SVG/WebP,大小上限 2MB。沒有自訂 logo 時,標題前面顯示預設的 🚓 emoji。
🚓
🗣️ 自然語言查詢