釋出報告 · 跌倒偵測

fall_sq_v20260805 — 模型、用法與逐鏡頭門檻

2026-08-05 · session:模型訓練 · 範圍:ISMS「PM 視角:🧠 訓練 / 驗證 (172 隻)」內跌倒 21 支

18 / 21
鏡頭達到可用標準
0.9960
整體 AP(考試用 913 倒地 / 4,307 沒倒地)
95.2%
建議設定的抓到率
(4,307 個沒倒地的人只誤判 3 個)

一、模型

取得與規格

https://pub-478929a98a5c440cb22c2241c0bde314.r2.dev/fall_sq_v20260805/best.pt
SHA 檔案大小 17,011,733 bytes
Backbone
mobilenetv3_large_100.ra_in1k
參數量
4.20 M
輸出
單一 logit(fall)· 過 sigmoid
輸入尺寸
384 × 384(正方形)
前段偵測器
person_yolo26m_v20260715
偵測推論尺寸
1280
這是「逐人」判斷,不是「整張圖」判斷。 流程是先偵測畫面裡的每一個人,把每個人裁切出來,再逐一判斷這個人有沒有倒下。 所以一張畫面會產生 N 個判斷結果(N = 畫面裡的人數),門檻是套在每一個人身上。

二、用法

完整推論流程

步驟

  1. 人員偵測 —— 用 person_yolo26m_v20260715imgsz=1280conf=0.25
    1280 是固定值,不可改成偵測器的訓練尺寸 —— 場域遠景的人很小,用 640 會漏。
  2. 裁切 —— 每個人的框四邊各外擴 15%,超出畫面就截斷。
  3. 縮放 —— 直接 resize 成 384 × 384不要保持長寬比、不要補邊
  4. 正規化 —— ImageNet 標準值。
  5. 推論 —— 過模型取單一 logit,再過 sigmoid 得到 0–1 的分數。
  6. 判定 —— 分數 ≥ 該鏡頭的門檻即判為「倒地」。門檻見第三節,每支鏡頭不同

參考實作

import torch, timm
import torchvision.transforms as T
from PIL import Image
from ultralytics import YOLO

det = YOLO("person_yolo26m_v20260715.pt")
ck  = torch.load("best.pt", map_location="cpu", weights_only=False)
IH, IW = ck["img_size"]                       # (384, 384)

class FallNet(torch.nn.Module):
    def __init__(s):
        super().__init__()
        s.backbone = timm.create_model(ck["backbone_name"], pretrained=False,
                                       num_classes=0, global_pool="avg")
        s.dropout  = torch.nn.Dropout(0.3)
        s.cls      = torch.nn.Linear(ck["feat_dim"], 1)
    def forward(s, x):
        return s.cls(s.dropout(s.backbone(x)))

m = FallNet(); m.load_state_dict(ck["model_state"]); m.eval().cuda()

tf = T.Compose([
    T.Resize((IH, IW)),                       # 不保持長寬比
    T.ToTensor(),
    T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
])

PAD = 0.15
def detect_falls(img_path, thr):
    im = Image.open(img_path).convert("RGB"); W, H = im.size
    r  = det.predict(img_path, imgsz=1280, conf=0.25, verbose=False)[0]
    crops, boxes = [], []
    for b in (r.boxes.xyxy.cpu().numpy() if r.boxes is not None else []):
        x1, y1, x2, y2 = b[:4]; bw, bh = x2 - x1, y2 - y1
        if bw < 8 or bh < 8:                  # 太小的框直接丟掉
            continue
        crops.append(tf(im.crop((
            int(max(0, x1 - bw * PAD)), int(max(0, y1 - bh * PAD)),
            int(min(W, x2 + bw * PAD)), int(min(H, y2 + bh * PAD))))))
        boxes.append((x1, y1, x2, y2))
    if not crops:
        return []
    with torch.no_grad():
        p = torch.sigmoid(m(torch.stack(crops).cuda())).float().cpu().numpy()[:, 0]
    return [(bx, float(s)) for bx, s in zip(boxes, p) if s >= thr]
