OC-SORT 详解
OC-SORT: Observation-Centric SORT
论文: Observation-Centric SORT: Rethinking SORT for Robust Multi-Object Tracking (CVPR 2023)
作者: Jinkun Cao, Xinshuo Weng, Rawal Khirodkar, Kris Kitani, Jiangmiao Pang (CMU / 商汤)
代码: noahcao/OC_SORT
一句话总结:OC-SORT 把 SORT 从”以估计为中心”改为”以观测为中心”–当轨迹从遮挡中恢复时,用观测历史修正卡尔曼参数(ORU);在关联代价中加入观测方向一致性(OCM);用最后一次观测做二次恢复匹配(OCR)。 无需外观特征,即超越 DeepSORT。
一、背景:SORT 的三个局限
OC-SORT 的出发点是分析 SORT 的三个根本局限,逐一解决。
1.1 局限一:对状态噪声敏感
SORT 假设匀速运动,用卡尔曼滤波估计速度。但在高帧率视频中,连续帧间位移很小,噪声与实际位移量级相当,导致速度估计方差大。
1 | 帧率 30fps: 每帧位移 ~10px, 噪声 ~2px -> 信噪比 5:1, 还行 |
1.2 局限二:遮挡期间误差累积(O(t²))
当物体被遮挡(检测器漏检),轨迹没有新观测,KF 只做预测不做更新。预测只用上一次的速度估计,如果速度估计有偏差,误差会随时间平方增长:
$$
\text{误差} \sim O(\Delta t^2)
$$
1 | 帧 10: 物体正常跟踪,速度估计 v=5px/帧 |
这就是 SORT “丢失后不能恢复”的根因:不是故意不恢复,而是 KF 预测偏离太远,IoU=0,无法匹配。
1.3 局限三:以估计为中心(Estimation-Centric)
SORT 严重依赖 KF 的状态估计(预测位置),把检测器的观测只当作”辅助修正”。但现代检测器(YOLOv8/RT-DETR)已经非常可靠,应该更信任观测。
1 | SORT 的信任链: KF 预测 (主导) > 检测观测 (辅助) |
二、核心思想:从”以估计为中心”到”以观测为中心”
OC-SORT 的核心哲学转变:
| SORT(以估计为中心) | OC-SORT(以观测为中心) | |
|---|---|---|
| 信任谁 | KF 状态估计(预测位置) | 检测器观测(实际位置) |
| 恢复丢失轨迹 | 用 KF 预测位置匹配(已偏离) | 用最后一次观测位置匹配 |
| 速度方向 | 用 KF 估计的速度 | 用观测历史计算的方向 |
| 遮挡后 KF 参数 | 信任累积了误差的参数 | 用虚拟轨迹重新更新参数 |
关键洞察:现代检测器足够可靠,观测比 KF 预测更可信。OC-SORT 让观测”反客为主”。
三、三大创新
3.1 ORU:观测为中心的再更新(Observation-centric Re-Update)⭐
解决”遮挡后 KF 参数偏离”问题。
问题:轨迹丢失期间 KF 只预测不更新,误差累积。即使后来重新匹配成功,KF 参数(状态 + 协方差)已经偏离正确值,可能很快再次丢失。
解法:当丢失轨迹重新匹配成功时,回溯丢失期间,用虚拟轨迹重新更新 KF 参数:
1 | 时间线: |
公式(沿虚拟轨迹的再更新):
$$
\hat{\mathbf{x}}{t|t} = \hat{\mathbf{x}}{t|t-1} + \mathbf{K}_t (\tilde{\mathbf{z}}_t - \mathbf{H}t \hat{\mathbf{x}}{t|t-1})
$$
- $\tilde{\mathbf{z}}_t$:虚拟轨迹上的”伪观测”
- $\mathbf{K}_t$:卡尔曼增益
- 效果:KF 参数被”拉回”到与真实运动一致的状态
直觉:KF 在丢失期间”走偏了”,ORU 相当于”假装这段时间有观测,重新校正一遍”。
源码:ORU 在
KalmanFilterNew类(kalmanfilter.py)中实现。当 OCR 恢复成功后调用tracker.update(),KalmanFilterNew内部会检查是否是从丢失状态恢复,如果是则沿虚拟轨迹($z_{t_1}$ 到 $z_{t_2}$ 的线性插值)重新执行 predict-update 循环,修正累积误差。
3.2 OCM:观测为中心的动量(Observation-Centric Momentum)⭐
解决”只用 IoU 匹配不够鲁棒”问题。
问题:SORT 的关联代价只用 IoU,当物体运动较快或预测有偏差时,IoU 可能不够高导致漏匹配。
解法:在代价矩阵中加入运动方向一致性项:
$$
C(\hat{X}, Z) = \underbrace{C_{\text{IoU}}(\hat{X}, Z)}{\text{SORT 原有}} + \lambda \underbrace{C_v(\hat{X}, Z, V)}{\text{OC-SORT 新增}}
$$
- $C_{\text{IoU}}$:负的 IoU(IoU 越大代价越小)
- $C_v$:方向一致性代价
- $\lambda$:权重因子
方向计算(用观测而非估计):
1 | θ_track = track 的历史运动方向 |
为什么用观测而非 KF 估计算方向? KF 估计的速度有误差累积,而观测是检测器的直接输出,噪声更可控。论文证明:增大两次观测的时间差 Δt 可以降低方向噪声(噪声与 Δt 负相关),但 Δt 太大线性假设会失效,需权衡。
直觉:如果一个轨迹一直在向右走(历史方向),新检测也在右边,那方向一致、代价低、应该匹配;如果新检测在左边(方向相反),代价高、可能不是同一个物体。
源码(association.py: associate()):
1 | def associate(detections, trackers, iou_threshold, velocities, previous_obs, vdc_weight): |
关键:
linear_assignment(-(iou_matrix + angle_diff_cost))– 代价 = IoU + 方向一致性,方向越一致代价越小。vdc_weight(默认 0.2)控制方向项的权重。
速度方向的计算(用观测,不用 KF 估计):
1 | def speed_direction(bbox1, bbox2): |
在
KalmanBoxTracker.update()中,每次匹配成功时用delta_t步前的观测与当前观测计算速度方向:self.velocity = speed_direction(previous_box, bbox)。delta_t默认 3(用 3 帧前的观测算方向,降低噪声)。
3.3 OCR:观测为中心的恢复(Observation-Centric Recovery)⭐
解决”丢失轨迹的 KF 预测偏离太远导致无法恢复”问题。
问题:轨迹丢失后,KF 预测位置已偏离真实位置很远,与重新出现的检测框 IoU=0,正常关联阶段无法匹配。
解法:在正常关联之后,用轨迹的最后一次观测(而非 KF 预测)与未匹配检测做二次关联:
1 | 正常关联阶段(同 SORT): |
1 | flowchart LR |
直觉:KF 预测说”物体应该在 100px 外”,但物体其实没动(停在原地被遮挡)。用最后一次观测位置(”物体最后在这”)去匹配,比用偏离的 KF 预测靠谱得多。
源码(ocsort.py: OCSort.update() 中的 OCR 二次恢复):
1 | # 正常关联后,如果仍有未匹配检测和未匹配轨迹 |
关键:
left_trks = last_boxes[unmatched_trks]– 这里用的是last_observation(最后一次真实检测),而非 KF 预测框。这是 OCR 与 SORT 的核心区别。
last_observation 的维护(KalmanBoxTracker):
1 | class KalmanBoxTracker: |
每个轨迹独立维护
last_observation(最后一次匹配到的检测框)和observations字典(所有历史观测)。OCR 用last_observation做二次匹配,OCM 用observations中的delta_t步前观测算速度方向。
四、整体流程
1 | flowchart TD |
与 SORT 相比,OC-SORT 多了两个阶段:OCM(在关联代价中加方向项)和 OCR + ORU(二次恢复 + 恢复后修正 KF)。
五、与 SORT 的对比
| 维度 | SORT | OC-SORT |
|---|---|---|
| 关联代价 | 仅 IoU | IoU + 方向一致性(OCM) |
| 丢失恢复 | 用 KF 预测匹配(易偏离) | 用最后一次观测二次匹配(OCR) |
| 恢复后 KF | 直接用(参数已偏离) | ORU 重新更新(沿虚拟轨迹修正) |
| 速度方向来源 | KF 估计(有误差累积) | 观测历史(噪声更可控) |
| 哲学 | 以估计为中心 | 以观测为中心 |
| 外观特征 | 无 | 无(仍纯运动模型) |
| IDSW | 高 | 大幅降低 |
| 遮挡恢复 | 差 | 强 |
六、性能
| 模型 | 数据集 | MOTA | HOTA | IDF1 | IDSW↓ |
|---|---|---|---|---|---|
| SORT | MOT17 | 57.5 | 53.3 | 59.7 | 4872 |
| DeepSORT | MOT17 | 58.2 | 56.9 | 62.6 | 1296 |
| ByteTrack | MOT17 | 56.4 | 58.3 | 63.3 | 689 |
| OC-SORT | MOT17 | 59.1 | 63.2 | 67.3 | 659 |
OC-SORT 在 MOT17 上 HOTA 63.2,无需外观特征即超越 DeepSORT 和 ByteTrack。在 DanceTrack(非线性运动)上优势更明显。
七、改进路线总结
1 | SORT (2016) |
八、总结
OC-SORT 的核心贡献是把 SORT 从”以估计为中心”改为”以观测为中心”,三个创新环环相扣:
- OCM:关联时不只看 IoU,还看运动方向是否一致(用观测算方向,不用 KF 估计);
- OCR:丢失轨迹恢复时,用最后一次观测位置匹配(不用偏离的 KF 预测);
- ORU:恢复成功后,沿虚拟轨迹重新更新 KF 参数(修正遮挡期间的累积误差)。
关键洞察:现代检测器足够可靠,观测比 KF 预测更可信。 OC-SORT 不加任何外观特征,仅靠”更聪明地使用观测”就超越了 DeepSORT 和 ByteTrack。
相关链接
- 📝 [[20.notes/感知算法/目标跟踪/SORT/SORT 详解|SORT 详解]] - OC-SORT 的基础,理解 SORT 的局限才能理解 OC-SORT 的改进
- 📋 论文原文: arxiv.org/abs/2203.14360
- 📋 官方代码: noahcao/OC_SORT
- 📋 [[10.clippings/感知算法/目标跟踪/OC-SORT/22.03 OC-SORT]]
- 📋 [[10.clippings/感知算法/目标跟踪/OC-SORT/OC- SORT]]
- 📋 [[10.clippings/感知算法/目标跟踪/OC-SORT/OC-SORT文章梳理(略读)]]
- 📋 [[10.clippings/感知算法/目标跟踪/OC-SORT/以观察为中心的SORT:为鲁棒多目标跟踪重新思考SORT]]
- 📋 [[10.clippings/感知算法/目标跟踪/OC-SORT/如何使用OC-SORT:从安装到实战的完整多目标跟踪指南]]
- 📦 源码参考:
deeplearning/tracking/OC_SORT/trackers/ocsort_tracker/(ocsort.py / association.py / kalmanfilter.py)