多目标跟踪(MOT)FAQ 深度解读:computervision-recipes 中 FairMOT 的标注、训练、推理与评估全指南
多目标跟踪(MOT)FAQ 深度解读:computervision-recipes 中 FairMOT 的标注、训练、推理与评估全指南
多目标跟踪(Multi-Object Tracking, MOT)需要在连续视频帧中为目标框持续分配唯一 ID,比单纯的目标检测更复杂。本文以 scenarios/tracking/FAQ.md 为骨架,围绕仓库集成的 FairMOT 跟踪器,系统讲解数据标注格式、训练损失构成、推理参数调优、MOT Challenge 评估指标,以及 tracking-by-detection 领域的常见技术方案。读者读完本文将掌握:如何为 MOT 模型准备训练与评估数据、理解 FairMOT 各损失项与推理参数的作用、读懂 MOTA/IDF1/ID-switch 等指标,并对照仓库源码理解底层实现。
一、文档定位与背景
scenarios/tracking/FAQ.md 是仓库多目标跟踪模块的问答总纲,覆盖数据、训练与推理、评估、SoTA 技术、数据集与论文五个主题。它服务于仓库中集成的 FairMOT(one-shot 在线跟踪算法),配套的完整入门材料位于 scenarios/tracking/README.md 以及两个 Notebook:
| Notebook | 说明 |
|---|---|
| 01_training_introduction.ipynb | 讲解模型训练、推理与评估的基本概念与典型指标 |
| 02_mot_challenge.ipynb | 在 MOT Challenge 数据集上运行模型推理 |
关于"需要多少训练样本""如何监控 GPU 使用率"等通用问题,可参见图像分类 FAQ。
二、数据篇:如何标注多目标跟踪数据
2.1 训练数据:复用目标检测标注,逐帧训练
FAQ 明确指出:MOT 训练使用与目标检测完全一致的标注格式(详见目标检测 FAQ),即从单帧图像训练,不利用帧间的时序位置信息。仓库的 TrackingDataset(见 utils_cv/tracking/dataset.py)正是沿用了目标检测模块的 Pascal VOC 解析器 parse_pascal_voc_anno,将 images 目录下的图像与 annotations 目录下的同名 XML 一一对应读取。
2.2 使用 VOTT 标注,并导出 PASCAL VOC / CSV
FAQ 推荐的标注工具是 VOTT。以标注视频中的两个易拉罐为例,将白/黄罐标记为 can_1、红罐标记为 can_2。标注前务必把提取帧率(extraction rate)设置为与视频帧率一致,以保证轨迹连续性。标注完成后可导出为 PASCAL VOC 或 CSV 等格式,VOTT 的 CSV 格式每行包含:
[image] [xmin] [y_min] [x_max] [y_max] [label]
2.3 FairMOT 训练标签:内部转换格式
用户不需要手工接触 FairMOT 的训练格式,但了解其转换规则有助于排查标注问题。在 TrackingDataset._write_fairMOT_format()(utils_cv/tracking/dataset.py)中,仓库会把 PASCAL VOC 标注转换为 FairMOT 期望的 labels_with_ids 目录,每个 .txt 文件的每一行描述一个框:
[class] [identity] [x_center] [y_center] [width] [height]
字段说明:
- class:恒为
0。FairMOT 参考实现目前只支持单类别多目标跟踪(例如易拉罐),因此所有目标归为一类; - identity:整数,范围
0 ~ num_identities - 1,将不同类别名映射为整数(如可乐罐、咖啡罐等)。源码中由label_idx - 1得到(背景矩形按设计取label_idx = 0); - [x_center] [y_center] [width] [height]:以图像宽/高归一化到
0~1区间的值。
同时会生成一份 <name>.train 文件,按行列出所有训练图像相对路径,供 FairMOT 的 JointDataset 加载。
2.4 评估数据:MOT Challenge 格式
评估阶段仓库遵循 py-motmetrics 的约定,要求 ground-truth 采用 MOT Challenge 格式:
[frame number] [id number] [bbox left] [bbox top] [bbox width] [bbox height] [confidence score] [class] [visibility]
其中最后三列(confidence / class / visibility)在人工标注 ground-truth 时可默认置为 -1。仓库的 boxes_to_mot()(utils_cv/tracking/dataset.py)在保存推理结果时会生成该格式的 10 列 CSV(预测时 confidence 置 1,其余置 -1),随后由 evaluate_mot() / mot_summary() 交给 motmetrics 计算指标(见 utils_cv/tracking/model.py)。
三、训练篇:FairMOT 的损失函数
3.1 损失组成
FAQ 指出 FairMOT 的损失分为两部分:
- 检测相关损失:
hm_loss(中心点热图损失)、wh_loss(宽高回归损失)、off_loss(中心偏移回归损失); - 身份相关损失:
id_loss(re-id 特征分类损失)。
总体损失 loss 是检测损失与 id 损失的加权组合。
3.2 源码级解析:可学习权重的加权
对照参考实现 utils_cv/tracking/references/fairmot/trains/mot.py 的 MotLoss.forward(),其计算方式比"固定权重加权"更进一步:
det_loss = opt.hm_weight * hm_loss + opt.wh_weight * wh_loss + opt.off_weight * off_loss
loss = torch.exp(-self.s_det) * det_loss + torch.exp(-self.s_id) * id_loss + (self.s_det + self.s_id)
loss *= 0.5
hm_weight=1、wh_weight=0.1、off_weight=1、id_weight=1为检测/身份各项的基础权重(默认值定义在 utils_cv/tracking/opts.py);s_det、s_id是可学习参数(初始值分别为-1.85、-1.05),用于动态权衡检测与身份两个任务分支,属于基于不确定性的自动加权策略;hm_loss采用 Focal Loss(实现见 utils_cv/tracking/references/fairmot/models/losses.py),wh/off回归默认用 L1 损失(reg_loss='l1'),id_loss采用带ignore_index=-1的交叉熵;- 身份特征维度
reid_dim=512,经emb_scale = sqrt(2) * log(nID - 1)缩放后送入nn.Linear(512, nID)分类器。
3.3 训练循环与损失可视化
TrackingLearner.fit()(utils_cv/tracking/model.py)实现训练主循环:默认 lr=1e-4、lr_step=[20, 27](在这两个 epoch 各把学习率降为原来的 1/10)、num_epochs=30。每个 epoch 结束后记录 loss / hm_loss / wh_loss / off_loss / id_loss,可通过 plot_training_losses() 直接绘制五条损失曲线,用于诊断训练是否收敛、各任务分支是否失衡。
四、推理篇:FairMOT 的主要推理参数
FAQ 列出的推理参数及作用如下:
| 参数 | 作用 |
|---|---|
input_w / input_h |
数据集视频帧送入网络的图像分辨率 |
conf_thres |
置信度阈值,过滤置信度不足的检测 |
nms_thres |
NMS 阈值,过滤重叠框 |
min_box_area |
最小框面积,过滤过小的框 |
track_buffer |
轨迹缓冲:若丢失轨迹在若干帧内未能重新匹配则被删除,且其 ID 不会复用 |
4.1 默认值与取值范围(源码确认)
opts 类(utils_cv/tracking/opts.py)给出的默认值:conf_thres=0.6、det_thres=0.3、nms_thres=0.4、track_buffer=30、min_box_area=200;input_w/input_h 默认 -1,由 MOT 数据集的默认分辨率 [608, 1088](高×宽)决定,网络输出特征图经 down_ratio=4 下采样。
4.2 推理调用链
TrackingLearner.predict()(utils_cv/tracking/model.py)的签名为:
predict(im_or_video_path, conf_thres=0.6, track_buffer=30,
min_box_area=200, frame_rate=30)
支持图像目录(.jpg/.jpeg/.png/.tif)或视频文件(.mp4/.avi)。底层调用 JDETracker.update()(utils_cv/tracking/references/fairmot/tracker/multitracker.py),关键行为包括:
track_buffer会按帧率换算:buffer_size = int(frame_rate / 30.0 * track_buffer),max_time_lost = buffer_size,即丢失超过该帧数即删除轨迹(mark_removed),ID 不再复用;- 检测框需满足
tlwh[2] * tlwh[3] > min_box_area且宽高比tlwh[2]/tlwh[3] < 1.6(过滤过窄的竖直框)才会被输出; - 数据关联分两步:第一步用 re-id 特征余弦距离并融合卡尔曼滤波运动距离(
fuse_motion,马氏距离门控、融合系数lambda_=0.98),阈值0.7;第二步对剩余检测用 IoU 距离,阈值0.5;未确认的新轨迹再单独做 IoU 匹配(阈值0.7)。两处匹配均调用linear_assignment()的lap.lapjv求解(见 utils_cv/tracking/references/fairmot/tracker/matching.py)。
由此可以推断:调高 conf_thres 会减少低置信检测与误报但可能漏检小目标;调大 track_buffer 会让轨迹在短暂遮挡后更易恢复,但 ID 长时间悬置可能增加身份混淆;min_box_area 过小则噪声框(背景误检)更容易进入轨迹。
五、评估篇:MOT Challenge 与常用指标
5.1 什么是 MOT Challenge
MOT Challenge 网站托管了行人 MOT 领域最常用的评测基准数据集,包括 MOT15、MOT16/17、MOT19/20 等。这些数据集包含多条难度不一的视频序列及人工标注的 ground-truth,并额外提供检测结果(detections)供参赛算法选用,便于将跟踪算法与检测算法解耦对比。
5.2 常用评估指标
多目标跟踪评估指标众多,按其计算方式可分为基于事件的指标(CLEAR MOT 指标)与基于 ID 的指标。MOT 基准中最主要的三个指标是 MOTA、IDF1 与 ID-switch:
- MOTA(Multiple Object Tracking Accuracy):基于事件计算跟踪结果与 ground-truth 的失配程度,衡量整体准确率。
MOTA = 1 - (FN + FP + IDSW) / GT,其中 FP 为误报数、FN 为漏报数、IDSW 为 ID 切换次数,三者之和除以 ground-truth 轨迹总数归一化; - IDF1:基于 ID 计算跟踪器正确识别目标的时间占比,是识别精确率(IDP)与识别召回率(IDR)的调和平均,
IDF1 = 2 * IDP * IDR / (IDP + IDR); - ID-switch:衡量跟踪器错误改变某条轨迹 ID 的次数。
ID-switch 的典型场景如下图所示:左侧,person A 与 person B 在 4–5 帧重叠且未被检测到,第 6 帧恢复时 A 被错误赋予原本属于 B 的 ID_2;右侧,person A(初始 ID_1)在第 3 帧后丢失,最终在第 n 帧被赋予新 ID_2,构成又一次 ID 切换。
在实际项目中,TrackingLearner.evaluate() 与 eval_mot()(utils_cv/tracking/model.py)会逐序列推理、保存 MOT 格式结果,并用 py-motmetrics 的 motchallenge_metrics 汇总 MOTA、MOTP、IDF1、ID-switch 等指标,供调参对比。
六、SoTA 技术篇
6.1 FairMOT 的架构
FairMOT 由一个单编码器-解码器神经网络构成,从视频帧中提取高分辨率特征图。作为 one-shot(单阶段)跟踪器,它在共享骨干之上接入两个并行 head:一个预测目标边界框(检测分支),一个预测 re-id 特征(身份分支):
仓库支持的骨干架构(arch 参数)在 utils_cv/tracking/references/fairmot/models/model.py 中注册,包括 dlav0、dla(DLA-34,默认)、resdcn、resfpndcn、hrnet 等。训练时网络输出的 head 为 hm / wh / id(以及可选的 reg),对应前述损失项。
6.2 tracking-by-detection 常用的目标检测器
SoTA 跟踪算法最常用的检测器包括:Faster R-CNN、SSD 与 YOLOv3。检测器负责在每帧生成候选框,跟踪器再对这些框做跨帧关联。更详细对比可参考目标检测 FAQ。
6.3 特征提取技术
- 传统局部特征:光流、区域特征(颜色直方图、梯度特征、协方差矩阵等);
- 深度 CNN 特征:在 re-id 数据集(如 MARS)上训练的经典 CNN 提取视觉特征,DeepSORT 即采用此方案;
- Siamese CNN:一对共享权重的 CNN 比较两个目标的相似度,以专门设计的损失函数学习最具区分性的特征;
- LSTM 网络:以不同时间帧上的检测特征序列为输入,基于历史预测下一帧的边界框;
- 相关性滤波(Correlation Filters):将相关滤波器与 CNN 特征图卷积,预测目标在下一帧的位置。
6.4 亲和度(Affinity)与数据关联(Association)技术
- 简单方案:基于 CNN 特征的欧氏/余弦距离计算亲和度得分,再用匈牙利(Hungarian / Munkres)算法做在线数据关联;离线数据关联则常用 K-partite graph 全局优化。仓库的
linear_assignment()即通过lap.lapjv(Jonker-Volgenant 变体)实现该类最优指派; - 复杂方案:将亲和度计算与特征提取融合,例如 Siamese CNN 与 Siamese LSTM 直接输出亲和度得分,从而端到端学习关联决策。
6.5 在线与离线(批处理)跟踪的区别
两者在数据关联步骤上不同:
- 在线跟踪:仅用当前帧的检测与历史帧生成的轨迹关联,扩展已有轨迹或创建新轨迹,逐帧实时推进;
- 离线(批处理)跟踪:可全局考察一个批次内所有观测,通过求全局最优解把观测连成轨迹。离线方法在长期遮挡、空间邻近相似目标等难题上通常表现更好,但速度更慢,不适合自动驾驶等要求实时处理的场景。
仓库集成的 FairMOT 属于在线跟踪器。
七、流行数据集与论文
7.1 常用 MOT 数据集
| 名称 | 年份 | 时长 | 轨迹/ID 数 | 场景 | 目标类型 |
|---|---|---|---|---|---|
| MOT15 | 2015 | 16 min | 1221 | 室外 | 行人 |
| MOT16/17 | 2016 | 9 min | 1276 | 室内外 | 行人、车辆 |
| CVPR19/MOT20 | 2019 | 26 min | 3833 | 拥挤场景 | 行人、车辆 |
| PathTrack | 2017 | 172 min | 16287 | YouTube 人物场景 | 行人 |
| Visdrone | 2019 | - | - | 无人机俯瞰 | 行人、车辆 |
| KITTI | 2012 | 32 min | - | 车载相机交通场景 | 行人、车辆 |
| UA-DETRAC | 2015 | 10 h | 8200 | 交通场景 | 车辆 |
| CamNeT | 2015 | 30 min | 30 | 室内外 | 行人 |
7.2 代表性跟踪算法论文
下表整理了原 FAQ 列出的代表性方法及其在 MOT16 上的公开指标与方案特征(数据来自原文档整理,供横向参考):
| 方法 | 年份 | MOT16 IDF1 | MOT16 MOTA | 推理速度(fps) | 在线/批处理 | 检测器 | 特征提取/运动模型 | 亲和度与关联方法 |
|---|---|---|---|---|---|---|---|---|
| FairMOT | 2020 | 70.4 | 68.7 | 25.8 | Online | One-shot 检测头 | One-shot re-id 头与多层特征聚合、IoU、卡尔曼滤波 | IoU 与 embedding 距离上的 JV 算法 |
| DeepMOT-Tracktor | 2020 | 53.4 | 54.8 | 1.6 | Online | 单目标跟踪器:Faster-RCNN (Tracktor)、GO-TURN、SiamRPN | Tracktor、CNN re-id 模块 | 使用 Bi-RNN 的 Deep Hungarian Net |
| Tracktor | 2019 | 54.9 | 56.2 | 1.6 | Online | 改进 Faster-RCNN | 时序 bbox 回归与相机运动补偿、Siamese CNN 的 re-id embedding | 基于 re-id embedding 距离的贪心 tracklet 合并 |
| JDE | 2019 | 55.8 | 64.4 | 18.5 | Online | One-shot 跟踪器(Faster R-CNN + FPN) | One-shot(Faster R-CNN + FPN)、卡尔曼滤波 | 匈牙利算法 |
| TNT | 2019 | 56.1 | 49.2 | 0.7 | Batch | MOT challenge 检测 | CNN 与相机运动补偿、embedding 特征相似度 | tracklet 对 CNN 相似度、基于 tracklet 的图割优化 |
| VIOU | 2018 | 56.1 (VisDrone) | 40.2 (VisDrone) | 20 (VisDrone) | Batch | Mask R-CNN、CompACT | IoU | KCF 与贪心 IoU 启发式合并 tracklet |
| DeepSORT | 2017 | 62.2 | 61.4 | 17.4 | Online | 改进 Faster R-CNN | CNN re-id 模块、IoU、卡尔曼滤波 | 匈牙利算法;基于马氏距离(运动)与 embedding 距离的级联匹配 |
| LMP | 2017 | 51.3 | 48.8 | 0.5 | Batch | 公开检测结果 | StackeNetPose CNN re-id 模块 | 时空关系、deep-matching、re-id 置信度;检测图 lifted-multicut 优化 |
这些表格中的指标体现了不同设计取向:one-shot 方案(FairMOT、JDE)在速度上优势明显;批处理方案(TNT、LMP)则更重视全局最优下的精确性。
八、在仓库中实操:环境与流程指引
若要在本地复现上述内容,可参考 scenarios/tracking/README.md:
- 环境依赖(仅支持 Linux 计算目标,受 FairMOT 参考实现约束):
conda activate cv
conda install -c conda-forge opencv yacs lap progress
pip install cython_bbox motmetrics
- 编译 DCNv2 扩展(FairMOT 的 DLA-34 骨干依赖可变形卷积):
cd utils_cv/tracking/references/fairmot/models/networks/DCNv2
sh make.sh
-
模型与数据:默认从
models/all_dla34.pth加载预训练权重;数据通过TrackingDataset(root, name, batch_size, im_dir, anno_dir)组织,images与annotations目录下分别放图像与 Pascal VOC XML 标注。 -
Notebook 实践:01_training_introduction.ipynb 走通训练-推理-评估全流程,02_mot_challenge.ipynb 在 MOT Challenge 数据上批量推理与评测,两者均基于本文所述的数据格式、损失与指标设计。
小结
本文以 FAQ 为纲、以仓库源码为证,覆盖了 MOT 从数据到评估的完整链路:训练用 Pascal VOC 逐帧标注、评估用 MOT Challenge 格式;FairMOT 以可学习权重融合 hm/wh/off 检测损失与 id_loss;推理参数 conf_thres、min_box_area、track_buffer 各有明确的底层机制;MOTA、IDF1、ID-switch 三个指标分别从事件、ID 与轨迹一致性三个视角刻画性能。理解这些细节,是开展高质量多目标跟踪实验、复现 SoTA 结果并针对自身数据调优的前提。