一、引言
在视频感知里,“检测”告诉我们这一帧有什么,“跟踪”回答这些对象是谁、从哪来、到哪去。
SORT 以极简工程结构(卡尔曼滤波 + IoU + 匈牙利 + 生命周期)实现了实时且易落地的多目标跟踪;但仅凭 IoU 的几何重叠,对遮挡、交汇、相似外观常会发生 ID 切换(ID switch)。
DeepSORT 正是为解决这一痛点而生:在 SORT 的骨架上,加入外观特征(ReID embedding)与级联匹配(Cascade Matching),并配合马氏距离的运动门控,在保持较高实时性的前提下显著提高 ID 稳定性。
二、方法总览:DeepSORT 做了哪些增强?
一句话:
DeepSORT = SORT(KF + IoU + 匈牙利 + 生命周期)
- 外观 ReID(appearance embedding)
- 级联匹配(先匹配“刚更新”的轨迹)
- 运动门控(Mahalanobis 距离 χ² 检验)
流程鸟瞰(逐帧):
1、检测:从检测器(如 YOLO)得到当帧检测框(可按类别/ROI 过滤)。
2、提特征:为每个检测裁图,送入 ReID 模型,得到 L2 归一化的外观向量 f∈Rd。
3、预测:对每条存活轨迹做 卡尔曼滤波(KF)Predict,获得预测位置/尺度及其协方差。
4、级联匹配:按 time_since_update 从小到大(0 → 1 → 2 → …)分组轨迹;每组中:
-
运动门控(马氏距离):先剔除运动上不合理的候选;
-
代价矩阵:以外观距离为主、IoU 为辅构建代价;
-
匈牙利匹配:在“可行候选”上求全局最优;
-
消耗掉的检测从候选池移除,进入下一组匹配。
5、更新/新建/删除:匹配到的轨迹做 KF Update 并更新外观库;未匹配轨迹仅预测计龄;未匹配检测新建轨迹;超龄轨迹删除;达到 min_hits 的轨迹转 confirmed。
6、输出:仅输出 confirmed 轨迹作为当帧跟踪结果(用于计数/统计/控制)。
三、数学要点:运动 + 外观的“双重约束”
3.1 运动模型与量测(与 SORT 一致)
3.2 运动门控:马氏距离 χ² 检验
3.3 外观度量:最近邻的余弦距离
3.4 组合代价(appearance 主导 + IoU 兜底)
3.5 级联匹配(Cascade)
将轨迹按 time_since_update 分桶(0 → 1 → 2 …),先匹配“最新鲜”的轨迹,再处理“更久未命中”的。这样能显著减少老轨迹在复杂场景中“抢走”新目标,降低 ID 切换。
四、与 SORT 的系统对比
维度 | SORT | DeepSORT |
---|---|---|
关联信号 | 几何重叠 IoU | 外观(ReID embedding)+ IoU |
运动一致性 | 一般仅 IoU 门限 | 马氏距离门控(χ²) |
匹配策略 | 一次性匈牙利 | 级联匹配(按最近更新时间分组) |
轨迹外观记忆 | 无 | 有(gallery + nn_budget) |
遮挡/交汇 ID 稳定 | 中等 | 高 |
复杂度与开销 | 低(极快) | 中(需 ReID 推理) |
典型适用 | 目标分散、遮挡少、资源紧 | 遮挡/交汇多、相似外观多、对 ID 稳定要求高 |
取舍:DeepSORT 用外观与级联策略换取更稳的 ID,代价是多一次特征推理与略高的工程复杂度。在真实项目里,它往往是“既实用又稳健”的默认选择。
五、工作流程(逐帧)——可直接照此实现
1、读入检测:[x1,y1,x2,y2,score,cls],按 ROI/类别过滤。
2、提外观特征:裁剪检测框 → ReID 模型 → fd(L2 Norm)。
3、预测所有轨迹:KF Predict,得到预测框、预测量测与创新协方差 S。
4、级联匹配:按 time_since_update 排序轨迹桶:
-
马氏门控: 𝑑2≤𝜒thr2的候选才保留;IoU < 阈值的剔除;
-
代价矩阵:𝛼⋅app_dist+(1−𝛼)⋅(1−IoU)
-
匈牙利分配:得到匹配/未匹配;
-
更新:匹配上的轨迹做 KF Update、写入新外观特征(维护 gallery)。
5、新建:对仍未被消费的检测,新建轨迹(初始化 KF + gallery)。
6、删除/确认:time_since_update > max_age 删;hits ≥ min_hits 转 confirmed。
7、输出:仅输出 confirmed 的轨迹(track_id + box + cls/score)。
六、数值例子:交汇时如何“稳住 ID”
场景:两辆外观很像的车在路口交汇。上一帧我们已有两条轨迹 T1、T2;当前帧检测到 D1、D2,并提取外观向量 𝑓𝐷1,𝑓𝐷2。
七、代码参考
# 假设 dets: List[Det],每个 Det 含 box, score, cls, crop()
# tracks: List[Track],每个 Track 含 kf, id, status, gallery, time_since_update, hits, age
alpha = 0.7 # 外观权重
chi2_thr = 9.49 # 4 维量测的 95% 阈值
appearance_thr = 0.35 # 外观门限(越小越严格)
iou_min = 0.2 # IoU 最低门限
min_hits, max_age = 3, 30
# 1) 提外观特征(仅 NMS 后保留的目标)
for d in dets:
d.feat = l2norm(reid(d.crop()))
# 2) KF 预测
for t in tracks:
t.kf.predict()
t.pred_box = state_to_box(t.kf.x)
# 3) 级联匹配:按 time_since_update 升序分桶
for group in bucketize_by_tsu(tracks):
cand_dets = dets_remaining
# 3.1 运动门控 + IoU 最低门限
mask = []
for t in group:
for d in cand_dets:
if not gate_mahal(t.kf, d, chi2_thr): # 马氏门控
mask.append((t.id, d.id, False)); continue
if iou(t.pred_box, d.box) < iou_min:
mask.append((t.id, d.id, False)); continue
mask.append((t.id, d.id, True))
# 3.2 代价矩阵(appearance 主导 + IoU 兜底)
C = build_cost_matrix(group, cand_dets, mask, alpha, appearance_thr)
# 3.3 匈牙利匹配
matches, u_grp, u_det = hungarian_with_mask(C, group, cand_dets)
# 3.4 更新匹配的轨迹(KF update + 更新 gallery)
for (ti, dj) in matches:
z = box_to_meas(cand_dets[dj].box)
group[ti].kf.update(z)
group[ti].gallery.push(cand_dets[dj].feat) # 维护 nn_budget
group[ti].time_since_update = 0
group[ti].hits += 1
group[ti].age += 1
if group[ti].hits >= min_hits:
group[ti].status = 'confirmed'
# 3.5 剩余未匹配的检测留给下一组
dets_remaining = [cand_dets[j] for j in u_det]
# 4) 为仍未被消费的检测新建轨迹
for d in dets_remaining:
tracks.append(new_track_from_det(d))
# 5) 删除超龄轨迹
tracks = [t for t in tracks if t.time_since_update <= max_age]
# 6) 输出 confirmed 轨迹
outputs = [(t.id, state_to_box(t.kf.x), t.cls) for t in tracks if t.status=='confirmed']
八、实战调参与工程建议
-
外观阈值 appearance_thr(0.2–0.35):
越小越严格(漏配↑,误配↓)。遮挡/交汇多时可略放宽并提高 max_age。 -
权重 α(0.6–0.8):
外观主导,IoU 兜底。外观质量差时适当降低 𝛼。 -
马氏门控 chi2_thr(9.49/11.35):
第一层硬筛,强降“离谱跳跃”的误配;低 FPS 或运动剧烈可略放宽。 -
min_hits(2–4):
抑制短命假轨迹;噪声多时增大。 -
max_age(与 FPS/遮挡相关):
30 FPS 可先取 30(≈1s 隐身);低 FPS/遮挡重可 45–60。 -
nn_budget(50–200):
Gallery 长度;过大会累积噪声,过小记忆弱。可优先保留“大框/高置信/清晰帧”的特征。 -
按类分轨:car/bus/truck/person 各跑一套 DeepSORT,杜绝跨类误配。
-
性能优化:仅对 NMS 后目标提特征;ReID 用 FP16/轻量 backbone;必要时异步管线。
-
移动相机:结合 相机运动补偿(CMC) 或考虑 OC-SORT / BoT-SORT。
-
多传感器融合:若有毫米波/激光雷达,把距离/速度加入门控或代价项,ID 稳定性可再上一个台阶。
九、SORT 还是 DeepSORT?
1、先上手:如果你需要最快速的原型与基线,且遮挡/交汇不严重,选 SORT。
2、追稳定:若你的场景遮挡多、交汇频、外观相似(如行人、密集车流),选 DeepSORT,它的 外观 + 级联 + 门控 组合会带来明显收益。
3、更进一步:
-
OC-SORT:强调几何/速度一致性,在移动相机或光流明显时强势;
-
BoT/StrongSORT:更强外观与补偿;
-
ByteTrack:两阶段(高/低置信)关联,拥挤场景召回高,可与外观结合。
十、总结
DeepSORT 的本质:在 SORT 的简单高效骨架上,用外观特征与级联匹配、运动门控把“时空上的同一个目标”稳稳地串起来。
它不追求花哨,而是在工程可控的前提下,把 ID 稳定性 拉升到一个更可靠的水平。理解了它的每一环(KF、马氏门控、外观度量、级联策略、生命周期),你就能根据场景做出有依据的取舍与调参 —— 在实时性与稳定性之间找到最顺手的平衡点。
如果你已经有了检测器(如 YOLO),按本文流程接入 DeepSORT,并用上述参数区间微调,很快就能得到一个可用、可解释、可维护的多目标跟踪系统 。