基于YOLOv8的交通人群监测系统设计与边缘部署实践 简介本资源是一套完整的基于YOLOv8的交通人群监测系统实现方案面向深度学习初学者、计算机视觉课程设计与本科毕业设计学生解决交通场景下行人检测、计数与实时监控等核心问题适用于智能交通管理、公共安全预警等实际应用场景。压缩包共24个文件含3个核心Python脚本webcam_detect.py、image_detect.py、utils.py、1个训练好的best.pt模型、8张标注测试图png/jpg、1个Jupyter Notebook实验记录、requirements.txt依赖清单及readme.md项目说明文档整体大小25.56MB结构清晰覆盖数据加载、模型推理、结果可视化全流程。目前已有40人学习下载提供可直接运行的摄像头实时检测与静态图像批量处理能力并附带混淆矩阵、F1曲线等评估图表便于理解模型性能与调优方向。 先说项目结论这套“基于YOLOv8的交通人群监测”方案我在实际项目里完整跑通过从数据标注、模型训练、精度调优到边缘设备部署全链路走下来大概花了两周。如果你正准备用YOLOv8做类似的人群计数、人流密度预警、交通路口分析这类需求这篇博客应该能帮你少踩不少坑。交通人群监测和普通行人检测不太一样它是把目标检测算法用在真实交通场景里比如十字路口、公交站、地铁出入口、商场广场这些地方核心要解决的是“某个区域里到底有多少人、什么时候人流量超过阈值、人群是否出现拥堵或异常聚集”。这套东西在智慧城市项目里需求量很大交通信号灯配时优化要看路口行人流量地铁站需要实时预警防止踩踏商圈需要统计客流做运营决策。我在这套方案里选YOLOv8不是因为它“最新”而是因为它在一众开源检测模型里精度、速度、部署生态的平衡最稳。而且从数据标注到训练再到ONNX导出、RKNN转换整个工具链都是现成的不需要自己造轮子。下面我把整个设计和实操过程拆开讲每个环节都会说清楚“为什么这么做”以及“我踩过的坑”。1. 项目整体设计与核心需求拆解1.1 交通人群监测和普通行人检测到底差在哪你可能会觉得人群监测不就是行人检测加个计数吗实际做起来完全是两码事。普通行人检测数据集里人通常是画面主体数量少、尺度大、遮挡少。但交通场景的监控画面摄像头一般架在路口杆子或者建筑高处俯视角度下的人全是小目标一个1080P画面里挤几十上百人太正常了而且人挤人的时候遮挡非常严重。我把这个项目拆解成三个核心能力行人检测把画面里的每个行人用检测框框出来这是基础能力。人群计数统计检测框数量映射到实际场景后给出区域人群数量。密度评估基于检测结果进一步判断区域属于畅通、拥挤还是拥堵状态这个需要按实际场景面积和人数设计阈值。技术上还有一个容易被忽略的点交通场景里行人和骑行者骑自行车、电动车的人经常混在一起要不要区分我在项目里选择把“骑行中的人”单独作为一个类别。因为从交通管理的角度机动车和非机动车混行、行人乱穿马路是不同的安全事件分开统计对后续应用更有价值。1.2 为什么是YOLOv8而不是YOLOv5或RT-DETR先说结论YOLOv8在“精度不输、速度够快、部署链路最短”这三点上是最适合这个项目的。YOLOv8相比YOLOv5有几个关键结构变化。一个是Backbone里的C2f模块替代了C3模块它借鉴了ELAN网络的设计思路把输入特征分流后经过多个Bottleneck串联再把每层输出拼接起来。这样做的直接好处是梯度流更丰富网络变深了反而不容易梯度消失同样计算量下特征提取更充分。另一个变化是检测头从Anchor-Based换成了Anchor-Free解耦头。分类分支和回归分支分开走独立的卷积分支每个位置直接预测目标中心点到四条边的距离。没有Anchor的候选框预设了也就少调一个参数对密集小目标场景反而更友好。还有一个设计是TaskAlignedAssigner标签分配策略它按“分类得分预测和回归IOU的加权对齐度”来选正样本而不是简单按IOU阈值一刀切。在人群这种目标重叠严重的场景里这种分配方式能让回归分支学到更准确的边界。我也对比过RT-DETR那个模型精度确实高一截但在边缘设备上跑起来对算力要求高TensorRT和RKNN的适配也没YOLOv8成熟现阶段不划算。1.3 系统架构与数据流设计整个系统的数据流是这样的摄像头采集视频流 → 抽帧或直接解码 → YOLOv8模型推理得到检测框 → 后处理过滤计数 → 按规则判断人群状态 → 联动告警或展示。我把项目分成了四层数据层负责采集、标注、管理图片数据这部分看起来不起眼但决定了模型性能上限。模型层YOLOv8模型训练、评估、导出。推理层处理视频流、执行检测、做后处理逻辑、计数。应用层告警规则、可视化界面、数据上报。这样的分层有个好处每一层可以独立替换。比如数据层换数据集不影响推理层代码模型层将来升级成YOLOv11也不需要动应用层逻辑。在做项目的时候这种解耦能省掉后面大量返工时间。2. 数据准备与标注交通场景定制化数据的完整流程2.1 数据从哪来公开数据集与自采数据组合做交通人群监测数据不建议只依赖单一来源。公开数据集方面我主要用了三个VisDrone无人机视角有大量小目标行人和监控场景的俯视角度接近适合作为基础数据扩充。CrowdHuman密集行人数据集遮挡情况极其丰富是训练模型应对“人挤人”场面的关键数据。CityPersons城市街景行人数据集包含各种街道路口场景。公开数据集有一个麻烦标注类别和格式不统一。VisDrone的“pedestrian”和“people”需要合并成统一的person类CrowdHuman的标注是边界框全量标注但部分框重叠严重需要做重合度过滤。我处理这些数据花了三天左右比训练模型本身还久。如果要做真正落地的交通人群监测自采数据必不可少。方案是用手机或监控摄像头在几个核心场景采集视频再抽帧成图片。建议按不同时间段采集早高峰、晚高峰、平峰期、夜间、雨天这些场景会让模型泛化能力差很多。我自己的经验是自采数据至少要有2000到3000张高质量图片再配合公开数据集混着训。注意公开数据集的类别体系要和你最终需求对齐。如果公开数据里有“rider”类而你不需要直接舍弃如果你需要“rider”而公开数据没有对应类别就得自己标。我最后定了两个类别person和rider既满足交通场景需求也不会让分类任务过重。2.2 类别设计与数据清洗类别设计看起来简单其实很考究。如果只分一个“person”行人和骑行中的人就混在一起统计分析维度少。但如果分太细比如行人、骑自行车、骑电动车、骑摩托车类别间特征混淆会非常严重对标注量和数据量要求都剧增。我实测下来两个类别是最务实的person步行状态的人rider骑行状态下的人车辆类型不细分数据清洗要做的三件事第一是去重公开数据集和自采数据可能存在相似图片用感知哈希找到重复图片后删除第二是剔除极度模糊和过度遮挡的图片标注本身已经标了遮挡属性但大多数标注工具导出的格式不含这个属性只能人工扫一遍第三步是检查类别平衡如果rider数量只有person的十分之一就要多找骑行场景数据否则模型会对rider类严重欠拟合。2.3 标注实操遮挡与密集场景怎么标标注工具我推荐X-AnyLabeling开源免费支持YOLO格式直接导出而且内置了自动标注模型可以先自动跑一遍再人工修正密集场景下能省不少时间。LabelImg虽然经典但功能还是太简陋了。在遮挡严重的交通场景里标注规范比工具更重要。我总结出三条原则团队标注前必须先对齐第一紧密围绕可见主体画框。如果一个人被杆子挡住一半框只包住可见部分不要脑补完整的身体轮廓。为什么因为模型训练时看到的就是画面里的像素你标了个包含大量背景的框会让模型学成“看到一个杆子也框人”。第二漏标比错标危害更大。密集场景里漏标一个人会导致模型认为“人不完整也可以不算人”错标顶多产生一两个噪声样本。所以人再多也宁可慢一点尽量不要漏。第三多人交错的框采用分割线原则。两个人紧紧靠在一起时如果一个人挡住另一个人大半身体就按可见部分分两个框一定不要把两个人框成一个框。标注完成后导出YOLO格式每个标注文件是txt每行格式是类别ID x_center y_center width height坐标都是归一化到0到1之间的值。2.4 数据集划分与增强策略数据划分上我按8:1:1拆成训练集、验证集和测试集。但有一个关键细节一定要按场景划分不能按图片随机划分。什么意思如果同一个摄像头同一个时间段产生的连续帧一部分进了训练集一部分进了测试集测试集就形同虚设模型“背题”了。我把同一场景的图片全部归到同一个集合里确保测试集是模型从未见过的场景。增强策略方面YOLOv8内置了挺强的数据增强开箱即用。Mosaic把四张图拼成一张训练对密集小目标帮助很大MixUp两图叠加混合标签能提升泛化能力HSV扰动模拟不同光照条件对交通场景的日夜变化很重要。我自己还会加一个自定义策略随机裁剪增强。因为监控画面里的人群经常集中在某个区域整图缩放后目标太小用随机裁剪模拟“镜头拉近”的效果可以帮模型适应中等尺度的目标。3. 环境配置与模型训练从零跑通YOLOv83.1 环境配置清单与显卡优化YOLOv8的环境配置本身不复杂但版本兼容性是个坑。我的推荐组合是Python 3.9或3.10PyTorch 2.0.1或以上CUDA 11.8ultralytics 8.1.x版本锁定很重要新版本API变动频繁安装其实一行命令pip install ultralytics。它会自动带上PyTorch相关依赖。但如果你要自己控制PyTorch版本建议先装好PyTorch再装ultralytics避免它自动装个不匹配的版本。如果你用的也是GTX 1660Ti这种6GB显存的卡有几个优化技巧值得记一下。第一训练时一定要开AMP自动混合精度ultralytics默认会开半精度训练能明显降低显存占用速度还快一些。第二workers线程数可以调到4或者8配合pin_memoryTrue让GPU在等数据的时候不闲着。第三如果batch_size起不来用梯度累积技术效果上相当于变相增大了batch。实测下来GTX 1660Ti在640分辨率下训练YOLOv8sbatch_size16可以稳定跑显存占用大概在5GB出头。如果调成1280分辨率batch只能开到8左右。3.2 预训练权重与超参数选择训练用预训练权重还是从头训我强烈建议用COCO预训练权重。YOLOv8官方提供的yolov8s.pt已经在COCO数据集上训过一轮学到了通用的特征表达。我们项目数据量就几千张从头训很容易不收敛或者过拟合用预训练权重微调是正解。超参数方面给出我调试后比较稳定的组合参数值说明modelyolov8s.pt用s版本性价比最高epochs100这个量级够了batch166GB显存上限imgsz640小目标多可调至960optimizerSGDAdamW收敛快但泛化弱lr00.01SGD的基准学习率cos_lrTrue配合余弦退火效果更好patience20早停机制防过拟合ampTrue混合精度mosaic1.0默认开mixup0.1适当开启valTrue边训练边验证这里有个细节为什么不直接用AdamW我在实际对比中发现SGD配合余弦退火虽然前期收敛慢一点但最终的mAP通常会比AdamW高0.5到1个点而且不容易过拟合。AdamW更适合目标函数复杂的场景或者在调参阶段快速探索的时候用。3.3 训练实操与日志指标解读训练命令很简单在已经配置好的环境里执行yolo detect train datatraffic_dataset.yaml modelyolov8s.pt epochs100 batch16 imgsz640 optimizerSGD lr00.01 cos_lrTrue ampTrue其中traffic_dataset.yaml需要自己定义内容包括数据集路径、类别数量和类别名称。训练日志里最关键的几个指标Pprecision是精确率Rrecall是召回率mAP50是IOU阈值0.5下的平均精度mAP50-95是不同IOU阈值的综合平均精度。对于人群检测这个任务我第一优先看recall人群遮挡严重时漏检的安全风险比误检更大。训练结束前recall能到0.85以上就算合格mAP50做到0.75以上基本可上线。训练过程中最需要盯的是val曲线。如果train loss持续下降但val loss先降后升说明模型开始过拟合这时候就需要回退到val loss最低的权重或者用更早的epoch。ultralytics默认会保存best.pt和last.pt两个权重最好用best.pt做推理。3.4 损失函数曲线可视化别只盯着一张图很多新手问损失函数曲线在哪看。ultralytics训练完会在runs/detect/train目录下生成results.png里面包含了train/box_loss、train/cls_loss、train/dfl_loss和val对应的指标曲线基本够用。但如果想更精细地观察训练过程建议开TensorBoard。训练前在环境变量里设置export ULTALYTICS_TENSORBOARDtrue或者在代码里加上回调参数训练时就能在TensorBoard上实时看loss曲线和各指标曲线。我自己还会用matplotlib把每次训练的平均loss画出来对比尤其是做消融实验时多个训练项目的曲线放在一起能明显看出哪些改动有效果、哪些改动反而让loss更差了。做法很简单训练日志里每行都有loss值提取出来画即可。3.5 显存不足的五种自救方案显存不足是这个项目里最常遇到的问题尤其用消费级显卡训练。我从实际情况出发整理五种方案按优先级排列第一先降batch_size再降imgsz。batch降到8还不行再考虑imgsz降到480或512。降低imgsz牺牲的是小目标检测能力影响比降batch严重。第二开启梯度累积。代码里通过参数gradient_accumulation控制batch4加gradient_accumulation4效果相当于batch16显存占用却只有原来的四分之一。第三开启AMP混合精度。默认是开的如果你的训练命令里之前关了一定加回去。第四用缓存数据集方式把数据提前加载到内存省掉GPU在数据加载上的等待时间间接提高训练效率。第五把模型换小。如果后续还要迭代先用yolov8n跑通流程验证数据集和标注没问题再用s版本正式训练。模型大小不是问题流程跑通才是关键。4. 模型评估、性能优化与边缘部署4.1 评测不止看mAP混淆矩阵与recall策略训练完第一件事不是看mAP而是看混淆矩阵。ultralytics在训练目录里会生成confusion_matrix.png它展示每个类别被预测成其他类别的比例。我第一版模型在rider上的召回率明显偏低查了混淆矩阵发现大量rider被预测成了person原因就是两类在俯视角度下从外观上确实容易混淆。解决这个问题有两个思路一个是在数据层面多补充骑行者场景的图片尤其是电动车和自行车在一起的情况另一个是增强后处理比如rider和person的检测框如果重叠度很高且一个是person一个是rider可以结合目标的宽高比做二次判断。交通场景对召回率要求高我的策略是把推理的conf阈值压低到0.25默认是0.25NMS的iou阈值从0.7降到0.5。这样虽然会让一些低置信度的误检混进来但换来的是漏检大幅减少再配合按区域人数设定告警阈值误检的影响可以被上层规则消化掉。4.2 密集人群推理的后处理调优推理层面的后处理参数对结果影响很大。YOLOv8默认conf_thres0.25、iou_thres0.7在密集人群场景我会做调整。conf_thres降低到0.2甚至0.15后检测框数量会增加不少这时NMS的iou_thres反而要适当调低到0.5让重叠度高的重复框被抑制得更狠。同时要留意max_det参数默认是300密集场景下框数量经常超过1000需要把max_det调到1000以上否则人数统计会偏少。还可以开启agnostic_nms它让所有类别放在一起做NMS而不是每个类别单独做。在person和rider这类容易互相重叠的类别场景下能减少重复框。如果精度还是不够可以开启TTATest Time Augmentation通过水平翻转等多重增强推理后融合结果。这个会降低推理速度边缘设备上一般不推荐但服务器端做离线分析时很好用。4.3 注意力机制改进与轻量化什么时候该做这个话题要泼点冷水。我在做项目时发现网上大量“YOLOv8改进”相关的内容比如给C2f模块融入ECA注意力、EMA注意力等效果在实际交通场景里可能只提高0.1到0.3个mAP但训练时间和调试成本却增加不少。我的建议是先跑通基线确认模型在目标场景的精度瓶颈在哪里再决定要不要做结构性改进。如果模型在白天高密度场景已经85分晚上低照度场景只有50分这时候加注意力模块不如去补夜间数据。注意力机制能帮助模型关注重点区域但解决不了数据本身的分布问题。如果确实要做改进ECA注意力融入C2f是个相对轻量的选择它只增加少量参数对推理速度影响小。EMA注意力机制对密集小目标有一定帮助但会明显增加计算量边缘设备上要谨慎。改进时要做好消融实验基线模型跑一遍改进模型跑一遍其他条件完全一致最后对比mAP和速度。没有这种对比改来改去很容易被“感觉好了”误导。4.4 rk3588等边缘设备的部署流程项目要落地部署这步躲不开。我以rk3588为例这个芯片在边缘设备里性价比很高6 TOPS的NPU算力跑YOLOv8s量化后能做到实时。部署流程大致是训练好的模型先导出成ONNX再通过RKNN-Toolkit2转换成rk3588专用的RKNN格式。转换时有几个注意点。第一是版本匹配RKNN-Toolkit2和rk3588的固件版本必须对应不然转换后模型可能加载报错。第二是量化数据集转INT8量化时需要一个校准数据集一般准备200到500张代表性图片覆盖不同时段和场景的光照条件。量化后的精度损失如果不大于2%到3%属于正常范围。如果部署到Jetson系列设备直接用TensorRT加速即可。YOLOv8的ONNX导出后用trtexec工具转成engineFP16精度损失小速度提升明显。无论是RKNN还是TensorRT输入输出格式都变了后处理代码也要跟着适配。嵌入式端的C语言后处理核心是解析模型输出。YOLOv8经过onnx导出后输出张量通常是[1, 4num_classes, 8400]这种格式640输入下每个目标包含边界框坐标、类别得分。C语言的输出结构体可以这样定义typedef struct { float x1, y1, x2, y2; float score; int class_id; } DetectResult;后处理把模型的输出逐列解析经过conf和NMS筛选后填充到结构体数组里。4.5 项目交付物清单一个完整zip包该有什么这个项目命名为“基于YOLOv8的交通人群监测设计.zip”那交付物就该对得起这个名字。我梳理了一个完整项目包的文件结构data/数据集配置文件和标注说明models/训练好的best.pt权重、ONNX文件、RKNN文件scripts/训练脚本、评估脚本、推理脚本docs/项目说明文档、数据标注规范、部署手册results/训练日志、指标曲线图、混淆矩阵实测下来一个能复现的项目包别人拿到后按文档操作能在三个小时内把模型跑通、复现出主要结果。达到这个标准说明结构和文档是合格的。5. 高频问题排查与避坑速查表5.1 典型问题速查表问题可能原因解决方案训练时OOMbatch过大、imgsz过大降batch、降imgsz、开AMP、梯度累积loss持续为NaN学习率过高、数据含异常标注降低lr0、清洗NaN坐标标注、调小样本mAP很低标注质量差、类别不平衡抽检标注、补数据、统一标注规范train loss下降但val loss不降数据分布差异大、过拟合增加数据多样性、打开mixup、早停小目标完全检测不到输入分辨率太低、下采样丢失信息调大imgsz、开启TTA、考虑加P2检测头部署后精度比训练时下降量化精度损失、预处理不一致检查归一化参数、重做量化校准集同一目标出现多个框NMS阈值不合适调低iou_thres、开启agnostic_nms5.2 训练不收敛的排查顺序遇到loss不下降或者震荡时我建议按顺序排查而不是乱调参。第一步先确认数据标注没问题。随机抽取200张训练图片用X-AnyLabeling打开看一眼标注框是否紧贴目标、类别是否正确、是否有大量漏标。很多时候模型训不好不是因为网络问题而是数据本身有脏东西。第二步确认数据增强参数是默认值。有人为了追求多样性把Mosaic和MixUp调到很高结果训练前期loss波动巨大看起来像不收敛实际上是增强强度过大数据太“难”了。第三步检查学习率。SGD的lr0从0.01往下降二进制搜索调试如果loss完全不降试试0.001如果loss下降又飙升可能是lr太高。这一步是最耗时间的但也是最有效的。第四步看验证集指标。如果valid的mAP一直在上升只是慢那就不叫不收敛而是训练时间不够把epochs和patience调大。5.3 小目标漏检的处理思路交通监控场景里小目标漏检是最大痛点我的经验是按这个顺序处理先调大imgsz。把640改成960或1280是提升小目标检测最直接有效的方法。代价是训练变慢、显存变多所以要先确认算力够不够。再加TTA推理。这个方法不需要重新训练只是推理时多几次翻转和缩放小目标检出的稳定性会明显提高适合在非实时要求的场景用。最后考虑结构改进。如果前两步都不够再考虑给检测头加P2层高层特征图或者引入注意力机制。但这一步一定要基于前面的消融实验不要盲试。5.4 部署精度下降的排查方向训练好的模型转成RKNN或TensorRT后精度掉了基本上逃不出这几个原因量化校准集没有代表性。校准集应该覆盖待部署场景的真实分布如果只放了白天数据部署到夜间的摄像头就会掉点。校准集里白天、夜间、黄昏各放一部分。预处理不匹配。训练时的归一化是除以255部署时有些框架的预处理已经做了归一化你再归一化一次就会输入分布偏移。务必检查两边输入像素范围是否一致。后处理参数不一致。训练时验证用的conf和iou阈值部署时如果改变了效果会有波动。我见过有人训练用conf0.001做mAP评估部署时用conf0.25然后觉得精度掉了其实是自己改了配置。6. 项目复盘与下一步扩展思路这套交通人群监测系统跑通之后我最大的感受是模型训练只是项目的一小部分数据和部署才是真正花时间的地方。数据决定精度上限部署决定你能否把精度变成实际价值。后续扩展的话我建议优先做两个方向。第一个是追踪在检测基础上接入ByteTrack或多目标跟踪算法这样统计到的就不是瞬时人数而是这个摄像头一天经过了多少人流量。这对商圈的客流统计、路口的人流潮汐分析更有商业价值。第二个是密度估计。YOLOv8检测框天然可以转成密度图对每个检测框中心点做高斯热力渲染就能得到人群密度热力图。引入密度图比单纯计数更能表达“拥堵”状态例如检测到100个人但分散在四个角落和100个人挤在一个电子屏幕前面安全风险完全不一样。最后再说一个我非常主观但实用的经验网上各种眼花缭乱的YOLOv8改进模块如果时间和算力有限先别追。把一个标准的YOLOv8在目标场景上做透数据、标注、后处理、部署都调到最优效果绝对能超过90%的“魔改”版本。先把地基打牢再谈改进。本文还有配套的精品资源点击获取