ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

8300张头盔检测数据集:YOLO训练与部署全流程实战

8300张头盔检测数据集:YOLO训练与部署全流程实战 做智慧交通项目的朋友应该都有体会头盔检测这个东西看着简单真正落地的时候坑特别多。前阵子我把一个内部跑了大半年的头盔检测数据集整理了出来一共8300张YOLO格式图片覆盖城市路口电瓶车、摩托车、外卖骑手这些真实场景拿给YOLOv5、YOLOv8可以直接开始训练。这篇就围绕这个数据集把采集、标注、训练、评估、部署的完整链路讲明白也会把我踩过的坑和参数调优经验分享出来。新手可以用它来打通目标检测全流程正在做智慧交通项目的朋友可以直接拿来当baseline。先说一个很多人忽略的点头盔检测不是简单给图片打标签就完事。路口摄像头拍到的骑车人往往只有几十个像素高头盔在图上可能就占二三十个像素再加上逆光、阴影、遮挡、头盔颜色和背景融为一体模型要么漏检要么把后脑勺、雨棚、甚至电动车后备箱当成头盔。这个数据集在设计时把这些问题都考虑进去了所以8300张不是随口定的数字而是按场景比例、难易样本搭配、类别平衡做出来的一版。1. 头盔检测数据集到底解决了什么问题1.1 智慧交通场景下的真实需求智慧交通里头盔检测的用途主要分两类。一类是城市道路对电瓶车、摩托车骑乘人员是否佩戴头盔做自动识别代替原来的人工视频巡检。以前靠人盯着监控屏一个路口的几十路视频根本看不过来而且人看两个小时注意力就下降了漏检率很高。另一类是园区、厂区、建筑工地管理方需要实时判断工人是否按要求佩戴安全帽。这类场景摄像头安装位置固定、角度统一比野外路口好做但要求实时性高、误差容忍度低。不管哪一类核心诉求其实是一样的在海量视频流里自动把没戴头盔的人挑出来告警。这里有个容易踩的认知误区很多人以为只要训练一个头盔检测器就够了实际上生产系统里更常用的是双路判断先检测人和头盔区域再通过位置关系判断这个人的头上到底有没有头盔。因为一个人戴了头盔头盔一定在人的头部附近如果头盔检测框和头部检测框的空间重叠度不够就判定为未佩戴。这个方案比单纯检测头盔鲁棒得多也不容易被画面里远处别人戴的头盔干扰。我做的这个数据集里面的标注框就是按helmet和head两类来组织的目的就是方便大家做这种组合逻辑。1.2 8300张的规模定位与标注策略很多初学者一上来就问数据集是不是越大越好我的看法是分任务。像MNIST那种任务确实可以小但目标检测这种任务数据量不够模型就只会背场景。头盔检测的视觉特征非常明确头盔有固定的形状和结构人戴不戴头盔在头部轮廓上差异也大这种任务对数据量的需求比通用目标检测低不少。8300张已经能训练出一个在固定场景下有实用价值的模型而且训练成本可控。我划分数据的时候留了10%做验证集训练集约7400张验证集约900张。这个比例不固定如果你的场景很杂验证集可以多留一点防止模型过拟合到训练集的拍摄角度。标签策略上我坚持使用两个类别类别含义标注框范围helmet佩戴的头盔紧贴头盔外边缘head未佩戴头盔的头部紧贴头骨轮廓可含头发有人会问为什么不直接标一个person_with_helmet和person_without_helmet那样模型输出的信息更直接但遇到一个人推着车、头盔挂在车把上的情况就会误判。拆成helmet和head两个独立目标后推理阶段可以做空间匹配而且如果以后想扩展检测骑车姿势、车牌号码也能共用低层特征。实例数量上我统计了一下8300张图大约包含32000个标注框其中helmet约17500个head约14500个。比例接近但不算完全平衡这是刻意的真实路口里戴头盔的人数本来就比不戴的多强行把类别做成一比一反而会让模型在真实场景里误报增多。2. 数据采集与标注的完整流程2.1 场景多样性与采集设计这个数据集里的图片主要来源于三块一是我在几个城市路口用摄像头抓取的视频抽帧二是公开的监控视频片段三是一些网上收集的街拍素材。视频抽帧有个好处同一段视频相邻帧场景相同但行人姿态不同能低成本拿到大量有变化的样本。但我不会连续抽太多帧否则训练集里会出现大量极度相似的图片导致模型过拟合到特定动作。我一般是一段10秒的视频抽2到3帧且抽帧间隔不少于15帧。场景多样性上我做了几个维度的覆盖时段白天、黄昏、夜间夜间单独控制一部分。夜间样本难标但如果不放进去模型在晚上直接罢工。天气晴天、阴天、小雨雨天镜头上有水渍的也保留了一些用来模拟摄像头卫生条件差的情况。拍摄角度平视、俯视、侧向。路口监控很多是俯视角度差异大会让模型泛化能力明显下降。目标尺寸头盔占画面比例从10像素的小目标到占半张脸的大目标都要有。另外我必须提醒一点电瓶车头盔和工地安全帽在形状、颜色、佩戴方式上有很大区别。我这个数据集主要定位交通场景所以里头全是骑车人的头盔没有建筑工地那种带帽檐的安全帽。如果你要拿去训练工地项目建议自己补充一批安全帽数据再微调直接拿交通头盔的模型去检测安全帽效果会打折扣。2.2 标注工具与YOLO格式转换标注工具我推荐X-AnyLabeling它比老牌的LabelImg方便很多支持自动标注辅助框出目标后还能微调。如果你只是简单标一批数据LabelImg也完全够用操作逻辑都是画矩形框、填类别。标注导出的时候一定要注意格式。YOLO格式不是把左上角和右下角坐标直接写进txt而是每行一个目标格式是class_id x_center y_center width height其中x_center、y_center、width、height都是相对于图片宽度和高度的归一化值范围在0到1之间。举个例子一张1280x720的图片有个头盔目标左上角坐标是(200,150)右下角是(500,400)。计算过程是box宽度 500 - 200 300 box高度 400 - 150 250 x_center (200 300 / 2) / 1280 350 / 1280 ≈ 0.2734 y_center (150 250 / 2) / 720 275 / 720 ≈ 0.3819 box宽度归一化 300 / 1280 ≈ 0.2344 box高度归一化 250 / 720 ≈ 0.3472所以txt里那一行就是0 0.2734 0.3819 0.2344 0.3472注意类别id从0开始。我定义的data.yaml里顺序是helmet在前、head在后所以helmet对应0head对应1。如果你用可视化工具验证标注一定要确认图片文件名和txt文件名完全一致否则训练的时候会报找不到标签。2.3 难样本与易错标注处理标注里最容易出问题的是边界情况。我整理了一批难样本处理的约定这里直接写出来供参考头盔被手臂、雨棚、树枝遮挡超过一半仍然标helmet但只标可见部分的外接矩形不凭想象补全。头盔拿在手上、挂在车把上、放在座椅上一律不标helmet因为那不是佩戴状态。人离镜头特别远整个头部小于15x15像素不标head避免给模型引入一堆模糊小目标。画面里有人戴着头盔但完全背对镜头只要头部的轮廓能看清头盔形状就标helmet。两个人挨得很近头盔有重叠按各自独立目标标但框不能互相覆盖过多。这些规则看起来琐碎但直接影响训练出来的模型行为。比如你把挂在车把上的头盔也标成helmet模型就会学会检测一切头盔形状的物体到推理阶段看到路边停着一排电瓶车就开始乱报警。标注的一致性比标注的绝对精度更重要前提是规则本身合理。3. YOLO模型选型与训练实操3.1 模型版本怎么选YOLO系列发展到今天可选版本很多。做头盔检测这种小目标偏多的任务我建议直接用YOLOv8如果对最新版本有需求也可以试YOLOv10但v8的生态最成熟预训练模型下载、导出部署、社区资料都最全。YOLOv5虽然老但胜在稳定很多工业项目还在用如果你要部署到比较老的生产环境v5也是稳妥选择。选模型大小的原则是看推理硬件。我做过一组对比拿同一份验证集测模型输入尺寸参数量GPU推理耗时(ms)mAP50备注YOLOv8n6403.2M约80.912适合边缘盒子YOLOv8s64011.2M约140.935综合性价比高YOLOv8m64025.9M约250.946精度更高YOLOv8l64043.7M约400.951精度提升不明显对头盔检测这种目标类别少、特征清晰的任务YOLOv8s是甜点位m和l带来的精度提升很小但推理耗时翻倍。如果部署的硬件是Jetson Nano或者树莓派只能用n版本并且输入尺寸要降到320到416。训练时要下载预训练模型。YOLOv8的预训练权重是从COCO数据集上训练出来的直接用它做初始权重比从零开始训练收敛快得多最终精度也更高。下载的时候注意版本匹配v8的权重不能用在v5的代码上。3.2 训练参数配置与数据增强我的训练配置以YOLOv8为例直接跑一下命令yolo detect train datadata.yaml modelyolov8s.pt epochs100 imgsz640 batch16 device0data.yaml的内容大概是这样train: /data/helmet_dataset/images/train val: /data/helmet_dataset/images/val nc: 2 names: 0: helmet 1: head这里有几个参数值得展开说。imgsz我建议设640不要为了图快降到320。头盔是典型的小目标分辨率降低以后很多头盔只有几个像素模型根本学不到特征。如果你的显卡显存不够优先降batch不要降imgsz。batch16在8GB显存上跑YOLOv8s是没问题的如果你用A100或4090可以开到32甚至64训练更快收敛也更稳。训练轮数我建议100起步。有人觉得50轮就够了但头盔检测这种任务类别少不代表容易收敛尤其是夜间样本往往要到七八十轮精度才明显上来。我实际训练时开了早停连续20轮验证集mAP没有提升就自动停。数据增强方面YOLO默认开启的马赛克增强对头盔检测很有用它能在一张图里拼出多个场景让模型学会适应小目标。如果发现训练集和验证集分布差异大可以把马赛克增强的概率降到0.5避免模型学到的分布太失真。我常用的增强参数如下augment: hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4 translate: 0.1 scale: 0.5 fliplr: 0.5 mosaic: 1.0hsv_h是色调扰动设太大会导致头盔颜色乱变反而影响识别。头盔本身的颜色不是判别性特征但也不能让它变得离谱。fliplr水平翻转对这类任务几乎无害可以放心开。3.3 损失函数与训练中容易崩的地方YOLOv8的损失函数由三部分组成边界框回归损失、分类损失、分布焦点损失。边界框回归默认用CIoU它同时考虑预测框和真实框的重叠面积、中心点距离和长宽比比早期YOLO用的IoU损失收敛更稳定。分类损失用BCE分布焦点损失用来优化边界框的定位质量。对于头盔检测我的经验是这三个损失权重不需要刻意调整默认值就很好。真正要小心的是训练过程中loss突然变成NaN或者直接飞掉。最典型的原因是BN层崩溃。YOLO结构里有大量BatchNorm层当batch size太小、学习率太高或者训练数据里出现极端数值时BN层的均值和方差会剧烈抖动导致梯度爆炸。我踩过最狠的一次坑是把batch设成4学习率用默认值0.01跑了30轮loss直接NaN前面全白费。解决办法有三个至少保证batch大于等于8最好16以上。学习率降一个量级用0.001到0.005起步。打开混合精度训练amp数值稳定性会好很多。如果loss曲线出现阶梯状下降不要慌这是正常的目标检测的损失本身就不是平滑单调的。如果loss在某个epoch后反复震荡且验证集mAP不升优先怀疑学习率太高而不是数据有问题。4. 评估指标与常见问题排查4.1 指标怎么看mAP、混淆矩阵与类间关系训练完成后看一组指标就够了mAP0.5、mAP0.5:0.95、Precision、Recall。mAP0.5衡量的是预测框和真实框IoU大于0.5时算正确的平均精度头盔检测这种任务主要看它。mAP0.5:0.95更严格IoU从0.5到0.95每隔0.05算一次再取平均对定位精度要求高的场景参考价值大。我的数据集在YOLOv8s下mAP50大约0.93到0.95mAP50-95大约0.76到0.80这个水平在固定场景下已经够用了。很多人喜欢看混淆矩阵但会困惑为什么混淆矩阵的行和与列和加起来对不上也就是总合不唯一。这其实不是代码bug。混淆矩阵在目标检测里是按预测框和真实框的匹配情况统计的一个真实框可能同时和多个预测框的IoU都大于0.5NMS会抑制一部分但样本分配过程是动态的导致一个真实框可能出现在多个预测框的匹配路径里。加上漏检的背景类、被NMS删掉的冗余预测行和、列和自然不相等。看混淆矩阵时重点看两个数helmet预测成head的比例head预测成helmet的比例。头盔检测里误检成head的概率要压到最低因为一旦误判就会把戴了头盔的人当成没戴来告警交警那边天天收到假警情项目就黄了。4.2 实测排坑记录我在训练这个数据集的过程中踩了不少坑挑几个典型的写一下第一个坑是loss不降反升验证集mAP恒为0。查了一圈发现是标注文件里混进来几张损坏的图片分辨率只有80x60模型在里面根本学不到东西还把BN的分布带偏了。清洗方法很简单写脚本把训练集所有图片的宽高打印出来凡是长或宽小于100的直接剔除。这个习惯后来我一直保留每次换了新数据集都要先做一遍基础体检。第二个坑是过拟合。训练到60轮左右训练损失还在降验证集mAP卡在0.91不动反复横跳。这就是模型开始背训练集的场景了。解决手段分两步一是增加增强强度把mosaic概率调到1.0scale调到0.7让模型每轮看到的图都差别大一点二是调早停阈值验证集mAP连续15轮不提升就停保存最佳权重。第三个坑是小目标漏检。骑电动车的人离摄像头远时头盔在640分辨率下只有20个像素左右模型经常漏。我试过把imgsz从640提到960小目标的召回率明显上升mAP50提升了两个点但推理耗时也涨了将近一倍。如果你有硬实时要求我更推荐保留640输入在训练阶段用随机的尺度蒸馏技巧或者单独把包含小目标的图片在训练时多抽样。数据层面也可以做滑窗切图把大图切成几块分别检测这个方案我想在后面部署部分细说。5. 部署与落地经验5.1 导出与视频流推理模型训完后部署到智慧交通平台一般不会直接用PyTorch模型。我推荐导出成ONNX再用TensorRT做加速。YOLOv8导出命令很简单yolo export modelbest.pt formatonnx dynamicTrue导出后要验证一下输出维度YOLOv8的输出是[batch, 84, 8400]84的前4位是边界框坐标后80位是COCO类别的概率。头盔检测改成2类后输出维度是[batch, 6, 8400]才对如果你导出后发现类别数还是80那就是data.yaml没配对需要核对模型训练时的类别配置。视频流推理我是用RTSP接入路口摄像头的。这里有一个容易忽略的问题摄像头画面分辨率往往在1080p甚至更高直接整帧送进模型显存和延迟都吃不消。我的做法是降采样到1280然后如果场景里的目标确实小再做切片或者保持原分辨率但用更轻的模型。实测YOLOv8s在TensorRT fp16下推理一张1080p抽帧大约25到35毫秒一个路口同时接4路视频流单张GPU完全扛得住。5.2 数据集后续扩展思路数据集发布之后我自己还在持续迭代。目前最值得做的两个方向一是难样本挖掘把模型在真实场景里漏检的图片挑出来按帧抽出来人工补标再放回训练集循环几轮之后精度提升非常明显。二是做基于半监督的伪标签用当前最优模型给大量无标注路口视频打预测框人工只纠正高置信度的错误样本能省下一大半标注人力。这两件事听起来高大上实际操作起来都不复杂关键是流程要闭环。另外一个方向是模型结构层面YOLO和Transformer结合、用CLIP做语义对齐这些新玩法我也在跟进。头盔检测本身特征简单单纯的Transformer替代CNN收益不大但用注意力机制增强小目标分支还是有一定效果的。我的建议是先把手头的数据和工程链路做扎实再考虑在检测头里加模块别一上来就魔改网络。模型结构改进对最终效果的贡献在数据量不足的时候远小于数据质量的贡献。最后分享一个我个人的习惯每次迭代模型时除了mAP指标我会随机挑两百张验证集图片把推理结果画出来一张一张看。mAP高不代表项目效果好只有亲眼看到夜间逆光下的头盔被正确框出来、看到没戴头盔的人头部被锁定才有底气把模型推到生产环境。做智慧交通这行模型不是炫技是要能扛住真实世界的复杂光线、天气和遮挡而这个8300张的数据集就是在为这一步打底子。
返回列表