YOLOv8+DeepSort多目标跟踪实战:从检测框到稳定ID的完整实现

发布时间:2026/9/11 22:59:41
YOLOv8+DeepSort多目标跟踪实战:从检测框到稳定ID的完整实现 简介这是一套基于YOLOv8与DeepSORT框架的多目标跟踪算法项目源码专为计算机专业学生及算法实战学习者设计可直接用于毕业设计、课程设计或期末大作业。项目由导师指导完成被评为98分调试稳定确保开箱即运行。全部文件共696个以Python源码.py与.pyc为核心辅以YAML模型配置、图像与GIF演示素材、UI界面设计文件.ui/.qss以及参考文档.docx压缩包约47.14MB结构清晰便于按需查阅。目前已有802人学习适合正在研究目标检测与跟踪结合方向的读者。资源附带了可运行的项目源码、演示样例与配套文档能够帮助理解YOLOv8在目标检测阶段的输出如何输入DeepSORT进行身份关联与轨迹管理读者还可通过替换视频或调整YAML配置来验证不同场景下的跟踪效果是完成毕设或项目实践的高质量参考。1. 从 bus.jpg 里的一条时间线说起yolov8 负责看见deepsort 负责记住解压这个 yolo 项目后先把 demo.gif 逐帧拆开看bus.jpg 里的行人排成一列从画面左侧走到右侧每个检测框上都挂着一个数字 ID互相遮挡后重新露头ID 还是原来的。这就是多目标跟踪和纯目标检测的区别——yolov8 只回答“这一帧哪些位置有行人”deepsort 要回答“这个行人从上一帧到这一帧是不是同一个人”。整套源码把两件事接在了一起压缩包里有完整工程、手册.docx以及 bus.jpg、zidane.jpg、train.jpg 几个测试图。适合正在做毕业设计、需要直接跑通 MOT 项目的同学也适合准备用自定义数据集做车辆或行人计数的开发者。2. 双模型接口设计检测框坐标如何变成带 ID 的轨迹2.1 YOLOv8 检测输出从 tensor 到 xyxy 再喂给跟踪器YOLOv8 是 anchor-free 检测器网络结构中最大的变化是 C2f 模块。C2f 把多个 Bottleneck 的输出做 concat再经过一次卷积形成更丰富的梯度回流路径配合 SPPF 做多尺度池化检测头直接输出无锚框的类别概率和边界框回归量。对跟踪系统来说真正需要的只是每帧的边界框坐标、置信度和类别号不需要关心内部 tensor 怎么排布因为 ultralytics 包已经把后处理封装好了。拿到检测结果的第一步是把框转成 DeepSort 认得的格式from ultralytics import YOLO model YOLO(yolov8s.pt) def detect_one_frame(frame): results model(frame, verboseFalse, conf0.25, iou0.5) r results[0] boxes r.boxes.xyxy.cpu().numpy() # [x1, y1, x2, y2]像素坐标 scores r.boxes.conf.cpu().numpy() # 置信度 classes r.boxes.cls.cpu().numpy() # 类别 id return boxes, scores, classes参数说明conf0.25是置信度阈值用来过滤低质量框iou0.5是 NMS 的 IoU 阈值两个重叠超过一半的框会被合并。对跟踪场景conf不是越高越好——行人互相遮挡时检测置信度会掉到 0.3 以下为了保留这些框不少项目会把阈值降到 0.2 左右。代价是误检变多而这些误检框同样会被 DeepSort 分配 ID所以后面要靠n_init参数兜底。2.2 DeepSort 的三层关联外观特征、运动预测与级联匹配DeepSort 维持着若干条轨迹每条轨迹内部有一个卡尔曼滤波器状态量是中心坐标、宽高比、高度以及对应的速度分量。每一帧检测框进来后卡尔曼先预测旧轨迹在当前帧的位置算出预测框和检测框的马氏距离这是运动匹配的度量。但只靠运动匹配两辆外观接近但速度一致的汽车容易混淆。因此 DeepSort 还有一个外观分支用一个小型残差网络把每个框裁出来提成 128 维特征计算新框和旧轨迹特征库的余弦距离作为外观相似度。做主数据关联时先对可信度高的轨迹做级联匹配再用 IOU 匹配兜底整体指派交给匈牙利算法求解。这个流程决定了同一目标只要没丢太久ID 就一直挂得住。提示DeepSort 并不是每一帧重新识别身份而是靠上一帧的轨迹预测当前帧位置再匹配。所以 ID 跳变通常不是检测器单独造成的而是卡尔曼预测和特征库之间的匹配断掉了。2.3 主循环代码把检测结果 update 进 tracker工程里的主循环基本是“读帧 → 检测 → update → 画框”。核心调用长这样import cv2 from ultralytics import YOLO from deep_sort.deep_sort import DeepSort tracker DeepSort( model_pathdeep_sort/deep/checkpoint/ckpt.t7, max_dist0.2, # 特征余弦距离阈值超过视为不同目标 max_iou_distance0.7, # IOU 匹配时允许的最大 IoU 距离 max_age30, # 目标丢失后轨迹保留的帧数 n_init3, # 连续匹配多少帧才确认 ID nn_budget100 # 每条轨迹特征库的样本上限 ) cap cv2.VideoCapture(demo.gif) while True: ret, frame cap.read() if not ret: break results model(frame, verboseFalse) r results[0] boxes r.boxes.xyxy.cpu().numpy() confs r.boxes.conf.cpu().numpy() clss r.boxes.cls.cpu().numpy() track_out, det_conf tracker.update(boxes, confs, clss, frame) for x1, y1, x2, y2, track_id, cls_id in track_out: cv2.putText(frame, fID {track_id}, (int(x1), int(y1) - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.imshow(mot, frame) if cv2.waitKey(1) 0xFF ord(q): break参数说明tracker.update的入参是当前帧全部检测框、置信度、类别和原始帧图像其中类别列表有的分支不参与关联只作为输出透传。返回的track_out每行是x1, y1, x2, y2, track_id, cls_id如果类别始终是 -1说明这套 DeepSort 分支不带类别输出需要额外维护一个track_id - cls的映射表。max_age30表示目标连续 30 帧没匹配到检测框才彻底删除轨迹行人被汽车挡住一两秒后还能找回原 ID。2.4 特征提取模型选型为什么默认是 ckpt.t7ckpt.t7是 DeepSort 常见开源版本自带的权重输入是64x128的抠图输出 128 维行人外观特征。它体积小、CPU 也能跑得动对行人跟踪足够用。如果跟踪目标是车辆或者摄像头俯视角度很大这个特征就不一定稳很多项目会换成针对车辆 reid 训练的特征模型。换的时候不用改主循环只需要保证新模型输出固定维度的向量并在DeepSort内部对齐预处理尺寸。模型变体特点跟踪场景建议yolov8n最快小目标容易漏CPU 实时演示yolov8s速度精度均衡默认首选yolov8m精度高显存需求升高GPU 车流计数yolov8x精度最高帧率最低离线视频分析模型的选择直接决定跟踪的上限。检测器漏检后面 DeepSort 再强也要靠max_age硬撑检测器误检跟踪器会把影子也当成目标记 ID。所以项目里如果只跑动图建议从 yolov8s 起步先把链路打通再考虑换大模型。3. 环境装配与图片实测把解压后的源码跑出框和 ID3.1 环境装配先把依赖装到能跑 CPU 推理这个项目运行前最卡人的是环境依赖。压缩包里的 requirements.txt 一般规定了 ultralytics、torch、opencv-python 等版本范围。不要把 ultralytics 直接装最新版因为它和 deepsort 分支里的接口可能不兼容。我的建议是先按 CPU 跑通一次再决定要不要 GPU。先创建干净环境cd yolov8_deepsort_project conda create -n mot python3.9 -y conda activate mot pip install -r requirements.txt python -c import torch; print(torch.__version__, torch.cuda.is_available())参数说明最后一条命令会输出 PyTorch 版本以及 CUDA 是否可用。如果机器有 NVIDIA 显卡安装 PyTorch 时要用对应 CUDA 版本的轮子否则训练速度会非常难受。yolov8s 在 CPU 上也能跑但对实时视频流来说单帧推理通常会掉到 1 秒以上deepsort 的特征提取反而小CPU 上负担不大。很多人问“需要用到 gpu 吗”回答是演示动图不需要训练自定义数据和跑实时流需要。3.2 压缩包目录与手册.docx 的正确打开方式拿到压缩包后不要直接双击跑先看两个东西手册.docx 和 demo_cam_para.jpg。手册一般写了运行环境和入口命令demo_cam_para.jpg 表面上是测试图实际上是摄像头参数参考图用来对齐画面尺寸和畸变参数。工程里的图片文件各有用途文件场景作用demo.gif演示动图展示多目标跟踪完整流程bus.jpg街道行人遮挡多、目标多压测用zidane.jpg球场两人长时间跟踪 ID 稳定性train.jpg列车站台目标密集场景demo_cam_para.jpg摄像头参数对齐 USB 相机分辨率单张图片跑跟踪得到的只有一个框集看不出 ID 连续性。要验证效果用 demo.gif 或视频流更有意义。我第一次跑的时候直接拿 bus.jpg 单帧测发现所有框都正常但完全暴露不了 deepsort 的工作过程后来改成接摄像头才发现遮挡情况下 ID 会互相交换。3.3 运行主入口从 bus.jpg 到摄像头实时流工程里一般会有一个 main.py 或 track.py 作为入口常用命令是python main.py --source bus.jpg --save-vid python main.py --source demo.gif --save-vid python main.py --source 0 --camera-param demo_cam_para.jpg --save-vid参数说明--source接收图片、视频文件、摄像头序号或者 RTSP 流地址--source 0表示打开本机默认摄像头--save-vid会把处理结果写成视频文件方便把 demogif 那样同一行人保持同一 ID 的效果录下来复盘--camera-param传入 demo_cam_para.jpg 对应的相机参数文件如果只是本地测试这个参数可以不加。跑起来以后重点观察两处检测框是否稳定落在目标身上以及框角上的 ID 在目标转身或遮挡后是否保持不变。如果 ID 频繁切换优先去看检测阈值和跟踪参数而不是怀疑代码坏了。3.4 从输出 txt 判断 ID 是否稳定工程里开启--save-txt后每帧结果会落成文本每行格式通常是frame_id, class_id, x1, y1, x2, y2, conf判断 ID 是否稳定的一个笨办法是取同一个 target 的 ID在所有帧里打印其中心点坐标。如果这个 ID 的中心点发生大幅跳变说明匹配错乱如果目标还在但 ID 变成新的说明轨迹被删除重建了。这类问题单看结果视频很难定位看输出 txt 反而快。4. 数据准备与损失曲线训练 yolov8 自己的检测器而不是只跑动图4.1 数据标注与 data.yaml 的组织方式如果想把这套源码用在自己的场景比如识别电动车或者工地安全帽核心工作是重训 yolov8 检测器deepsort 本身不需要训练。先标注一批数据按照 YOLO 格式组织目录path: ./datasets/vehicle train: images/train val: images/val names: 0: car 1: bus 2: truck参数说明path是数据集根目录train和val是相对path的图片目录。每个图片同名 txt 放在 labels 目录下每一行是class_id, x_center, y_center, width, height坐标全部归一化。标注工具建议用 labelImg 或 labelme导出 YOLO 格式即可。4.2 yolov8 训练命令与 C2f 收益数据准备好后训练命令很直接yolo detect train datadata.yaml modelyolov8s.pt epochs100 imgsz640 batch16 device0 yolo detect val modelruns/detect/train/weights/best.pt datadata.yaml参数说明modelyolov8s.pt是预训练权重可以迁移到自己的小数据集imgsz640是训练分辨率目标小就调大device0指定第一张 GPUCPU 训练可以把 batch 调小到 4。训练完成后把runs/detect/train/weights/best.pt替换到主工程的模型路径再重新跑跟踪流程。C2f 结构带来的直接收益是对重叠目标的 recall 更高它把各层输出 concat 后送入检测头梯度路径更短小目标特征不容易被深层的连续卷积稀释。对跟踪的意义是检测稳定后deepsort 就不需要反复通过max_age和n_init补赛道ID 交换会少很多。4.3 deepsort 参数调优max_age、n_init、nn_budget 怎么配合检测器重训完之后通常需要回过来调 tracking 阈值。train.jpg 这种密集人群里行人互相遮挡严重最常见的现象是同一个行人被反复分配新 ID也就是热搜里常说的“运动目标经过摄像头只识别一次”的反面。主要调下面几个参数参数作用典型调法max_dist外观余弦距离阈值相似外观目标多时调小到 0.1max_age静止轨迹保留帧数遮挡频繁调大到 60n_init确认轨迹前的最少匹配帧数误检多时调大到 5nn_budget特征库样本上限目标运动姿态变化快时调大到 150max_age大目标被遮挡更久也不会丢 ID但离开画面的框会晚一点消失n_init大会减少误检目标被标成正式 ID但起始阶段每个 ID 要等更多帧才显示。这几个参数要配合调整例如人群密集场景下同时调大max_age和n_init让 ID 更“懒”地建立和销毁。4.4 训练完的部署边界训练完的best.pt可以继续用 PyTorch 跑也可以转成 TensorRT 后部署到 RK3588 或 Jetson 这类边缘设备。但转引擎时要注意deepsort 的特征提取网络不一定在原来的工程里暴露了导出接口常见做法是检测器单独转 TensorRTdeepsort 留在 CPU 上跑这样整体帧率在边缘设备上才撑得住。这一步和本源码的主流程是解耦的动手前先确认手里的设备有没有足够的 NPU 资源。5. 用 result.csv 画损失函数曲线验证这次训练是否值得继续调yolov8 每次训练都会把逐 epoch 的损失写到runs/detect/train/results.csv字段包括train/box_loss、train/cls_loss、train/dfl_loss和对应的验证集指标。很多人训练完只看最后的 mAP不画曲线结果分不清是高方差过拟合还是欠拟合。画曲线脚本很简单import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/detect/train/results.csv) df.columns [c.strip() for c in df.columns] plt.figure(figsize(8, 4)) plt.plot(df[epoch], df[train/box_loss], labelbox_loss) plt.plot(df[epoch], df[train/cls_loss], labelcls_loss) plt.plot(df[epoch], df[train/dfl_loss], labeldfl_loss) plt.plot(df[epoch], df[val/box_loss], labelval_box_loss) plt.legend() plt.savefig(loss_curve.png, dpi160) print(曲线已保存到 loss_curve.png)参数说明df.columns [c.strip()...]是清零列名里的前后空格因为 ultralytics 生成的 csv 列名带空格直接取列会报 KeyError。val/box_loss是验证集框回归损失它比训练损失更能反映泛化能力。看曲线时按三条线判断box_loss 持续下降说明定位更准cls_loss 震荡说明学习率偏高或数据标注噪声大dfl_loss 是 anchor-free 的分布聚焦损失和框回归的分布单调性有关长期不降就要检查训练集大小。如果 100 轮后 box_loss 还在下降可以加大 epochs 继续训如果训练损失降到很低但验证损失反弹说明过拟合回去补数据或加数据增强。跟踪效果的验证和训练曲线要结合起来看把训练后的 best.pt 换回去跑同一段 demo.gif对比调参前后输出 txt 里的 ID 总数和切换次数。同样的目标数量下ID 总数越接近真实目标数越好ID 切换次数明显下降说明检测器稳定度提升了。把 loss_curve.png 和 mot 输出 txt 放在同一个目录下训练收敛情况和跟踪跳变情况就能对起来看。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询