三個最容易做錯的地方
  1. 裁切成正方形不能保持長寬比 —— 躺著的人在畫面上是橫向扁平的, 若沿用站姿的直立長方形或補邊保持比例,等於把人上下拉長 2–3 倍。 實測:改成正方形後 AP 從 0.385 提升到 0.736、誤報降 62%。這是這個模型最關鍵的一個設定。
  2. 偵測器的 imgsz 固定 1280,不要自動讀偵測器的訓練值。
  3. 門檻要逐鏡頭設,套單一全域值會在某些鏡頭漏報或吵。

三、門檻

三種設定,依現場需求選一種

同一個模型,門檻不同會得到完全不同的行為。三種設定都附「抓到率 / 誤報率」, 數字是在該鏡頭的考試用資料上實測的,不是估的。

設定 A · 不漏報優先

0.08
抓到 99.0%(漏 9 人)
誤報 2.72%(117 次)
適合:寧可多吵幾次也不能漏,例如夜間無人時段

設定 B · 不吵優先

0.70
抓到 93.1%(漏 63 人)
誤報 0.05%(2 次)
適合:人力有限、誤報會造成疲乏的場域

建議設定 · 兩者兼顧

0.61
抓到 95.2%(漏 44 人)
誤報 0.07%(3 次)
做法:先確保抓到 95% 以上,在符合的門檻中取誤報最低

上面是全體的數字,實際請用下一節的逐鏡頭門檻。 每支鏡頭的視角、人流、光線都不同,統一套一個值會顯著變差。

四、逐鏡頭

18 支達到可用標準

判定標準:建議設定下抓到率 ≥ 95% 且誤報率 ≤ 3%, 且考試用樣本雙邊足夠(倒地 ≥ 10、沒倒地 ≥ 20)。

鏡頭考試用
倒地
考試用
沒倒地
AP設定 A · 不漏報優先設定 B · 不吵優先建議設定
門檻抓到 / 誤報門檻抓到 / 誤報門檻抓到 / 誤報
新東陽
ch10
411721.0000.35100% / 0.0%漏 0・誤 00.16100% / 0.0%漏 0・誤 00.6495% / 0.0%漏 2・誤 0
新東陽
ch20
1291211.0000.65100% / 0.0%漏 0・誤 00.18100% / 0.0%漏 0・誤 00.7795% / 0.0%漏 6・誤 0
新東陽
ch22
35631.0000.22100% / 0.0%漏 0・誤 00.22100% / 0.0%漏 0・誤 00.22100% / 0.0%漏 0・誤 0
新東陽
ch23
33361.0000.85100% / 0.0%漏 0・誤 00.56100% / 0.0%漏 0・誤 00.8897% / 0.0%漏 1・誤 0
新東陽
ch24
25481.0000.28100% / 0.0%漏 0・誤 00.07100% / 0.0%漏 0・誤 00.4596% / 0.0%漏 1・誤 0
新東陽
ch6
21551.0000.67100% / 0.0%漏 0・誤 00.09100% / 0.0%漏 0・誤 00.7195% / 0.0%漏 1・誤 0
新東陽
ch8
411,6071.0000.57100% / 0.0%漏 0・誤 00.21100% / 0.0%漏 0・誤 00.8995% / 0.0%漏 2・誤 0
興農
151-11
472071.0000.73100% / 0.0%漏 0・誤 00.22100% / 0.0%漏 0・誤 00.7598% / 0.0%漏 1・誤 0
興農
151-14
442081.0000.48100% / 0.0%漏 0・誤 00.17100% / 0.0%漏 0・誤 00.9395% / 0.0%漏 2・誤 0
興農
152-1
431681.0000.76100% / 0.0%漏 0・誤 00.09100% / 0.0%漏 0・誤 00.7895% / 0.0%漏 2・誤 0
興農
152-14
477631.0000.65100% / 0.0%漏 0・誤 00.55100% / 0.0%漏 0・誤 00.7896% / 0.0%漏 2・誤 0
興農
152-6
411891.0000.61100% / 0.0%漏 0・誤 00.43100% / 0.0%漏 0・誤 00.9595% / 0.0%漏 2・誤 0
興農
155-1
48730.9960.4796% / 0.0%漏 2・誤 00.2396% / 0.0%漏 2・誤 00.4796% / 0.0%漏 2・誤 0
興農
155-5
47840.9940.58100% / 1.2%漏 0・誤 10.17100% / 1.2%漏 0・誤 10.8196% / 1.2%漏 2・誤 1
興農
155-7
513541.0000.53100% / 0.0%漏 0・誤 00.38100% / 0.0%漏 0・誤 00.8496% / 0.0%漏 2・誤 0
愛烙達
頻道16-3樓走道+貨梯
21500.9940.9595% / 0.0%漏 1・誤 00.7095% / 0.0%漏 1・誤 00.9595% / 0.0%漏 1・誤 0
天銳國際
測試1
44280.9970.2498% / 0.0%漏 1・誤 00.2098% / 0.0%漏 1・誤 00.2795% / 0.0%漏 2・誤 0
天銳國際
測試2
32341.0000.60100% / 0.0%漏 0・誤 00.11100% / 0.0%漏 0・誤 00.6997% / 0.0%漏 1・誤 0

