实战派教程:用YOLOv8+DeepSORT在MOT17数据集上跑通你的第一个跟踪Demo
实战派教程用YOLOv8DeepSORT在MOT17数据集上跑通你的第一个跟踪Demo当你第一次接触多目标跟踪MOT时可能会被各种算法和数据集搞得晕头转向。别担心这篇文章将带你从零开始用最流行的YOLOv8检测器和DeepSORT跟踪器在MOT17数据集上实现一个完整的跟踪流程。我们会一步步搭建环境、准备数据、编写代码最终生成可视化的跟踪结果。1. 环境准备搭建你的跟踪实验室在开始之前我们需要确保开发环境配置正确。这里推荐使用Python 3.8和PyTorch 1.10的组合它们能提供最佳的兼容性和性能。首先安装基础依赖conda create -n mot python3.8 conda activate mot pip install torch torchvision torchaudio接下来安装YOLOv8和DeepSORT相关包pip install ultralytics # 包含YOLOv8 pip install opencv-python numpy scipy # 基础计算机视觉库 pip install githttps://github.com/nwojke/deep_sort.git # DeepSORT官方实现提示如果你有NVIDIA显卡建议安装对应版本的CUDA和cuDNN以加速计算。可以运行nvidia-smi查看显卡支持的CUDA版本。验证安装是否成功import torch print(torch.__version__) print(torch.cuda.is_available()) # 应该返回True2. 数据准备理解MOT17数据集结构MOT17是多目标跟踪领域最常用的基准数据集之一包含21个训练序列和21个测试序列。每个序列都提供了高质量的标注和多种检测器的输出。数据集目录结构通常如下MOT17/ ├── train/ │ ├── MOT17-02-DPM/ │ │ ├── det/ │ │ ├── gt/ │ │ ├── img1/ │ │ └── seqinfo.ini │ ├── MOT17-02-FRCNN/ │ ├── MOT17-02-SDP/ │ └── ...其他序列 └── test/ └── ...类似train的结构关键文件说明det/det.txt: 预生成的检测结果gt/gt.txt: 真实标注仅训练集有img1/: 视频帧图像序列seqinfo.ini: 序列元信息3. 核心代码实现从检测到跟踪现在我们来编写核心的跟踪代码。整个过程可以分为三个步骤检测、特征提取、关联跟踪。首先创建一个tracker.py文件导入必要的库import cv2 import numpy as np from ultralytics import YOLO from deep_sort import DeepSort from deep_sort.utils.parser import get_config初始化YOLOv8检测器和DeepSORT跟踪器# 加载YOLOv8模型 detector YOLO(yolov8n.pt) # 也可以使用yolov8s/m/l/x等不同尺寸的模型 # 配置DeepSORT deepsort_cfg get_config() deepsort_cfg.merge_from_file(deep_sort/configs/deep_sort.yaml) tracker DeepSort( deepsort_cfg.DEEPSORT.REID_CKPT, max_distdeepsort_cfg.DEEPSORT.MAX_DIST, min_confidencedeepsort_cfg.DEEPSORT.MIN_CONFIDENCE, nms_max_overlapdeepsort_cfg.DEEPSORT.NMS_MAX_OVERLAP, max_iou_distancedeepsort_cfg.DEEPSORT.MAX_IOU_DISTANCE, max_agedeepsort_cfg.DEEPSORT.MAX_AGE, n_initdeepsort_cfg.DEEPSORT.N_INIT, nn_budgetdeepsort_cfg.DEEPSORT.NN_BUDGET, use_cudaTrue )编写处理单帧的函数def process_frame(frame): # 使用YOLOv8检测 results detector(frame, classes[0]) # 只检测人(类别0) detections [] for result in results: boxes result.boxes.xyxy.cpu().numpy() confs result.boxes.conf.cpu().numpy() for box, conf in zip(boxes, confs): x1, y1, x2, y2 box w, h x2 - x1, y2 - y1 detections.append([x1, y1, w, h, conf]) # 转换为numpy数组 detections np.array(detections) # DeepSORT跟踪 if len(detections) 0: tracks tracker.update(detections, frame) else: tracks [] # 绘制结果 for track in tracks: x1, y1, x2, y2, track_id track cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.putText(frame, fID: {track_id}, (int(x1), int(y1)-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) return frame4. 运行完整流程从视频到跟踪结果现在我们可以将上述代码整合成一个完整的流程。创建一个main.py文件import os from tracker import process_frame # 视频路径 video_path MOT17/train/MOT17-02-FRCNN/img1/%06d.jpg # 图像序列 output_path output.mp4 # 获取帧序列 frame_files sorted([f for f in os.listdir(MOT17/train/MOT17-02-FRCNN/img1) if f.endswith(.jpg)]) # 读取第一帧获取视频参数 sample_frame cv2.imread(os.path.join(MOT17/train/MOT17-02-FRCNN/img1, frame_files[0])) height, width sample_frame.shape[:2] # 初始化视频写入器 fourcc cv2.VideoWriter_fourcc(*mp4v) out cv2.VideoWriter(output_path, fourcc, 30.0, (width, height)) # 处理每一帧 for frame_file in frame_files[:300]: # 只处理前300帧作为示例 frame cv2.imread(os.path.join(MOT17/train/MOT17-02-FRCNN/img1, frame_file)) processed_frame process_frame(frame) out.write(processed_frame) cv2.imshow(Tracking, processed_frame) if cv2.waitKey(1) 0xFF ord(q): break out.release() cv2.destroyAllWindows()5. 常见问题与解决方案在实际运行过程中你可能会遇到以下问题CUDA内存不足降低YOLOv8模型尺寸如使用yolov8n.pt而不是yolov8x.pt减小输入图像尺寸detector(frame, imgsz640)跟踪ID频繁切换调整DeepSORT的max_dist参数降低特征匹配阈值增加max_age参数允许轨迹更长时间不更新检测框抖动对检测结果进行简单的卡尔曼滤波平滑使用YOLOv8的跟踪模式results detector.track(frame, persistTrue)性能优化技巧使用TensorRT加速YOLOv8对DeepSORT的特征提取器使用半精度(fp16)# 启用半精度的示例 torch.backends.cudnn.benchmark True torch.set_float32_matmul_precision(medium)6. 评估跟踪性能当你的跟踪器能够稳定运行后你可能想了解它的性能如何。MOT领域有几个关键指标指标全称解释MOTAMultiple Object Tracking Accuracy综合考虑FP、FN、IDSW的综合指标IDF1Identity F1 Score衡量ID保持能力的指标MTMostly Tracked被跟踪超过80%时间的轨迹比例MLMostly Lost被跟踪少于20%时间的轨迹比例计算这些指标需要使用专门的评估工具如MOTChallenge官方提供的py-motmetrics:pip install motmetrics使用示例import motmetrics as mm # 加载真实标注和跟踪结果 gt mm.io.load_motchallenge(MOT17/train/MOT17-02-FRCNN/gt/gt.txt) ts mm.io.load_motchallenge(your_tracking_results.txt) # 计算指标 acc mm.utils.compare_to_groundtruth(gt, ts) mh mm.metrics.create() summary mh.compute(acc, metricsmm.metrics.motchallenge_metrics) print(summary)7. 进阶优化方向当基本流程跑通后你可以尝试以下优化方法提升跟踪性能检测器优化在MOT17上微调YOLOv8使用更大的输入分辨率尝试其他检测器如Faster R-CNN、RetinaNet跟踪器改进替换更强的ReID模型实现自定义的关联逻辑添加轨迹预测模块后处理技巧轨迹插值和平滑基于场景几何的过滤多摄像头协同跟踪# 微调YOLOv8的示例代码 model YOLO(yolov8n.pt) model.train(datacoco.yaml, epochs50, imgsz640, batch16)记住多目标跟踪是一个复杂的系统工程需要不断调试和优化各个模块的参数。在实际项目中我通常会先确保检测器的质量足够好然后再集中精力优化跟踪关联逻辑。