YOLOV5安全帽检测落地全流程:数据标注、模型训练到推理部署

发布时间:2026/9/14 2:02:16
YOLOV5安全帽检测落地全流程:数据标注、模型训练到推理部署 简介基于YOLOV5构建的头盔佩戴检测识别系统完整项目包源自已通过的高分毕业设计面向计算机视觉方向毕业设计学生及深度学习初学者解决电动自行车骑行场景下头盔佩戴状态的自动检测问题。压缩包内共77个文件约23.73MB涵盖Python源码含模型训练、检测、数据集转换脚本、YOLO系列模型配置文件、VOC格式标注数据集、预训练权重下载脚本、环境配置说明文档及操作演示视频从数据准备到模型部署形成完整闭环。内容预览显示项目结构规范包含make_voc_dir.py、voc_to_yolo.py等标注格式转换工具以及detect.py、train.py等核心训练检测入口便于二次开发与算法理解。目前已有195人学习适合需要快速复现或基于YOLOV5开展头盔检测研究的用户下载参考。1. 工地监控里找出没戴安全帽的人YOLOV5 是怎么落下地的一个普通工地通常有十几路到几十路摄像头值班员不可能一直盯着屏幕漏看一帧就可能放过一次违规。把“头盔佩戴检测识别系统”做成能跑的东西核心不是训练本身而是把这套链路串起来数据集怎么标、模型怎么训、训好的权重怎么部署。这也是这类项目包会把源码、数据集、训练好的数据和教程一起打包的原因——对刚接触 YOLOV5 的人而言缺任何一环都会卡住。本文按实际落地顺序展开。先讲 YOLOV5 为什么适合头盔这类小目标检测再完整走一遍从数据标注到训练配置的流程最后落在推理部署和排错上。不管你是做毕设、做工地安防改造还是自己接了个巡检小项目按这个顺序走能少踩一半坑。2. 从头盔目标看 YOLOV5 的选型理由与关键机制2.1 实时视频流场景下单阶段检测的胜出逻辑头盔检测面对的是视频流每路摄像头每秒 25 帧左右如果按帧做检测单帧推理时间必须控制在几十毫秒量级。两阶段检测器如 Faster R-CNN 是先提候选区域再分类回归精度上限高但在 CPU 或低端显卡上很难跑到实时。YOLOV5 是单阶段模型在一张特征图上直接输出类别和边框省掉了区域提议这一步成为这类落地项目的首选。这不是说单阶段一定优于两阶段。比如需要检测极小目标、且对速度没有要求时两阶段模型可能更稳。但头盔目标的尺寸通常在 640 分辨率下只有 20×40 像素左右属于中小目标YOLOV5 的多尺度检测头能覆盖这个范围。配合工地场景的密集人群实时性带来的收益远大于那点精度差距。2.2 头盔小目标的召回靠什么特征金字塔与锚框聚类YOLOV5 的骨干网络是 CSPDarknet颈部是 PANet 特征金字塔检测头在 80×80、40×40、20×20 三个尺度上分别输出小、中、大目标的预测框。对头盔这种小目标80×80 这一层的感受野最小能保留更多空间细节是召回率的主要来源。锚框的设定也直接决定训练是否容易收敛。YOLOV5 会在训练前用 k-means 从你的数据集中自动聚类锚框尺寸不需要手工指定。但要注意如果项目包里自带的锚框是从 COCO 数据集聚类出来的迁移到头盔场景时建议让模型重新聚类。常见做法是在训练命令里加--noautoanchor参数来关闭自动聚类但多数情况下让 YOLOV5 默认重新聚类反而更省事。组件作用对头盔检测的影响CSPDarknet 骨干提取图像特征参数量适中4GB 显存可训练PANet 颈部多尺度特征融合小目标信息不丢失提升召回80×80 检测头负责小目标回归头盔的主要输出层k-means 锚框自适应数据集适合头肩比固定的目标2.3 项目包里的“训练好的数据”到底是什么很多新手拿到项目包会问训练好的数据是不是指数据集不是。数据集是标注好的图片训练好的数据在 YOLOV5 里指的是一次训练结束后保存的权重文件也就是runs/train/exp/weights/best.pt和last.pt。best.pt是验证集上 mAP 最高的那一轮权重last.pt是最后一轮的状态。这两个文件才是推理阶段真正要加载的东西。后续用detect.py或自定义脚本做实时检测时加载的就是best.pt。如果你拿到手的项目包里只有数据集而没有.pt文件那就需要自己从头训练如果有现成的best.pt可以直接跳到最后一步做验证再决定要不要微调。3. 构建头盔佩戴检测数据集采集、标注与划分3.1 原始素材获取监控帧、公开数据集与补充拍摄构建数据集的素材来源一般有三条路。最常见的是从现场监控视频里抽帧用 ffmpeg 每 5 到 10 秒抽一帧尽量覆盖不同角度、不同光照、不同工种。其次是公开数据集SHWDSafety Helmet Wearing Dataset这类项目包含已经标注好的头盔和人的两类目标可以作为初始训练集。最后是补充拍摄用手机在不同距离、不同方向拍一些现场照片专门用来修正模型在你自己场景下的偏差。素材采集的关键是多样性。一个常见的错误是只拍晴天上午的素材模型训练出来后在逆光、夜间或下雨场景下基本失效。采集时要有意识地记录时段、天气、摄像头机位高度这些信息按场景比例分配到训练集里而不是简单地把所有图片混在一起。3.2 用 LabelImg 标注头盔的类别设计与框选规范标注工具用 LabelImg 比较多它支持直接输出 YOLO 格式的 txt 文件。每个目标一行格式是class x_center y_center width height四个坐标值都是相对图片宽高的归一化浮点数取值范围 0 到 1。类别设计上我一般建议只标两类helmet表示佩戴了安全帽head表示没有佩戴的头部。这样设计的好处是分类边界清晰。如果引入第三类如“戴了但没系下颚带”标注难度和数据量都会成倍增加模型效果反而可能变差。框选规范上头盔框要贴合头盔外沿人头框从下巴到头顶不要包含太多肩膀区域。类别名含义标注框范围helmet正确佩戴安全帽贴合头盔外沿head未佩戴安全帽的人头下巴至头顶少带肩膀背景不参与标注忽略区域不需要框3.3 目录结构组织与训练/验证集划分脚本YOLOV5 训练时读取数据集的路径是写在dataset.yaml里的目录结构需要和配置文件对齐。常见做法是建一个helmet_dataset根目录下面分images和labels两个大目录各自再按train和val拆分。图片和对应的 txt 标注文件必须同名否则训练时会报找不到标签。下面的 Python 脚本完成从平铺目录到 train/val 分离的划分。假设原始图片都在helmet_dataset/images下对应的标注在helmet_dataset/labels下脚本会按 9:1 随机划分后移动到子目录。import os import random import shutil random.seed(42) dataset_root helmet_dataset train_ratio 0.9 all_items [] for name in os.listdir(os.path.join(dataset_root, images)): if name.endswith(.jpg): all_items.append(name) random.shuffle(all_items) train_size int(len(all_items) * train_ratio) for split, items in ( (train, all_items[:train_size]), (val, all_items[train_size:]), ): img_split os.path.join(dataset_root, images, split) lbl_split os.path.join(dataset_root, labels, split) os.makedirs(img_split, exist_okTrue) os.makedirs(lbl_split, exist_okTrue) for name in items: shutil.move( os.path.join(dataset_root, images, name), os.path.join(img_split, name), ) shutil.move( os.path.join(dataset_root, labels, name.replace(.jpg, .txt)), os.path.join(lbl_split, name.replace(.jpg, .txt)), )脚本逻辑是列出所有 jpg 文件名按比例切片后用shutil.move迁移文件。注意两点一是random.seed(42)保证每次运行结果一致方便复现二是图片和标注文件同步迁移不会出现图片有标注、标注没图片的情况。若你的图片格式是 png把两处.jpg后缀替换掉即可。划分完成后还要做一次校验统计train和val各自包含多少张图片和多少个目标框确认没有空标签文件。这一步常在训练报no labels found时才被想起但提前检查能省下不少定位时间。4. yolov5 环境配置、训练参数与模型训练教程4.1 环境配置conda、PyTorch 与 requirements.txtyolov5 环境配置是新手最容易卡住的地方。项目源码根目录下自带requirements.txt但直接pip install -r requirements.txt不一定能满足 PyTorch 的版本要求。建议先装 PyTorch再装其他依赖。CUDA 版本和 PyTorch 版本必须对应conda可以自动装好匹配的 CUDA 运行时比手动配省事很多。conda create -n yolov5 python3.9 -y conda activate yolov5 pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu118 pip install -r requirements.txt参数说明--index-url指定 PyTorch 官方 CUDA 11.8 版本的下载源如果显卡驱动较老就换成cu113或cu117。Python 版本 3.9 是兼容性较好的选择3.11 以上部分旧版本依赖会编译失败。装完后直接python train.py --help验证环境是否可用。4.2 写 helmet.yaml 与跑通第一条训练命令环境就绪后接下来是写数据配置文件。这个 yaml 文件告诉 YOLOV5 训练集和验证集的图片路径、类别数量和各类别名称。train: helmet_dataset/images/train val: helmet_dataset/images/val nc: 2 names: 0: helmet 1: head路径既可以写相对路径也可以写绝对路径。建议写相对路径并保证在项目根目录下执行训练命令这样后续换机器不用改配置。nc是类别总数names的索引顺序要和标注文件里 class id 一致标错顺序会让 helmet 和 head 的预测结果互换。执行训练命令时最常见的做法是基于 COCO 预训练权重yolov5s.pt做迁移学习。s代表 small 版本显存占用小适合大多数入门级显卡。python train.py \ --data helmet.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --project runs/train参数含义分别是--data指定数据配置--weights加载预训练权重脚本会自动下载到本地--img 640是训练输入分辨率--batch 16由显存决定8GB 显卡跑 16 通常没问题4GB 建议降到 8--epochs 100对头盔这类目标数量有限的场景足够看到收敛趋势。4.3 必调超参数与迁移学习参数不看显卡定 batch 会直接 OOMyolov5 超参数文件是data/hyps/hyp.scratch-low.yaml训练时默认会读取。这里重点说几个实际影响较大的参数而不是全部列出。超参数默认值建议范围说明lr00.010.001-0.01初始学习率小数据集调低更稳mosaic1.00.5-1.0马赛克增强小目标场景建议保留fl_gamma0.00.0-1.5焦点损失系数类别不平衡时调大scale0.50.3-0.9随机缩放范围影响目标尺寸多样性mosaic是 YOLOV5 最有效的增强手段之一它把四张图拼接成一张训练头盔这类小目标会显著受益。但如果你发现模型在小目标上精度不错、大目标反而漏检适当降低mosaic到 0.5 能让模型更好地学习原始尺度下的特征。fl_gamma在头盔和未带头数量差距大时可以调到 1.0 左右它会让模型更关注难分类的样本。迁移学习方面--freeze 10可以冻结前 10 层骨干网络参数数据集较小或预训练场景接近时能加快收敛并减少过拟合。如果项目包里带了同场景的预训练权重直接用那个权重做初值比用 COCO 权重效果更好如果用的是公开数据集训练的权重要注意类别顺序是否一致不一致时需要重新映射类别索引。训练结束后检查runs/train/exp/weights目录下生成的best.pt和last.pt文件同时看训练日志里的mAP0.5指标。头盔这个场景mAP0.5通常能到 0.9 以上才算合格低于 0.8 说明数据集或标注有问题先回头检查标注而不是加轮数硬训。这是判断训练好的数据是否可用的最直接依据。5. 用训练好的权重做推理部署与现场排错5.1 三条命令完成图片、视频、摄像头推理与 ONNX 导出训练完成后最关心的是拿best.pt跑起来。YOLOV5 自带的detect.py可以处理图片、视频和摄像头输入。python detect.py --weights runs/train/exp/weights/best.pt --source demo.jpg --conf-thres 0.5 --iou-thres 0.45 python detect.py --weights runs/train/exp/weights/best.pt --source demo.mp4 --conf-thres 0.5 --iou-thres 0.45 python detect.py --weights runs/train/exp/weights/best.pt --source 0 --conf-thres 0.5 --iou-thres 0.45--conf-thres是置信度阈值低于该值的框会被丢弃。现场误检多就调高到 0.6 以上漏检明显就降到 0.3 左右。--iou-thres是 NMS 去重阈值人群密集场景建议保持 0.45 或略调低避免两个重叠人头被合并成一个框。如果想部署到服务端或边缘设备建议先转成 ONNX 再转 TensorRT。ONNX 版不依赖 PyTorch 运行环境推理速度更快。python export.py --weights best.pt --include onnx engine --device 05.2 漏检、误检、掉帧从参数到数据复核的排错链路现场遇到漏检时先压低--conf-thres看目标是否以较低置信度出现了。如果 0.25 下能看到框但 0.5 下看不到说明模型对这类样本的置信度总体偏低大概率是训练数据里缺少该角度或该光照的样本。这时候要补充的是数据不是调阈值。误检分两种。一种是背景被识别成头盔多发生在蓝色彩钢瓦、蓝色雨伞这类颜色接近安全帽的区域。这类问题优先检查训练集中负样本是否足够建议额外收集 500 张以上完全不含人和头盔的工地背景图放进训练集但不标注任何框。另一种是把头盔识别成未佩戴通常是类别边界不清晰重新检查一批标注中helmet和head的框是否混入了对方的区域。掉帧问题在摄像头部署时最明显。先看推理耗时用--profile参数打印前向推理时间。如果单帧超过 100ms说明算力吃紧优先把--img-size从 640 降到 512 或 416小目标精度会下降但速度提升近一倍。再不行就换yolov5n权重重新训练它比yolov5s小一半以上。最终极的优化是导出 TensorRT 引擎并开启半精度推理在 Jeston 系列板卡上能做到 5ms 级别。还有一个实操技巧当多路摄像头同时接入时不要每路都跑一个完整模型实例。用一个推理进程处理多路视频流每路抽帧后放入队列模型批量推理再把结果写回各自的显示线程。这样能充分利用 GPU 的 batch 并行能力把总吞吐从 5 路提升到 10 路以上这也是这类项目从单路演示走向真实部署的关键一步。本文还有配套的精品资源点击获取