1. 项目缘起:为什么我们需要一个“一站式”的检测与跟踪资源库
在计算机视觉领域,尤其是自动驾驶、智能交通监控、机器人导航等应用场景中,车辆和行人的检测与跟踪是两项最基础、最核心的任务。我接触过不少刚入行的朋友,也包括一些需要快速验证算法的团队,他们面临的第一个难题往往不是模型本身,而是“数据”和“代码”从哪里来。网上资源确实很多,但散落在各个论文官网、GitHub仓库、学术数据集平台,质量参差不齐,标注格式五花八门,代码依赖的环境可能早已过时。光是整理和复现,就要耗费大量精力,更别提进行有效的对比实验了。
这个项目,或者说这篇总结,就是源于我过去几年里无数次“找数据、跑代码”的切身体会。我希望能整理一份相对全面、经过一定验证的“资源地图”,把那些真正好用、有代表性的公开数据集和开源代码汇总起来,并附上我踩过的坑和调试经验。这不仅仅是一个列表,更是一个带有实操指南的索引,目标是让你拿到这份资料后,能快速定位到适合自己需求的数据和工具,并少走弯路地跑起来。无论是想学习经典算法,还是为新产品做原型验证,这份汇总都能提供一个扎实的起点。
2. 核心数据集盘点:从经典基准到垂直场景
数据集是算法训练的基石。选择合适的数据集,意味着你的模型在一开始就站在了正确的赛道上。下面我将从通用性、规模、场景特点等维度,对主流的车辆行人检测与跟踪数据集进行分类梳理。
2.1 通用大型基准数据集
这类数据集规模大、标注质量高、场景多样,是学术研究和算法性能评测的“黄金标准”。
2.1.1 COCO (Common Objects in Context)虽然COCO以80类物体检测闻名,但其包含的‘person’和‘car’类别数据量巨大,且场景极其丰富。对于行人检测任务,COCO提供了超过25万张标注了行人的图像,姿态、遮挡、尺度变化都很大,是检验模型泛化能力的试金石。对于车辆,虽然类别不如专用数据集精细,但用于训练一个通用的车辆检测器仍然足够。它的标注格式(JSON)已成为业界事实标准,绝大多数开源代码都支持。
2.1.2 KITTI自动驾驶领域无人不知的经典数据集。它最大的特点是提供了多传感器同步数据(摄像头、激光雷达、GPS/IMU),并且标注包含了2D/3D边界框、朝向、遮挡/截断程度等丰富信息。其目标检测基准涵盖了‘Car’, ‘Pedestrian’, ‘Cyclist’等类别。需要注意的是,KITTI的数据采集于2011年左右,图像分辨率(1242x375)和场景复杂度以今天的标准看略显简单,但其严谨的评测标准和在学术界的深远影响,使其仍是入门自动驾驶视觉的必选项。
2.1.3 BDD100K (Berkeley DeepDrive)这是一个更现代、规模更大的驾驶场景数据集。它包含了10万段高清视频序列(约1000万帧),覆盖了不同天气(晴天、雨天、雪天)、不同时间(白天、夜晚)和不同地点。其标注不仅包括2D边界框(10类物体),还包括车道线、可行驶区域、语义分割等。对于需要研究时序一致性、复杂天气下鲁棒性,或者进行多任务学习的项目,BDD100K是极佳的选择。它的数据量足以训练大型模型而不易过拟合。
2.2 行人与车辆检测专项数据集
这类数据集针对特定任务进行了更精细的标注。
2.2.1 CityPersons & CrowdHuman两者都是专注于密集行人检测的数据集,专门解决遮挡和小尺度行人的难题。
- CityPersons:基于Cityscapes语义分割数据集的行人子集,在德国多个城市的街景中标注了行人。它的标注区分了可见区域和全身区域,对于研究严重遮挡下的行人检测非常有价值。
- CrowdHuman:一个大规模、高密度的行人检测数据集,图像主要来自互联网,场景拥挤,平均每张图有22.6个人,最高可达400多人。它提供了三种标注:人体可见框、人体全身框以及人体关键点。如果你想挑战极端密集场景,或者训练一个“人挤人”环境下依然稳健的检测器,这是不二之选。
2.2.2 UA-DETRAC这是一个专门用于车辆检测与跟踪的数据集,包含超过10小时的真实交通监控视频(约14万帧),在北京和天津的24个不同地点拍摄。它标注了超过8250辆车,总计121万个边界框。其挑战在于光照变化、车辆尺度变化以及不同程度的遮挡。数据集提供了清晰的训练集/测试集划分,并有一套完整的评测工具(包括检测精度和跟踪指标如MOTA、MOTP),非常适合用于研究多目标跟踪(MOT)算法。
2.3 多目标跟踪(MOT)专用数据集
跟踪任务不仅需要框,更需要跨帧的身份(ID)关联。
2.3.1 MOT Challenge 系列这是多目标跟踪领域最权威的评测基准。它包含多个子数据集,如MOT17、MOT20等。这些数据集提供已标注好行人ID的视频序列,标注格式统一。MOT17在相对简单的场景下提供了清晰的边界框和ID。MOT20则专注于极度拥挤的场景,人群密度非常大,对跟踪算法的数据关联和抗遮挡能力提出了终极挑战。几乎所有最新的跟踪算法(如ByteTrack, OC-SORT, BoT-SORT)都会在此基准上报告性能。
2.3.2 DanceTrack这是一个比较新的跟踪数据集,其目标不是行人或车辆,而是舞者。但正是这个特性使其成为检验跟踪算法泛化能力和解决“相似外观干扰”的利器。视频中多个舞者穿着相似服装,做着相似动作,外观区分度极低,传统的基于外观重识别(Re-ID)的跟踪方法在这里会遭遇滑铁卢。它迫使研究者更关注运动模型和稳健的数据关联策略。
注意:选择数据集时,务必考虑其许可协议。大部分学术数据集仅限非商业研究使用。若用于商业产品,可能需要购买商业许可证或自行采集数据。
3. 关键代码仓库与框架实战指南
有了数据,下一步就是让代码跑起来。这里我按任务类型,推荐几个经过社区验证、文档相对完善,且我个人成功部署过的开源项目。
3.1 检测任务:YOLO系列与MMDetection
3.1.1 YOLOv5 / YOLOv8 (Ultralytics)对于需要快速原型验证和部署的开发者,Ultralytics维护的YOLOv5和YOLOv8是首选。它们的最大优点是“开箱即用”。
- 环境配置:通常一个
pip install ultralytics就能安装核心库。但如果你想从源码训练,建议使用Python 3.8+和PyTorch 1.7+。我遇到过在Python 3.10上某些依赖包冲突的问题,回退到3.8后解决。 - 数据准备:你需要将数据集转换为YOLO格式(每个图像对应一个.txt文件,内容为
class_id x_center y_center width height,坐标归一化)。COCO、KITTI等都有现成的转换脚本。关键点:务必检查转换后标签文件中的类别ID是否与你的data.yaml配置文件中的names列表顺序一致,这是最常见的报错来源。 - 训练与验证:命令极其简单,如
yolo train data=coco.yaml model=yolov8n.pt epochs=100。实操心得:在自定义数据集上,不要一上来就训练很多轮。先用小模型(如YOLOv8n)、少轮数(如50轮)跑一个快速实验,确认数据管道、损失曲线正常。关注val/box_loss和val/cls_loss在验证集上的表现,确保它们没有持续上升(过拟合)。 - 部署:Ultralytics提供了导出到ONNX、TensorRT、CoreML等格式的一键命令(
yolo export)。在部署到边缘设备(如Jetson系列)时,TensorRT版本与CUDA、PyTorch版本的兼容性是最大的坑。建议严格按照官方Docker镜像或文档中指定的版本组合来搭建环境。
3.1.2 MMDetection (OpenMMLab)如果你需要更前沿的算法、更灵活的模块化设计,或者进行严谨的学术研究,MMDetection是更强大的工具箱。它实现了数十种检测算法(Faster R-CNN, Cascade R-CNN, RetinaNet, DETR系列等)。
- 环境搭建:MMDetection的依赖管理更严格,强烈建议使用其提供的MIM工具和Dockerfile。我的经验是,在Ubuntu系统上,按照官方“安装”文档一步步走,成功率最高。避免手动混用
conda和pip安装,容易导致版本地狱。 - 配置文件系统:这是MMDetection的核心,也是学习曲线最陡的部分。它采用模块化继承设计。例如,你想在COCO数据集上用ResNet-50 backbone训练Faster R-CNN,配置文件可能继承自多个基础配置。调试技巧:使用
python tools/misc/print_config.py /path/to/your_config.py可以打印出完整的、解析后的配置,方便你确认所有参数是否按预期合并。 - 自定义数据集:你需要编写一个新的数据集类(继承
CustomDataset),并修改配置文件中的data部分。MMDetection支持COCO格式和VOC格式。我通常将数据转为COCO格式,因为其标注信息更丰富,且社区工具支持更广。 - 训练技巧:MMDetection默认配置是针对8 GPU设计的。在单卡或双卡上训练时,必须等比缩放学习率(LR)和批次大小(batch size)。经典规则是:
new_lr = old_lr * new_bs / old_bs。同时,要相应调整训练总轮数(max_epochs),因为更小的batch size意味着参数更新更频繁,可能需要更多轮次来收敛。
3.2 多目标跟踪(MOT)任务:ByteTrack与BoT-SORT
跟踪是在检测的基础上增加跨帧的ID关联。目前主流范式是“检测+关联”(Tracking-by-Detection)。
3.2.1 ByteTrackByteTrack的核心思想非常简单却有效:充分利用低分数检测框(在YOLOX中,通常指分数在0.1-0.5之间的框)进行关联。传统方法会直接过滤掉这些低分框,认为它们是背景。但ByteTrack发现,很多被遮挡目标的检测分数会下降,直接丢弃会导致ID丢失(ID Switch)。它先使用高分框与已有轨迹进行第一次关联(Kalman滤波预测+IoU匹配),再将未匹配的高分框和低分框一起,与第一次未匹配的轨迹进行第二次关联。这个策略显著提升了在遮挡和运动模糊情况下的跟踪稳定性。
- 复现要点:官方实现基于YOLOX和PyTorch。你需要先准备好YOLOX检测器在目标数据集(如MOT17)上训练好的模型。关键步骤是数据预处理:必须将公开数据集的标注或你自己的视频,处理成MOT Challenge规定的输入格式(
[frame_id, obj_id, x, y, w, h, score, class, visibility_ratio])。ByteTrack仓库提供了对MOT数据的预处理脚本。 - 参数调试:最重要的两个参数是检测阈值
track_thresh(第一次关联的高分阈值)和match_thresh(IoU匹配阈值)。在人群密集场景下,可以适当降低match_thresh(如从0.8调到0.6),并提高track_buffer参数(允许轨迹短暂丢失后恢复的帧数),以应对频繁遮挡。
3.2.2 BoT-SORT & ByteTrack的演进BoT-SORT在ByteTrack的基础上,引入了相机运动补偿(CMC)和更精细的外观嵌入(Re-ID)融合策略。CMC通过特征点匹配估计相邻帧间的仿射变换,补偿因相机抖动或运动带来的整体位移,使得基于IoU的关联更准确。这对于车载或手持摄像头拍摄的视频至关重要。
- 部署经验:BoT-SORT的代码结构更复杂,依赖OpenCV的ECC算法做运动估计。在部署时,确保你的OpenCV版本编译了
opencv_contrib模块。如果跟踪实时性要求高,CMC计算可能成为瓶颈,可以尝试每N帧计算一次,而不是每帧都算。 - 关于Re-ID:许多跟踪框架(包括FastReID库)支持集成Re-ID模型。但引入Re-ID会显著增加计算量,并且在外观相似目标多的场景(如DanceTrack)可能起反作用。我的建议是:先只用运动信息(IoU+Kalman)跑通基线,在ID Switch严重时,再考虑加入轻量级的Re-ID分支,并仔细调整运动模型和外观相似度的融合权重。
3.3 一站式解决方案:PySlowFast 与 Detectron2
对于希望在一个框架内同时完成检测、跟踪甚至行为分析的研究团队,Meta AI(前Facebook AI)推出的PySlowFast和Detectron2是工业级的选择。
3.3.1 Detectron2这是一个模块化、高性能的视觉算法库,基于PyTorch。它不仅是检测,还涵盖了分割、关键点检测等。其模型动物园(Model Zoo)提供了大量预训练模型。对于跟踪,它通过Detectron2-Dev等分支项目提供了MOT任务的实现参考。它的数据加载器(DatasetMapper)、模型构建(build_model)和流水线设计非常优雅,适合中大型项目进行二次开发。但它的学习曲线比YOLO和MMDetection更陡,对编程能力要求更高。
3.3.2 PySlowFast如果你主要处理视频数据,并需要时空特征,PySlowFast是专为视频理解设计的。它天然支持从视频中提取片段进行训练和推理,其核心的“慢快通路”网络结构能高效捕捉时空信息。虽然它本身不直接提供“跟踪”模块,但其强大的视频特征提取能力,可以作为跟踪算法中外观表征部分的上游网络。例如,你可以用PySlowFast提取每帧或每个目标区域的特征,再输入到自定义的关联算法中。
4. 从数据到结果:全流程实操与避坑指南
这一部分,我将以一个具体的例子串联起整个流程:使用YOLOv8在BDD100K数据集上训练一个车辆行人检测器,并用ByteTrack在一段新视频上进行跟踪。
4.1 数据准备与预处理
- 获取数据:从BDD100K官网下载“100K Images”和“Detection Labels”。你会得到图片文件夹和一个大的
det_v2_train_release.json标签文件。 - 格式转换:BDD100K使用JSON格式,需要转换为YOLO格式。你需要写一个解析脚本,关键步骤如下:
避坑点:务必检查转换后的边界框坐标是否在[0, 1]之间,且宽高是否为正数。我曾遇到过原始标注有误(x1 > x2)导致训练时损失为NaN的情况。import json import os # 加载JSON文件 with open('det_v2_train_release.json', 'r') as f: data = json.load(f) # BDD100K类别映射到YOLO类别ID # 假设我们只关心‘car’, ‘person’, ‘traffic light’, ‘traffic sign’, ‘bus’, ‘truck’ category_map = {'car': 0, 'person': 1, 'traffic light': 2, 'traffic sign': 3, 'bus': 4, 'truck': 5} for img_info in data: img_name = img_info['name'] img_width = img_info['width'] img_height = img_info['height'] labels = img_info['labels'] txt_path = os.path.join('labels/train', img_name.replace('.jpg', '.txt')) with open(txt_path, 'w') as txt_f: for label in labels: cat = label['category'] if cat not in category_map: continue # 跳过不关心的类别 box = label['box2d'] x_center = (box['x1'] + box['x2']) / 2.0 / img_width y_center = (box['y1'] + box['y2']) / 2.0 / img_height width = (box['x2'] - box['x1']) / img_width height = (box['y2'] - box['y1']) / img_height # 写入: class_id x_center y_center width height txt_f.write(f"{category_map[cat]} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n") - 组织目录:创建
datasets/bdd100k目录,内部结构如下:
将图片和对应的.txt标签文件分别放入bdd100k/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/images和labels的对应子文件夹。
4.2 模型训练与调优
- 配置文件:创建一个
bdd100k.yaml文件放在YOLOv8项目根目录。# bdd100k.yaml path: /path/to/your/datasets/bdd100k train: images/train val: images/val # 类别数 nc: 6 # 类别名称,顺序必须与转换脚本中的category_map一致 names: ['car', 'person', 'traffic light', 'traffic sign', 'bus', 'truck'] - 开始训练:
yolo task=detect mode=train model=yolov8m.pt data=bdd100k.yaml epochs=150 imgsz=640 batch=16 workers=8model=yolov8m.pt:使用中等大小的预训练模型,在速度和精度间取得平衡。imgsz=640:BDD100K图像原始分辨率多样,统一缩放到640x640训练是常见做法。如果显存充足,可以尝试768或1024,可能带来精度提升。workers=8:数据加载线程数,根据你的CPU核心数调整。设置过高可能导致内存溢出。
- 监控与调优:训练开始后,使用TensorBoard或YOLOv8自带的日志工具监控损失曲线和验证集指标(mAP@0.5)。
- 如果训练损失下降但验证集mAP不升:可能是过拟合。尝试增加数据增强(在
bdd100k.yaml中配置augment: True并调整增强参数),或使用更大的模型(如yolov8l.pt),或减少训练轮数。 - 如果验证集mAP在某个轮数后剧烈波动:可能是学习率太大。尝试使用
cos学习率调度器,并降低初始学习率(lr0参数)。
- 如果训练损失下降但验证集mAP不升:可能是过拟合。尝试增加数据增强(在
4.3 跟踪推理与集成
训练好检测模型(假设保存为best.pt)后,我们使用ByteTrack进行跟踪。
- 准备ByteTrack环境:克隆ByteTrack仓库,安装依赖。注意其
requirements.txt可能与你训练YOLO的环境有冲突,建议使用虚拟环境。 - 修改检测器:ByteTrack官方示例使用YOLOX。我们需要将其替换为我们的YOLOv8模型。核心是编写一个适配器类,将YOLOv8的输出格式转换成ByteTrack需要的格式(
[x1, y1, x2, y2, score, class])。# 伪代码示例:在ByteTrack的tools/demo_track.py中修改 from ultralytics import YOLO class YOLOv8Detector: def __init__(self, model_path): self.model = YOLO(model_path) def __call__(self, img): results = self.model(img, verbose=False)[0] # 推理单张图片 boxes = results.boxes if boxes is None: return np.empty((0, 6)) # 提取框、分数、类别 dets = boxes.data.cpu().numpy() # [N, 6] (x1, y1, x2, y2, conf, cls) # ByteTrack需要分数在0-1之间,且类别为整数 dets[:, 4] = dets[:, 4].astype(np.float32) dets[:, 5] = dets[:, 5].astype(np.int32) return dets # 替换原来的检测器初始化 detector = YOLOv8Detector("path/to/your/best.pt") - 运行跟踪:配置好视频输入路径和输出路径,运行脚本。关键要调整ByteTrack的参数,特别是
track_thresh和match_thresh。对于车辆跟踪,由于车辆大小和运动相对规律,match_thresh可以设高一点(如0.7)。对于行人,尤其是密集行人,可能需要降低到0.5。 - 结果可视化:ByteTrack会输出带ID的边界框。你可以使用OpenCV将ID和框绘制在视频帧上。一个实用技巧:为不同ID分配固定颜色太难,可以为每个ID生成一个随机的但持续的颜色,这样在视频中更容易追踪单个目标的运动轨迹。
4.4 常见问题排查清单
- 训练时CUDA out of memory:降低
batch_size和imgsz。检查是否有其他进程占用显存。使用torch.cuda.empty_cache()。 - 验证时mAP为0或极低:首先检查数据标注路径是否正确。其次,验证数据集中是否有目标?用训练好的模型在几张验证集图片上可视化一下,看是否能检测出东西。最常见的原因是类别ID不匹配或标注文件为空。
- 跟踪时ID Switch频繁:首先检查检测器在单帧上的性能是否稳定(有无漏检、误检)。如果检测没问题,尝试调整ByteTrack的
track_buffer(增加以容忍短暂丢失)和match_thresh(降低以在遮挡时也能关联)。考虑是否引入相机运动补偿(CMC)。 - 跟踪速度慢:瓶颈通常在检测阶段。可以尝试换用更小的检测模型(如YOLOv8n),或者使用TensorRT加速推理。对于ByteTrack,关联算法的复杂度与目标数量成平方关系,在目标极多时(>100),可以考虑使用更高效的距离计算方式(如向量化操作)。
整个流程走下来,你会发现从数据准备到最终跟踪,每一步都有细节需要注意。这份汇总和指南的目的,就是帮你捋顺这条路径,把宝贵的精力集中在算法改进和业务逻辑上,而不是重复解决环境配置和数据格式这些“脏活累活”。在实际项目中,你可能还需要考虑模型量化、部署优化、前后端集成等一系列工程问题,但有了一个稳定可靠的检测跟踪基础,这些后续工作就有了坚实的立足点。