拓冰建站拓冰建站
首页 / 资讯中心 / 正文

PyTorch实现YOLOV5+SORT车辆行人目标识别追踪系统全解析

简介这是一套面向计算机视觉初学者与课程设计者的实战型目标检测与多目标追踪系统源码基于PyTorch框架融合YOLOv5目标检测模型与SORT算法实现对视频流中车辆与行人目标的实时识别、定位与ID持续追踪。资源适用于本科毕业设计、人工智能课程大作业及智能交通方向实践项目无需调参即可快速部署运行。压缩包共101个文件含42个核心Python脚本涵盖数据预处理、模型加载、追踪逻辑与可视化、51个编译后pyc文件、2个配置yaml、1个预训练模型pt文件yolov5m.pt、1张示例图像train.jpg及README.md说明文档整体体积79.92MB结构清晰、模块解耦便于理解YOLOv5推理流程与SORT卡尔曼滤波匈牙利匹配的追踪机制。目前已有1549人学习下载配套完整且开箱即用显著降低复现门槛。 先说结论这套“基于PyTorch实现的YOLOV5SORT车辆行人目标识别及追踪系统”核心思路就是“检测跟踪”两段式。YOLOV5负责在每一帧图像里找出车辆和行人SORT负责把这些目标跨帧关联起来给每个目标一个稳定ID最后形成一个带框、带编号、可统计数量的完整追踪结果。适合刚入门目标检测想进一步做多目标追踪的人也适合要做交通流量统计、安防巡检这类小项目但不想从零搭算法的朋友。拿到这类工程我建议第一件事不是着急跑demo而是先把目录结构、数据流、检测模块和追踪模块之间的接口读明白这一步做透了后面再改功能会轻松很多。1. 项目整体设计与核心思路1.1 这套系统到底解决了什么问题做视频分析的人应该都有体会单帧检测只能告诉你“这一帧里有什么”但放到视频场景里业务方往往想知道“这个目标从哪来到哪去”“这个路口一小时过了多少车”“这个人有没有反复出现在同一个区域”。这些需求单靠目标检测没法满足必须引入追踪。这个项目就是干这件事的。它的输入是一段视频或者摄像头画面输出是每一帧中被检测出来的车辆、行人边界框以及每个目标对应的唯一ID。如果你愿意加几行统计代码还能轻松输出“当前画面内有N辆车、M个人”这类信息。放在实际业务里最常见的三个使用场景是一类是交通路口统计车流量、判定是否拥堵第二类是园区和校园安防识别行人和车辆动向做轨迹回溯第三类是算法演示和实验教学作为“检测追踪”的入门模板。无论哪种场景这套组合都比单独做检测要更接近真实业务需求。1.2 方案选型为什么是YOLOV5加上SORT这个问题我经常被问到。目标追踪领域方案其实很多有以检测为基础的TBD范式Tracking-by-Detection也有联合检测与跟踪的端到端范式。对于大多数工程应用来说TBD范式仍然是稳定又灵活的选择而YOLOV5SORT正是这种范式里最经典的组合。先说检测器为什么选YOLOV5。相比两阶段的Faster R-CNN系列YOLO系列把“候选区域生成”和“分类回归”统一到一个网络里推理速度有数量级优势。而对比同时期的EfficientDet、SSD等YOLOV5在工程上最大的价值是生态成熟官方仓库提供了数据增强、超参数进化、模型导出、TensorRT部署等一整套脚本社区资料也异常丰富。对你做二次开发来说遇到问题能搜到答案比模型自己刷高0.5个点更重要。再来说SORT。SORT是Simple Online and Realtime Tracking的缩写它最大的特点是简单和快。它只用卡尔曼滤波预测目标位置再用匈牙利算法做检测框与轨迹之间的匹配整个过程不提取任何外观特征所以CPU上也能跑得动。相比之下DeepSORT增加了ReID外观特征分支在遮挡场景下表现更好但代价是更复杂的依赖和更高的计算量。如果你要处理的是车辆这类刚性目标SORT完全够用如果做密集行人场景我会建议后续再升级到DeepSORT或者ByteTrack。1.3 源码目录结构应该怎么读这类工程解压后一般会看到如下结构我强烈建议你先建立整体印象再动手改代码。一般会有models/存放YOLOV5的模型定义和模块组件utils/里是数据处理、损失函数、增强逻辑等工具代码datasets/或data/用于组织训练数据与数据集配置文件tracker/里是SORT核心代码而根目录下的detect.py、train.py、track.py分别是推理、训练、追踪三个入口。我第一次拿到类似项目时犯过“一上来就打开model文件逐行看”的错误结果越看越晕。正确顺序应该是先跑通track.py或者detect.py用现成权重看效果再沿着“入口→检测→追踪→画框”这条主链路去读代码。等你对数据流有了直觉再看那些网络结构细节完全是顺水推舟的事情。2. 核心原理拆解检测与追踪是怎么配合的2.1 YOLOV5检测器的工作过程YOLOV5本质上是一个单阶段卷积神经网络它把一张图切成固定数量的网格区域每个网格负责预测中心点落在该区域的多个候选目标框。具体来说网络的骨干网络是CSPDarknet它通过跨阶段局部连接减少重复梯度计算让模型在参数量不大的情况下保持较高特征提取能力颈部网络是PANet结构能把不同尺度的特征充分融合让小目标信息和大目标语义信息都能得到有效表达。输入图像经过网络后会输出三个不同尺度的特征图分别对应小、中、大三种目标尺寸。每个位置会预测若干预置锚框的偏移量、目标置信度以及类别概率。举个例子如果原图是640×640输出特征图可能是80×80、40×40、20×20三组每一组每个位置都有3个锚框所以预测结果数量非常大。这些原始输出必须经过NMS非极大值抑制去掉冗余框只保留置信度高且不重叠的检测框最终才能交给追踪模块。很多刚接触代码的人看YOLOV5的Detect层源码会很困惑因为那里既有anchor生成又有解码逻辑。其实核心就一件事把网络预测的偏移量换算成真实图像坐标的候选框。这个解码过程在PyTorch里可以用纯张量运算完成不需要循环遍历每个网格这也是很多人第一次看PyTorch代码时觉得“明明能写循环却偏要写成矩阵”的原因。2.2 SORT追踪器的两个核心部件SORT算法为什么能稳定跨帧追踪目标主要靠两个部分卡尔曼滤波和匈牙利匹配。先看卡尔曼滤波。它的作用是预测目标在当前帧的位置并且能在检测器偶尔漏检时提供一个过渡位置维持轨迹不立即断裂。你完全可以把卡尔曼滤波理解成一种“带置信度的平滑预测器”。它维护每个目标的状态向量通常是[cx, cy, s, r, vx, vy, vs]这种形式对应中心坐标、面积、宽高比以及它们的变化速度。新的检测结果进来后卡尔曼滤波会同时考虑上一帧的预测和当前的测量值得到一个更平滑的估计。车辆在视频中移动相对规律所以卡尔曼滤波的效果非常好行人因为姿态变化大、运动轨迹任意偶尔会追丢这也是算法的固有特点。再说匈牙利匹配。它的任务是把“当前帧检测到的框”和“已有的轨迹预测框”做最优配对匹配代价用的是IOU距离即检测框和预测框的交并比越小代价越大。SORT在这里还会对不满足阈值条件的匹配直接拒绝宁可让轨迹暂时失配也不愿强行绑定到错误目标上。那些连续多帧失配的轨迹会被删除而连续多帧存在的新检测框则会被注册成新轨迹。这套逻辑听着简单实际运行起来非常稳健。默认参数下SORT只需要几十毫秒就能完成一帧所有目标的匹配在CPU上都能轻松跑到实时。这也是我推荐初学者从SORT入手的原因——你能很清楚地看到每行代码在“预测、匹配、更新、注册、删除”这五个环节里分别做了什么。2.3 检测和追踪如何串成一条完整管线把YOLOV5和SORT串起来最核心的是约定好模块之间的数据接口。整套流程是这样的第一步读入一帧图像经过YOLOV5得到检测框列表每个框包含四个坐标值、一个置信度和一个类别ID。第二步将检测框坐标转换为SORT需要的格式一般是[x1, y1, x2, y2, conf, cls]或者[x1, y1, x2, y2, conf]。第三步调用SORT的update()方法传入当前帧的检测框信息得到跟踪结果。第四步把跟踪结果和原始帧合成绘制边界框和ID。这里有个容易踩坑的细节SORT本身是不区分类别的。如果你同时检测“车”和“人”同一个ID很有可能会先分配给一辆车再因为匹配失误跳到一个行人身上。所以我建议在实际项目中要么对不同类别分别维护一个SORT实例要么在传入SORT之前先把类别信息过滤出来按类别分组追踪。这个做法代码改动不大但能显著提升追踪质量。3. 实战环境搭建、数据准备与代码运行3.1 PyTorch环境搭建与版本匹配这个项目跑起来的第一步就是环境也是很多人最容易卡住的地方。我建议用conda创建独立环境避免和系统其他项目互相污染。创建环境并安装PyTorch命令如下conda create -n yolov5_sort python3.9 conda activate yolov5_sort pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118这里有一个老生常谈但每次都会有人踩的坑PyTorch的CUDA版本必须和显卡驱动、CUDA Toolkit版本匹配否则检测到GPU但运行时报错。你不需要把驱动和PyTorch版本完全对齐只要保证显卡驱动足够新能支持对应的CUDA运行时版本即可。直接跑nvidia-smi看驱动支持的CUDA版本再选择不高于该版本的PyTorch安装命令。装完PyTorch后用python -c import torch; print(torch.cuda.is_available())验证输出True再继续否则后面训练速度会慢到让人怀疑人生。接下来安装YOLOV5依赖。建议不要一股脑装最新版本有些依赖版本过新反而会出问题pip install -r requirements.txt如果requirements里没有明确版本建议手动指定几个稳定版本numpy小于等于1.24.0、opencv-python用4.8.1、matplotlib用3.7.5。这几个是我反复测试后比较稳的组合能避免不少奇奇怪怪的兼容问题。3.2 数据集准备车辆和行人数据怎么组织要训练自己的车辆行人检测模型先得准备数据。公共数据集方面COCO数据集本身包含car、bus、person等类别可以直接按大类过滤如果想要更偏交通场景的数据可以看看BDD100K和UA-DETRAC。实际项目里我一般会建议“公共数据预训练少量自采数据微调”的组合这样既有通用性又能贴合实际部署场景。YOLOV5训练用的标注格式是txt文本每一行对应一个目标内容为“类别ID x_center y_center width height”注意这四个坐标值都是相对图像宽高的归一化比例。标注工具我推荐labelImg它可以直接导出YOLO格式新手操作起来门槛最低。标注完成后的数据集目录组织如下datasets/ ├── vehicle_person/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ └── labels/ │ ├── train/ │ └── val/这里特别提醒图像和标签必须位于同名目录下且文件名一一对应比如IMG_001.jpg对应IMG_001.txt。我第一次自己整理数据时把图片放在images/train、标签放在labels/train文件名对不上结果YOLOV5报“No labels found”排查了半小时才发现是自己图片和标注文件数量不一致。数据集配置文件也要自己写一个yaml内容指向刚才的数据目录并声明类别。path: datasets/vehicle_person train: images/train val: images/val nc: 2 names: [vehicle, person]3.3 训练自定义模型的关键步骤数据准备好了接下来是训练。YOLOV5训练比较重要的是四个点网络规模选择、预训练权重、训练参数、超参数。网络规模我建议先用yolov5s它的体积小、速度快、显存占用低适合验证数据和训练流程是否跑通。等确认一切正常再换yolov5m或yolov5l提升精度。小模型跑通流程比大模型直接报错后到处排查要高效得多。训练命令示例如下python train.py --data vehicle_person.yaml --weights yolov5s.pt --img 640 --batch-size 16 --epochs 100这里的--img 640表示训练时输入尺寸为640这个值越大精度越高但显存占用和推理时间都会增加。--batch-size受显存限制如果只有8G显存且要用yolov5s建议8或者4。--epochs早期验证用50-100即可最终模型可以调到200以上。训练过程中要注意观察两个指标一个是P精确率和R召回率另一个是mAP0.5和mAP0.5:0.95。只看loss降下去不一定是好事有可能过拟合一定要结合验证集mAP判断。模型训练完成后权重保存在runs/train/exp/weights/best.pt后续推理和追踪都用这个best.pt。3.4 把检测结果接入SORT追踪器训练好模型后追踪系统的核心就是把检测结果喂给SORT。这里我直接给一段最简化的接入代码它表达的是逻辑主链路。import torch from tracker.sort import Sort from models.experimental import attempt_load from utils.general import non_max_suppression model attempt_load(runs/train/exp/weights/best.pt, map_locationcpu) model.eval() # 车辆和行人分开追踪避免ID交叉 sort_dict { vehicle: Sort(max_age30, min_hits3, iou_threshold0.3), person: Sort(max_age30, min_hits3, iou_threshold0.3), } for frame in video_frames: results model(frame)[0] dets non_max_suppression(results, conf_thres0.4, iou_thres0.4)[0] for cls_name in sort_dict.keys(): cls_id NAMES.index(cls_name) mask_cls dets[:, 5] cls_id cls_dets dets[mask_cls][:, :5].cpu().numpy() if len(cls_dets) 0: continue tracked sort_dict[cls_name].update(cls_dets) for track in tracked: x1, y1, x2, y2, track_id track # 这里可以画框、写ID、做计数统计这段代码里最关键的一行是sort_dict按类别维护了独立的SORT实例不同类别之间互不干扰。效果上车辆、行人的ID号段天然分开计数时也直接按类别汇总省掉了后续过滤的麻烦。SORT里还有三个参数值得单独说明。max_age表示轨迹最多失配多少帧后删除值越大越能容忍检测器短暂漏检但太大也容易造成轨迹残留min_hits表示一个新目标连续匹配多少帧后才被认为是稳定轨迹值越大越能过滤误检但太小的话偶尔出现的虚假检测也会被立即赋IDiou_threshold是匹配时的IOU下限。这三个参数在不同场景下需要微调下面的优化部分我会展开讲。4. 参数调节与效果优化心得4.1 检测环节的关键超参数怎么调追踪效果好不好一半取决于检测器输出质量所以参数调节要从检测环节开始。conf-thres是最影响体验的参数。它控制检测框的最低置信度。如果视频里目标比较多而且密集建议调到0.3-0.4能保证召回率如果场景相对干净可以调到0.5以上减少误报。我最开始图省事把置信度调到0.25结果车辆周围的一堆背景区域被框了出来SORT给那些误检框也分配了ID追踪结果惨不忍睹。iou-thres是NMS的IOU阈值默认0.4-0.45。这个值调整对车辆这种大目标影响不大但对密集行人特别关键。行人之间重叠严重时NMS阈值太小会把真正不同的行人框合并成一个追踪时就变成两个目标来回抢一个ID。我处理密集人群时一般会把NMS阈值放到0.5左右。输入分辨率对效果影响也很大。训练和推理尺寸保持一致很重要如果训练时用640推理时用1280模型可能会产生大量漏检。如果你部署设备支持建议把推理分辨率提高到768或者896对远处小目标效果提升非常明显。4.2 SORT追踪参数在各场景下的调优SORT参数不是越大越好也不是越小越好需要根据场景特性来判断。车辆场景相对简单车辆运动比较平滑、外形变化小卡尔曼滤波预测会很准确。这种情况下max_age可以设置得大一些比如50到80因为哪怕车辆被临时遮挡几帧预测位置也能大体跟得上轨迹不容易断。min_hits可以保持默认的3因为车辆检测框稳定很少出现闪烁误检。行人场景要复杂得多。行人形变剧烈、运动方向随意、互相遮挡频繁卡尔曼滤波的线性运动假设经常失效。如果max_age太大轨迹可能会“粘”在错误的目标上如果min_hits太小行人刚出现就被分配ID后面ID会频繁跳变。我的经验值是行人场景下max_age取20到40min_hits取2到5iou_threshold取0.3比较合适。还有一个容易被忽略的点视频帧率。如果是30fps的视频相邻帧目标位移小SORT很好匹配如果是10fps的视频目标每帧位移很大检测框和预测框的IOU可能直接归零轨迹会频繁断裂。这种低帧率场景下要么把视频插帧要么调整跟踪框架要么缩短检测间隔。我一般会建议客户在采集端保证15fps以上否则SORT效果大打折扣。4.3 性能瓶颈分析与整体加速思路追踪系统的耗时大头基本都在检测器上SORT本身几乎不占资源。如果用YOLOV5s在GPU上推理单帧耗时大概10到20毫秒SORT更新一帧可能只需要1到3毫秒画框等IO操作看具体实现。因此要加速最优先的是检测环节。最直接的做法是使用半精度推理。在GPU上给模型套一层torch.cuda.amp.autocast()推理速度能提升30%左右显存占用也少很多。前提是你的显卡支持FP16计算。第二个做法是减小输入分辨率。从1920×1080降采样到960×540速度提升不止两倍但小目标检测率也会下降。这个需要根据你的目标尺寸来权衡不能盲目降。再往后就是模型导出到TensorRT或者ONNX。将YOLOV5s导出为TensorRT FP16引擎后在Jetson这类嵌入式平台上推理速度甚至可以再翻倍。导出命令很简单python export.py --weights best.pt --include engine --device 0但这里提醒一句导出后如果换了PyTorch版本或CUDA版本可能需要重新导出不然会有兼容问题。如果只是跑demo不必这么折腾原版PyTorch推理完全够用。5. 常见问题与排查技巧记录5.1 训练阶段典型问题训练时最常遇到的错误是CUDA Out of Memory。原因不是显存不够就是你加了过大的--batch-size或者输入分辨率。解决方案是先把batch调到2跑通一个batch后再逐步上调。如果2都跑不过多半是模型选大了或输入分辨率太高。第二个高频问题就是标签报错。运行训练命令后提示No labels found in ...大概率是数据目录组织不对或者标签文件为空。我排查这类问题时习惯先打开一个标签文件看看内容是不是数字坐标再用python -c检查图像与标签文件名一一对应关系。第三个问题是训练loss异常。如果loss一开始就非常小先怀疑是不是数据增强没生效如果训练后期loss振荡明显可能是学习率太高或batch过小。YOLOV5默认的--hyp参数适普性好但不代表万能数据量特别多或特别少时都得手动调节。5.2 追踪阶段典型问题追踪最让人头疼的问题是ID跳变。目标明明在画面里一直走ID却从3跳到17再到25。出现这种情况要么是检测器漏检导致SORT轨迹断裂重建要么是检测框抖动导致IOU匹配不稳定。排查时先看检测器的稳定性如果连续帧同一目标检测框中心忽左忽右先调NMS和置信度如果检测结果是稳定的但ID还是跳就适当增大max_age让轨迹有更长的失配缓冲期。另一个典型问题是计数不准确。车辆进入画面后被反复计数原因是目标轨迹忽断忽续。SORT里max_age设置得太小时轨迹只要一帧没匹配到就会删除下一帧重新注册成新目标导致重复计数。把min_hits调大让轨迹先稳定几帧再注册会好很多。还有一类问题是检测框和ID的绘制结果闪烁、上下抖动。这往往是检测框本身的抖动不是追踪的问题。可以在画框前对跟踪框做一下简单的指数平滑或者把卡尔曼滤波的预测值直接作为绘制坐标而非直接用原始检测坐标。5.3 环境与运行问题速查表问题现象可能原因解决方案运行train.py报CUDA错误PyTorch CUDA版本与驱动不匹配安装与驱动匹配的PyTorch版本验证torch.cuda.is_available()检测时卡在import cv2opencv版本不兼容降级opencv-python到4.8.x运行后找不到模型文件路径配置错误或未下载预训练权确认权重路径与代码中默认路径一致SORT追踪ID反复跳变检测框抖动或max_age过小先调检测参数再适当调大max_age目标跑到画面边缘被切断图像边缘检测目标被截断推理前做边缘padding或忽略边缘目标推理速度过慢模型过大或分辨率过高换yolov5s、降分辨率、开半精度这张表是我踩坑记录里最常用的部分。你可以把它当作初始排查手册大多数运行问题都能在上面找到方向。6. 一点实操体会与后续扩展想法这套项目我跑了不止一次每跑一次都会发现新问题。印象最深的是第一次直接把SORT接到检测输出上没有分类别结果画面里一辆车和一个行人互相交错时ID瞬间互换了。那次之后我花了很大精力在“接口设计”上才意识到这类系统最关键的往往不是模型本身而是模块之间的约定。后续如果要在这个工程上继续扩展我建议按下面两条线走。第一条线是追踪算法升级把SORT换成ByteTrack或DeepSORT显著改善行人遮挡和ID切换问题。第二条线是业务功能增强比如加上跨摄像头的目标ID重识别或者把车辆轨迹绘制到电子地图上做路径分析。这两条线都不需要改动检测器接口设计得好的话替换成本很低。最后再分享一个小技巧调试追踪系统时不要把目光局限在追踪算法本身要先在检测输出上标注“如果检测框正确再判断追踪是否合理”。检测器一旦漏检或误检后面再优秀的追踪算法也救不回来。先把检测质量提上去再来调SORT的匹配参数这条顺序我强烈建议执行。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门