YOLOv5安全帽识别实战:从数据准备到部署的完整指南

发布时间:2026/9/16 1:26:50
YOLOv5安全帽识别实战:从数据准备到部署的完整指南 简介基于YOLOv5的安全帽识别项目涵盖源码、训练好的模型、数据集与操作说明面向计算机相关专业学生的毕业设计、课程设计也适合初学者快速上手目标检测实战。资源共13个文件整体约49.48MB包含Python脚本训练、导出、推理、YAML配置、PyTorch权重.pt、Jupyter Notebook及说明文档可满足从模型训练到部署的基本路径。项目已提供训练好的Safety helmet.pt和yolov5s.pt权重下载后可直接进行安全帽检测yaml文件可自行调整数据集配置train.py与export.py支持重新训练和ONNX导出ipynb里还演示了数据库格式转换适合在此基础上扩展功能。目前已有134人学习使用对于需要完成毕设或课设且希望快速产出演示效果的同学是一份结构清晰、开箱即用的参考项目。1. 从源码到成品的四件套这个标题里到底有什么工地入场安全帽识别是目标检测里少有的“场景足够局限、验收标准足够明确”的业务只需要管住“戴了”和“没戴”两个状态但阳光、灰尘、远距离小目标、密集人流全都会同时出现。YOLOv5 在 Jetson、工控机和普通 GPU 上都能跑到可用帧率mAP 也够看所以这些年它几乎成了这类“高分项目”的默认基线。所谓高分项目指的不是某个能一次跑出 0.99 的魔法权重而是源码、训练好的模型、数据集、操作说明这四件套齐全拿到手之后能训练、能推理、能接着改。下面从目录结构开始按“数据准备 → 训练 → 推理评估 → 迭代优化”的顺序把每一步的代码、参数和容易翻车的细节拆开讲适合正在做毕设、准备实习作品或要快速搭现场原型的读者。2. 先搭好数据与代码环境目录结构、标注格式与依赖安装2.1 拿到源码后先看 models / data / utils 三个目录YOLOv5 代码库的整体结构非常固定先花十分钟把目录过一遍后面调参时就不会到处翻文件。核心只有三块内容models/下放的是网络结构定义比如yolov5s.yaml、yolov5m.yaml它们描述的是网络深度和宽度data/下放数据配置和超参数文件比如coco.yaml、hyp.scratch-low.yamlutils/下是具体实现逻辑包括损失函数、锚框计算、评估指标这些被train.py和detect.py调用的底层模块。如果是第一次跑这个项目不要一头扎进utils/loss.py里读源码。先确认两条命令能跑通python train.py --help和python detect.py --help。能打印出参数列表说明环境已经通了。接着再打开runs/目录这是所有训练日志和推理结果的默认输出目录后面所有实验产物都会按exp、exp2、exp3这样的序号递增存放不容易覆盖之前的实验结果。实际操作里我会先把data/里的coco.yaml复制一份改成自己的safety_helmet.yaml因为它是数据入口训练命令靠它找到图片和标签的路径。这个文件的格式很固定后面 3.1 节会完整写出来。2.2 数据集目录规范与 label 格式安全帽识别项目自带的数据集解压后通常是下面的结构。这个布局本身就是 YOLO 系列的标准输入格式不需要额外转换datasets/ └── safety_helmet/ ├── images/ │ ├── train/ │ │ ├── 000001.jpg │ │ └── ... │ └── val/ │ ├── 000101.jpg │ └── ... └── labels/ ├── train/ │ ├── 000001.txt │ └── ... └── val/ ├── 000101.txt └── ...images和labels两个目录必须保持同名文件一一对应label 文件是 txt 文本每行描述一个目标格式为class x_center y_center width height。注意坐标是归一化到 0~1 之间的比例值不是像素绝对值x_center和y_center是目标框中心点坐标不是左上角width和height也是归一化后的宽高计算时不需要关心图片原始尺寸class 是从 0 开始的整数和配置文件里names列表的下标对应。如果数据集里只有一个“安全帽”类别那么每行开头的 class 就都是 0。真实项目中更常见的做法是分两类0: helmet戴了帽子和1: head没戴帽子这样模型学习的是“头”这个相对稳定的参照物比单纯学习“帽子”要鲁棒。分类为两类时现场统计就只需要算head的检出结果召回率还更高。提示训练前先随机抽几张图把 label 坐标换算回像素坐标画框可视化一遍。标注错位、类别写反、坐标越界这几类问题用肉眼看两分钟就能暴露直接训练只会浪费好几个小时。2.3 把 VOC XML 或标注平台的导出转换成 YOLO 训练格式很多公开的安全帽数据集或自己用 LabelImg 标注完的产物是 VOC 格式的 XML 文件。捐赠的和网上下载的安全帽数据集有不少是这种格式所以一份转换脚本是必做的功课。import os import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_path, out_txt_path, class_names): tree ET.parse(xml_path) root tree.getroot() w, h Image.open(img_path).size lines [] for obj in root.findall(object): cls obj.find(name).text if cls not in class_names: continue box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) cx ((x1 x2) / 2) / w cy ((y1 y2) / 2) / h bw (x2 - x1) / w bh (y2 - y1) / h lines.append(f{class_names.index(cls)} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) with open(out_txt_path, w, encodingutf-8) as f: f.write(\n.join(lines)) voc_to_yolo(000001.xml, 000001.jpg, 000001.txt, [helmet, head])脚本关键是归一化这一行x2 - x1算出的像素宽再除以图片宽就得到了 YOLO 需要的比例值。class_names的列表顺序必须和训练时safety_helmet.yaml里的names严格一致否则类别标签会错位。转换完成后检查一下生成的 txt 是否为空空文件意味着这张图里没有标注目标属于正常情况可以作为背景负样本保留但占比不能太高。数据划分直接放在images和labels两个目录下完成。常见做法是train : val 8 : 2val的比例不要低于 10%否则验证集太小mAP 波动会很剧烈分数忽高忽低不利于判断模型是否真的变好了。2.4 安装依赖yolov5 环境配置的最小命令集环境配置是这个项目新手翻车率最高的地方核心矛盾是 PyTorch 和 CUDA 版本不匹配。先装显卡驱动和 CUDA再装 PyTorch最后装 YOLOv5 的依赖顺序不能反。即使标题里的项目自带操作说明这套流程依然值得自己亲手过一遍后面换机器部署时才不会被动。git clone https://github.com/ultralytics/yolov5.git cd yolov5 python -m venv venv source venv/bin/activate pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install -r requirements.txt如果是 CPU 机器把--index-url那行去掉直接用 pip 默认源装 CPU 版 PyTorch 即可。装完后跑python -c import torch; print(torch.cuda.is_available())输出True才说明 GPU 可用。requirements.txt里包含 opencv-python、numpy、pandas、matplotlib 等常用库新版环境一般不会缺什么。需要提醒的是Python 版本建议在 3.8 到 3.11 之间PyTorch 2.x 与 Python 3.12 的组合偶尔会遇到依赖冲突出问题就切换 Python 版本重来比逐个解决依赖要快。环境跑通以后建议先把detect.py用官方权重跑一次确认推理链路是通的。这一步能验证 OpenCV 的 imshow 和文件写入权限都没问题再开始数据准备和训练。3. 训练与超参数从预训练权重到自己的安全帽模型3.1 先写对数据配置文件 safety_helmet.yaml训练命令里的--data参数指向的就是这个 yaml 文件。它告诉训练器三件事训练集在哪、验证集在哪、类别叫什么。path: ../datasets/safety_helmet train: images/train val: images/val names: 0: helmet 1: head注意path的写法YOLOv5 会以当前工作目录为基准去拼接这个相对路径。如果train.py在yolov5/目录下数据集在yolov5/../datasets/safety_helmet那么写../datasets/safety_helmet是对的。可以在路径里使用绝对路径但项目换机器以后要改不方便。更稳妥的做法是把safety_helmet.yaml放在yolov5/data/目录下同时在datasets/safety_helmet/目录里放一个data.yaml两者内容一致这样不管从哪个目录启动训练都不容易出错。names里的序号必须和 label txt 里的 class id 对应上。类别数量不是两个也可以单类别0: helmet一样能跑通只是模型失去了“通过未戴帽人头做对照”的能力。提示写完 yaml 后用python -c import yaml; print(yaml.safe_load(open(data/safety_helmet.yaml)))检查一遍语法很多训练中断是因为 yaml 缩进或中英文冒号出错根本不关模型的事。3.2 迁移学习训练命令与关键参数表安全帽数据集的规模通常在几千到一两万张之间直接用随机初始化的权重从头训练收敛慢且容易过拟合。常见做法是用官方预训练权重做初始化只训练后面自己的分类头和回归头这就是迁移学习。python train.py \ --data safety_helmet.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0 \ --workers 4逐项说明参数含义参数示例值作用与选择逻辑--weightsyolov5s.pt预训练权重路径。s版轻量适合快速验证m/l版精度更高但更慢更吃显存。--img640训练分辨率。安全帽是典型小目标640是精度与速度的平衡点全是远距离小图时尝试1280。--batch16单卡 batch size。显存不够就减半8 也够用多卡时是每个卡的 batch。--epochs100迭代轮数。看results.png里的 val loss 是否还下降连续 20 轮不降就停。--workers4数据加载线程数。数据在 SSD 上时可以调大机械硬盘反而设 2 即可。--device0GPU 编号CPU 训练写cpu但不建议用 CPU 做完整训练速度差几十倍。训练过程中打开runs/train/exp/目录里面会实时更新多个图表。我一般只看两张results.png的val/box_loss和mAP_0.5曲线。如果 mAP 在图表的最后十几轮还在稳定上升说明 100 轮还不够可以继续加轮次如果 val loss 已经开始回升但 mAP 还在涨那就是过拟合的前兆此时最好的操作是停止训练用当前 best.pt 的早停权重。3.3 超参数文件 hyp.yaml 与安全帽场景的三个必调项data/hyp.scratch-low.yaml里放着学习率、数据增强强度等超参数。默认值在 COCO 上表现良好但不一定适合安全帽这种“目标尺度集中、背景相对单一”的数据。以下几个参数需要额外注意参数默认值安全帽场景的调整建议lr00.01数据量少于 3000 张时降到 0.005否则第一轮容易震荡。mosaic1.0保持 1.0它能把四张图拼成一张直接增加小目标的训练样本数量。fliplr0.5降到 0.2。安全帽上的 logo 和公司名是文本水平翻转后文字镜像可能让模型学到错误特征。mixup0.0小样本场景可调到 0.1 左右用于抑制过拟合但训练时间会变长。mosaic是最值得讲的一个参数。YOLOv5 在训练时会把四张训练图随机裁剪、缩放后拼接成一张图变相制造了大量小目标样本。工地照片里远处人员的安全帽经常只有十几个像素没有 mosaic 这类操作模型基本学不好小目标。需要说明的是mosaic在训练最后10个 epoch 会自动关闭回到普通缩放训练目的是消除拼接图的分布偏差让最终模型更适应正常的输入图片。类别不平衡是安全帽数据集最常见的问题。很多数据集里“戴帽”样本远多于“未戴帽”样本模型最后会倾向于把什么都预测成helmet。除了在数据层面少采样helmet还可以在 loss 层面做文章——但 YOLOv5 的官方实现没直接开放类别权重参数。我一般直接用数据层面的办法按类别统计数量对head类图片做多一份复制增强让两个类别的样本量尽量接近。训练完成后runs/train/exp/weights/下会有last.pt和best.pt两个权重。best.pt是验证集 mAP 最高的节点推理和部署都用它不要用last.pt。4. 推理与结果评估detect.py 参数、输出与 mAP 指标4.1 推理命令参数逐项拆解训练完的模型最终要放到detect.py里做推理。这个命令的完整形态如下python detect.py \ --weights runs/train/exp/weights/best.pt \ --source ../data/val_site/ \ --img 640 \ --conf-thres 0.35 \ --iou-thres 0.45 \ --save-txt \ --save-conf \ --project runs/detect \ --name site_test参数解读参数作用与建议--source输入来源可以是图片目录、单张图、视频文件或摄像头 ID0。--conf-thres置信度阈值低于该值的框会被丢弃。密集小目标场景建议0.25起调误检多就上调到0.4。--iou-thresNMS 的 IoU 阈值值越小越激进重叠框被合并得越狠。人员密集时设0.3场景稀疏保持0.5。--save-txt把框坐标写成 txt 文件便于后续做指标统计现场部署时一定要加。--save-conf把置信度一并写进 txt与--save-txt搭配使用。--classes指定只输出某些类别比如--classes 1就只输出未戴帽结果可减少误报。推理结果默认存放在runs/detect/site_test/目录带框的可视化图片直接看labels/子目录下是与图片同名的 txt每行内容为class cx cy w h conf。注意这里的cx cy w h依旧是归一化比例如果上层业务系统需要像素坐标要自己乘回图片宽高。对于视频流或实时摄像头检测推理速度取决于--img和模型大小。yolov5s在 RTX 3060 上处理 640 分辨率大约能到 40 FPS现场多路视频推流时建议每路用一个独立进程避免 GIL 卡住预处理环节。4.2 评估脚本val.py 与 mAP 计算的参数差异train.py训练结束后虽然会自动在验证集上计算 mAP但想要得到更准确的评估结果需要单独跑一次val.py。这里的参数和推理时完全不同一个常见的误区是拿推理时的阈值直接跑评估。python val.py \ --data safety_helmet.yaml \ --weights runs/train/exp/weights/best.pt \ --batch 16 \ --conf-thres 0.001 \ --iou-thres 0.6评估时--conf-thres必须设得很低比如0.001这样才能把模型所有“疑似框”都拿出来计算 PR 曲线最终得到完整的 mAP 值。如果把conf-thres设成推理时的0.35低置信度框直接被丢弃Precision 会虚高mAP 结果是不可信的。--iou-thres 0.6表示预测框与真值框 IoU 超过 0.6 才算正确检出这和训练时的 loss 计算口径保持一致。安全帽项目一般重点看mAP0.5也就是 IoU 阈值为 0.5 时的平均精度。这个指标对“框得差不离就行”的业务足够。如果项目要求严格再顺带看mAP0.5:0.95它是多个 IoU 阈值的平均能反映定位精度但数值会比mAP0.5低不少不要拿这个数字去对标高分的mAP0.5结果。val.py运行完后在runs/val/exp/下会生成PR_curve.png、confusion_matrix.png、F1_curve.png等图表。PR_curve.png的曲线越靠近右上角越好曲线与坐标轴围成的面积就是 AP。混淆矩阵里看两个数字head列里被预测成helmet的比例以及background列里的数值。后者代表误检率数值超过 5% 时说明模型有系统性误报需要回到数据层面加负样本这比单纯调conf-thres更治本。4.3 从训练日志读 P、R、mAP 的平衡训练日志里有两个容易混淆的概念Precision查准率和 Recall查全率。安全帽项目里漏检一个未戴帽的人比误报一个戴帽的人严重得多所以调参方向是“保 Recall 优先”。具体操作是推理时把conf-thres从 0.35 降到 0.2Recall 上升Precision 下降然后用业务规则兜底——对置信度 0.2 到 0.35 之间的框标记为“待复核”由后台人工二次确认。日志输出的P和R是验证集在置信度 0.1 时的统计值它反映的是模型本身的查找能力和推理时选什么阈值无关。所以不要拿训练日志里的 P、R 直接复述成现场指标的预期。现场指标永远是“模型能力 推理阈值”的组合结果这点在写项目报告时要特别注意很多答辩被问倒都是栽在这个地方。5. 从 mAP 到现场可用badcase 分析、负样本回灌与边缘部署5.1 用 badcase 回灌把漏检样本变成训练样本mAP 只反映统计水平真正决定项目口碑的是几个极端场景远处几个人缩在一起、背对摄像头戴深色帽子、强逆光下帽子边缘和背景融为一体。针对这类 badcase最有效的做法不是调阈值而是把它们做成新训练集。操作流程分三步。第一步找出漏检图用推理代码对每张验证图输出--save-txt --save-conf与真值比对后筛选出包含head真值但模型没输出的图片。第二步把这些图片里的漏检目标用标注工具补上标签加入训练集。第三步对误检图做反向处理——把所有没戴帽子、但模型报成了helmet的图直接作为负样本放回数据集注意这类图的 label 文件保持为空即可YOLOv5 训练流程会正常处理无目标的背景图。这里有一个操作细节数据回灌后不要只是把新样本追加到原训练集建议单独把 badcase 做成一个hard_set以 15% 的比例混入每个 epoch 的数据流而不是一次性全量塞进去。后者会导致模型对固定难例过拟合换一批新现场照片之后效果反而变差。python train.py \ --data safety_helmet.yaml \ --weights runs/train/exp/weights/best.pt \ --img 640 \ --batch 16 \ --epochs 30 \ --hyp data/hyp.scratch-low.yaml5.2 小目标和误检的推理侧修正如果图像中的安全帽普遍小于 20×20 像素单纯靠加大训练分辨率会让推理变慢。常见做法是把推理分辨率保持640不变但在输入进模型前对图像做切片也就是把大图切成若干 640×640 的重叠块分别推理再将结果坐标映射回原图坐标。在 Jetson Nano 这类低算力设备上切片推理通常比img 1280整体推理更快因为有效计算区域更集中。误检问题则优先检查 NMS 参数。交互堆叠的人群里同一个头可能会同时被预测成helmet和head两个类别此时把--iou-thres从0.45调到0.3让同类别的重叠框被更快合并。如果是不同类别之间的误检直接用--classes 1在输出层过滤只保留head的结果业务层反转判断是否戴帽。5.3 用 TensorRT 固定形状把推理速度再压一档安全帽识别项目如果想部署到边缘盒子训练完成后的最后一步是模型转换。YOLOv5 仓库提供了export.py可以导出 ONNX 格式再转成 TensorRT 的 engine 文件。固定 batch size 为 1、固定输入分辨率 640能显著降低显存占用。python export.py --weights best.pt --include onnx --img 640 --batch 1 trtexec --onnxbest.onnx --saveEnginebest.engine --fp16转换后用best.engine替换--weights参数重新跑一遍detect.py确认检测结果和 PyTorch 版本一致。对旧款 Jetson 设备FP16 精度几乎没有损失推理时间通常能缩短到 PyTorch 的一半以下只有在摄像头画面中安全帽目标整体小于 12 像素时才需要对比 INT8 量化误差。整个转换和验证过程的时延数据直接在终端里跑一遍即可记录现场验收时不需要额外准备演示脚本。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

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

尧图内容编辑团队

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

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

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

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

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

网站改版的5个关键决策

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

获取专属建站方案

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

立即免费咨询