YOLOv5行人车辆检测跟踪计数系统:从环境配置到部署实战

发布时间:2026/9/10 5:44:41
YOLOv5行人车辆检测跟踪计数系统:从环境配置到部署实战 简介基于YOLOv5与DeepSORT的行人车辆检测跟踪计数系统源码面向计算机视觉学习者、算法工程师及智能交通应用开发者。系统实现南/北方向进出双向计数可根据场景在main.py中调整多边形检测区域适配不同监控视角默认支持行人、自行车、小汽车、摩托车、公交车、卡车六类目标检测与跟踪计数。压缩包共78个文件以Python脚本为主包含模型定义、检测器、追踪器、工具函数及配置文件另有yaml模型结构、xml工程配置、shell脚本、预训练权重、测试视频等整体大小约82.72MB。目录划分清晰便于按模块查阅与二次开发环境依赖与启动脚本均有提供可快速搭建运行。已有631人学习使用。资源附带了预训练权重与示例视频可快速运行体验也适合研究YOLOv5DeepSORT的工程化实现理解目标检测与多目标跟踪的协同流程为课程设计或实际项目提供完整参考。1. 这个行人车辆检测计数系统拿来能做什么拿到一份《基于YOLOv5行人车辆跟踪检测识别计数系统源码.zip》不少人第一反应是打开README却忽略了一个事实真正值钱的不是那一串权重文件而是它在同一份工程里把“检测、跟踪、计数”三层串成了一个可交付的视觉方案。检测解决“是什么在哪”跟踪解决“哪一帧跟哪一帧是同一个目标”计数解决“目标从哪来、进没进去、走了几条”。这套结构放到道路卡口、园区安防、商超客流、课堂考勤里都能复用区别只换数据集和落线逻辑。这篇内容不替你讲解压包过程而是把这份源码会遇到的“环境依赖、检测头输出、跟踪策略、自训数据集、线计数实现”逐层拆开。适合三类人拿它做毕设模块的学生需要快速出 demo 的工程师以及想把现有检测模型升级成计数服务的团队。2. YOLOv5环境配置与源码包结构先摸清这张“地图”2.1 YOLOv5环境配置先复现“torch.cuda.is_available() 为 True”所有的后续步骤都建立在环境这一关通过的前提下。跑这套系统标准配置是 Python 3.8、PyTorch 1.8、CUDA 11.x显卡不挑型号只要显存高于 6G 就能跑得动默认输入尺寸。建议用 venv 或 conda 隔离依赖避免覆盖系统里的其他项目环境。创建干净环境后按以下顺序安装比直接pip install -r requirements.txt更容易定位缺失conda create -n yolov5 python3.8 -y conda activate yolov5 pip install torch1.10.0 torchvision0.11.0 --extra-index-url https://download.pytorch.org/whl/cu113 pip install -r requirements.txt第一行创建独立环境第三行把 PyTorch 系装好这里指定cu113是为了跟本机 CUDA 驱动匹配再执行最后一行的通用依赖安装requirements 里包含 opencv-python、pandas、seaborn、matplotlib 等主要用于推理时的图像处理和结果可视化。安装完成后用三行代码做自检这一步最好保持常态换机器就重跑一次import torch print(torch.__version__) print(torch.cuda.is_available())如果输出True环境通过如果False优先检查显卡驱动版本和 PyTorch 对应 CUDA 版本是否匹配。注意驱动版本与 CUDA Toolkit 版本不同前者向下兼容后者随 PyTorch wheel 打包两者对不上是is_available()返回False的头号原因。2.2 源码包目录结构models、utils、tracker 各管什么这份源码一般会在官方 YOLOv5 工程骨架上新增一个跟踪与计数模块。官方目录解决“识别”后加进来的目录解决“跟踪和计数”。常见布局如下├── models/ # 网络结构定义与 yaml 配置 │ ├── common.py │ ├── yolo.py │ └── yolov5s.yaml ├── utils/ # 训练工具、指标计算、损失函数 │ ├── datasets.py │ ├── loss.py │ └── metrics.py ├── tracker/ # 新增行人车辆跟踪器 │ ├── track.py │ └── matching.py ├── detect.py # 纯检测入口 ├── track.py # 新增跟踪检测统一入口 ├── count.py # 新增人车计数逻辑 ├── runs/ # 训练/推理结果输出目录 │ ├── detect/ │ └── track/models/yolov5s.yaml定义的是网络骨架改动它等于改模型结构utils/loss.py包含分类损失、置信度损失、定位损失的计算方式多数源码包不会让你改这里而tracker/track.py和count.py是这份源码与官方版本拉开差距的部分后文会具体说明。2.3 跑通自带权重不训练也能先看效果拿到源码先跑一次预训练模型验证环境与依赖没有问题再开始后续改动。执行命令python detect.py --weights yolov5s.pt --source data/images/bus.jpg --conf-thres 0.5--weights指定权重文件--source可以接图片、视频、摄像头编号或 RTSP 地址--conf-thres控制置信度阈值低于该值的框会被过滤。如果输出runs/detect/exp/中能看到标注过的 bus.jpg说明检测链路已经贯通。提示绝大多数跟踪计数改版源码会在track.py中调用detect.py里的核心函数所以先把纯检测跑通再去看跟踪能避免“环境问题混在跟踪问题里”的假象。3. 检测与跟踪链路从 YOLOv5 网络结构到人车 ID 分配3.1 从 YOLOv5 网络结构看行人车辆为什么用同一模型YOLOv5 的网络结构由三块组成Backbone 负责提特征Neck 负责多尺度融合Head 负责输出预测框。对行人车辆这个场景用同一个模型做二分类而不是训练两个单独模型最主要的理由是两个类别存在共现样本比如车辆旁边站着人同一个特征层能同时保留两类目标的语义信息且推理只需一次前向计算耗时不会随类别数线性增长。在源码的models/yolov5s.yaml里nc: 2就是本项目的关键配置nc: 2 # number of classes depth_multiple: 0.33 width_multiple: 0.50 anchors: - [10,13, 16,30, 33,23]nc改成 2Head 的输出通道会自动适配每个 anchor 的预测张量为[x, y, w, h, obj_conf, cls1, cls2]其中obj_conf表示该位置是否存在目标的概率。这也是为什么自训数据集时第一件事就是改 nc——不是所有类别的目标都物尽其用地被检测到但漏改类别名会导致训练直接报错或指标失真。3.2 跟踪链路从 detect 到 track 的类切换纯检测输出是“这一帧有什么”跟踪需要回答“上一帧的那个目标这一帧在哪个位置”。常见做法是选用 SORT 或 DeepSORT 思路用卡尔曼滤波预测目标下一帧位置再用 IOU 匹配完成当前帧与上一帧轨迹的关联。精简版源码一般会省掉外观特征提取用纯 IOU 匹配在车辆行人这种运动相对平滑的场景下效果足够速度也快。python track.py --source test.mp4 --classes 0 1 --tracking-method iou--classes 0 1表示只对行人COCO 中的 class 0和车辆COCO 中的 class 2进行跟踪--tracking-method iou选择纯 IOU 跟踪策略。更换跟踪方法时注意源码是否重写了update函数很多改版在tracker/track.py里定义了Track类class Track: def __init__(self, bbox, cls, conf, track_id): self.bbox bbox # 格式: [x1, y1, x2, y2] self.cls cls # 0person, 1car self.conf conf self.track_id track_id self.history [] # 历史位置用于轨迹绘制 self.lost 0 # 连续未匹配帧数这个类约定了跟踪结果的数据结构后续线计数、区域计数都直接操作track_id和bbox。如果跟踪连续丢帧看两个值lost达到阈值后轨迹会被清理max_age决定了目标离开画面后轨迹能存活多久调大能减少计数分裂但会引入跟踪漂移。3.3 摄像头与 RTSP 流接入的实时性差异本地视频跑通后切换 RTSP 流是落地到实际场景的关键步骤python track.py --source rtsp://user:pass192.168.1.64:554/stream1 --img-size 640 --conf-thres 0.4这里--source接的是摄像头 RTSP 地址--img-size控制输入尺寸640 是精度与速度的平衡点。换成实际监控流时需要注意两个容易被忽略的问题一是 RTSP 地址里的特殊字符比如密码中的和:必须做 URL 编码否则解析失败二是视频流的帧率不稳会导致跟踪器lost值被误加频繁出现“一个目标断开成两个 ID”的现象解决思路是限制读取帧率而不是让跟踪器去适应环境。4. YOLOv5 训练自己的数据集人车两类的标注与训练4.1 标注格式与数据集目录组织要让这个系统变成“你的”需要把默认 COCO 权重替换成自训练权重并把标注转成 YOLO 格式。YOLO 标注的核心是每张图片对应一个.txt文件文件名与图片同名每一行代表一个目标cls x_center y_center width height注意这四个坐标值用 0 到 1 的归一化浮点数表示不是像素坐标。举例来说一张 1920×1080 的图中行人框在像素位置(600, 300, 800, 700)转换公式是x_center (600 800)/2 / 1920 0.3646 y_center (300 700)/2 / 1080 0.4630 width (800 - 600) / 1920 0.1042 height (700 - 300) / 1080 0.3704对应的标注文件内容为0 0.3646 0.4630 0.1042 0.3704。使用 LabelImg 或 labelme 导出 YOLO 格式时要注意统一勾选“自动保存”否则漏掉标注批次训练时会出现“No labels found”的报错。整个数据集的目录结构需要跟datasets.py的默认读取逻辑匹配dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml4.2 修改 yaml 设定行人车辆类别名data.yaml是训练时的数据入口它告诉 YOLOv5 从哪里读图和标注以及类别列表train: dataset/images/train val: dataset/images/val nc: 2 names: [person, car]names的顺序必须与标注文件里的cls数字一一对应——标注里0表示 person、1表示 car如果写反了训练的损失会下降但检测结果完全错乱。检查类别是否映射正确可以在训练前执行python train.py --data dataset/data.yaml --weights yolov5s.pt --epochs 100 --batch-size 16 --img 640训练早期日志会打印类别分布确认每个类别的样本量差异不过大。如果 person 样本数是 car 的十倍--bce损失会出现类别倾向需要参考utils/loss.py中的类别权重参数做调整但这属于进阶优化先跑通再回头改。4.3 关键超参数怎么设epochs、batch-size、patience自训练数据集通常在几千到几万张以下参数组合是常用起点参数推荐值说明--img640输入分辨率行人小目标多可上调到 960 换取精度--batch-size16显存不够时降为 8梯度累积可抵消--epochs100小数据集用 200便于观察后续 loss 收敛曲线--patience30连续 30 个 epoch 未提升则自动停止--weightsyolov5s.pt推荐使用预训练权重做迁移学习不建议从零训练--hypdata/hyps/hyp.scratch-low.yaml低增强配置数据量偏少时更稳定patience是早停机制它依赖验证集 mAP 作为监控指标连续多次不上升就终止训练并保留最优权重。如果发现训练时间异常长且 loss 不降排查方向是学习率预热是否正常启动、backbone 层是否被冻结。默认配置中冻结前三层需要全量微调时可在train.py中修改freeze参数。4.4 训练完成后的模型评估mAP 与混淆矩阵训练结束后runs/train/exp/目录下的results.png和confusion_matrix.png是判断质量的关键文件。results.png包含mAP_0.5和mAP_0.5:0.95两条曲线前者判断检测框定位是否准确后者更严格同时考察框的回归精度。如果mAP_0.5高但mAP_0.5:0.95低说明模型对目标位置敏感边界仍有抖动。评估命令python val.py --weights runs/train/exp/weights/best.pt --data dataset/data.yaml --img 640 --conf-thres 0.4 --iou-thres 0.5--iou-thres 0.5是 NMS 时的 IOU 阈值。当前帧里两个框高度重叠时iou-thres决定哪个框被抑制。人车密集场景下这个值过大会抹掉邻近目标过小会出现大量重复框常用区间在 0.45 到 0.6 之间。提示训练完成后不要直接看last.pt它在最后几个 epoch 可能出现过拟合。best.pt是按验证集 mAP 最优保存的权重应作为后续跟踪计数的唯一推理权重。5. 计数逻辑与业务接入从轨迹到人流车流的统计链路5.1 三类计数参考点、线、区域的差异计数系统的核心在于“什么时候把 track_id 算进总数”。差异在于选择参考空间。点计数最简单检测到目标即加一适合出入口闸机线计数最常用目标跨过一条虚拟线产生一次计数区域计数统计某区域内的实时数量适合“当前停车场还剩多少车位”这类场景。线计数实现时在线两侧各留一个状态缓存目标侧向切换则计数增加。参考count.py中的核心逻辑类似def count_crossing(track, line_y, prev_pos, count): # prev_pos: {track_id: in|out}, 记录每个 ID 上一帧在线哪一侧 current_y (track.bbox[1] track.bbox[3]) / 2 # 取框中心 side in if current_y line_y else out if track.track_id in prev_pos and prev_pos[track.track_id] ! side: if side in: count[in] 1 else: count[out] 1 prev_pos[track.track_id] sideline_y是画面上虚拟线的 y 坐标在代码中通常以帧高度的百分比表示方便适应不同分辨率。第 3 行用 bbox 中心点而非底部点做判据是因为行人底部点受遮挡影响比中心点更明显。5.2 轨迹 ID 维持跨帧数据如何保证不重不漏计数准确率的上限由跟踪 ID 稳定性决定。同一个行人跨越计数线时被赋予不同 ID会出现重复计数这是最常见的误差来源。ID 跳变原因一般有三类目标被遮挡超过max_age导致轨迹删除目标速度突然变化导致卡尔曼预测偏离 IOU 阈值检测器漏检一帧导致轨迹暂时丢失。三个实用调整方向调高tracker/track.py里max_age到 30 或 50允许目标短暂消失后重新关联将min_hits调为 3避免单帧误检产生轨迹导致“被检测到一帧就计数一次”在当前帧与前一帧中间插入“位置预测二次匹配”的级联策略在高密度场景下能有效降低 ID Switch 次数。用真实视频验证时建议先在画面上叠加绘制每个 ID 的移动轨迹线观察目标在遮挡前后是否保持同一数字。如果 ID 变化频繁“计数总次数正确”只是偶然不能说明跟踪模块可用。5.3 计数结果对外输出SQL 落库与实时接口落地的计数服务需要把帧级统计结果变成业务数据。常见做法是开一个 REST 接口每隔固定时间推送各目标坐标与累计计数from flask import Flask, jsonify app Flask(__name__) # count_data 由 count.py 持续更新 app.route(/api/counts) def get_counts(): return jsonify({ in_count: count_data[in], out_count: count_data[out], current_in_area: count_data[area], timestamp: datetime.now().isoformat() }) if __name__ __main__: app.run(host0.0.0.0, port8080)/api/counts返回 JSON 格式的计数快照适合前端轮询或写入时序数据库。另一个常见做法是把计数结果直接写入 SQLite适合离线视频批量统计sqlite3 counts.db CREATE TABLE IF NOT EXISTS stats(id INTEGER PRIMARY KEY, ts DATETIME, dir TEXT, cnt INT); sqlite3 counts.db INSERT INTO stats(ts, dir, cnt) VALUES(datetime(now), in, 12);两条命令展示了表结构与插入方式。注意视频场景中的时间戳不应使用datetime(now)——它记录的是处理时间视频回放或加速处理时会失真。应使用视频帧的时间码或从视频元数据中提取真实时间。6. 部署与优化从 PyTorch 权重到边缘端推理6.1 导出 ONNX 与 FP16 构建脚本的设置项把训练好的best.pt转到推理阶段第一个常用操作是导出 ONNXpython export.py --weights runs/train/exp/weights/best.pt --include onnx --img 640 640--include onnx指定导出格式导出后可用onnxruntime或 TensorRT 加载。FP16 优化是边缘部署的标配在 TensorRT 环境中执行转换时开启--fp16模型体积约减半速度提升 1.5 到 2 倍精度损失通常低于 1%。对比参考格式体积相对CPU 推理速度可用框架PyTorch.pt1.0慢PyTorchONNX约 0.9中等onnxruntime、OpenCV DNNTensorRT FP16约 0.5快TensorRT、DeepStream设置--img 640 640时要与训练时的输入尺寸保持一致输入尺寸跨分辨率会对目标框位置产生尺度偏移输出坐标需要额外做 rescale 处理不如直接固定。6.2 在边缘端跑推理的三个取舍嵌入式设备跑 YOLOv5 需要明确取舍项分辨率、batch、后处理。分辨率从 640 降到 416 能换约 40% 的帧率提升但小目标检测召回明显下降适合“只关心车辆不关心行人”的场景batch 在视频流场景中固定为 1单张推理时优化重点应从模型结构转向 NMS 实现。后端推理源码调整# 将非极大值抑制替换为 Fast NMS减少 CPU/GPU 同步等待 def fast_nms(boxes, scores, iou_thres0.5): # 按置信度降序排序逐类剔除此前最优框的高重叠框 ...Fast NMS 是众多性能优化中收益最高的一个改动如果场景并发路数多还可以考虑 GPU 上直接完成 NMS避免每帧将候选框 copy 到 CPU。6.3 三个容易被当成 bug 的隐藏点输入尺寸不一致导致的框偏移训练用 960验证和导出用 640测得的 mAP 比训练日志低一截这不是模型退化而是尺度扰动。统一所有管线中的--img参数再看结果。分类阈值从训练到推理不一致训练时conf_thres设为 0.1 是为了回传更多梯度信息推理时设为 0.5 是为了减少误检两者职责不同不要用训练日志的混淆矩阵数值直接衡量线上效果。画面比例不匹配导致计数虚高imgsz固定为正方形后横向视频会被压扁行人宽高比失真。框中心线坐标越接近计数线压扁造成的中心点漂移越容易误触发计数。应在预处理时按原比例缩放后补边而不是直接拉伸。计数系统的最终验收不应只看 mAP 或帧率要拿一段带遮挡、不同光照的真实录像跑一遍统计“人工数出的过线人数”和“系统计出的过线人数”的绝对值误差。能稳定控制在 3% 以内这套源码才算真正在“识别”之上完成了“跟踪与计数”的闭环。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

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

尧图内容编辑团队

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

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

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

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

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

网站改版的5个关键决策

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

获取专属建站方案

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

立即免费咨询