未達標 3 支

鏡頭考試用
倒地
考試用
沒倒地
AP設定 A · 不漏報優先設定 B · 不吵優先建議設定
門檻抓到 / 誤報門檻抓到 / 誤報門檻抓到 / 誤報
新東陽
ch12
考試用樣本太少(沒倒地僅 16 人),算出的誤報率不可信 —— 需補測試資料
52160.9880.9581% / 0.0%漏 10・誤 00.1492% / 6.2%漏 4・誤 10.4390% / 6.2%漏 5・誤 1
新東陽
ch21
考試用樣本太少(沒倒地僅 14 人),算出的誤報率不可信 —— 需補測試資料
23140.9970.5596% / 0.0%漏 1・誤 00.1896% / 0.0%漏 1・誤 00.5596% / 0.0%漏 1・誤 0
愛烙達
頻道15-3樓後方走道
考試用樣本太少(沒倒地僅 17 人),算出的誤報率不可信 —— 需補測試資料
48170.9910.4992% / 0.0%漏 4・誤 00.2292% / 0.0%漏 4・誤 00.0596% / 23.5%漏 2・誤 4
未達標不代表模型在這些鏡頭不能用。 三支裡有兩支是考試用資料太少(沒倒地只有十幾個人), 任何一個判錯都會讓誤報率大幅跳動,數字本身不可信 —— 要補測試資料才能給結論。

五、限制

已知會影響效果的條件

條件影響怎麼確認
畫面解析度 畫面中一個人若小於約 40 × 80 像素,裁切後放大到 384×384 會嚴重失真,判斷力大幅下降 實測:某鏡頭串流只有 480×240,人只有 17×41 像素,308 個人全部判成沒倒地。 換成同一支的高畫質畫面(人約 89×167)後 AP 達 1.000
人員偵測是前提 偵測不到人就不會有判斷。遠景、重疊、遮擋都會影響 先確認偵測器在該鏡頭的召回率,再談分類準度
蹲姿與彎腰 是最容易被誤判成倒地的姿勢 模型在這帶會給 0.15–0.70 的中間分數。若場域常有蹲姿作業,建議用設定 B

六、這一版怎麼來的

訓練與驗證

訓練資料
cvat2 #12 · 約 13,000 個人
batch / epochs
96 / 25
patience
16(ep06 最佳)
lr / wd
3e-4 / 0.01
aug / mixup
strong / 0.2
考試用資料
913 倒地 / 4,307 沒倒地
這一版是三次改版對照後選出來的。 2026-08-05 另外訓了三個版本(補測試集、補兩支新鏡頭的真實資料、補生成的倒地樣本), 整體 AP 分別是 0.9927 / 0.9904 / 0.9903,都沒有超過這一版的 0.9960。 依「同一測試集對照、沒退步才換版」的原則,維持這一版。

考試用資料這一輪從 2,396 筆擴充到 5,220 筆, 原本三支完全無法評估的鏡頭補到只剩測試樣本不足的問題, 21 支鏡頭現在全部都有實測數字

產出:模型訓練 session · 2026-08-05 · 5090-2 · runs/fallcls_fall_sq_pat16