简介:一份基于YOLOv5的安全帽识别完整项目,含源码、训练好的模型与配套数据集,面向计算机相关专业学生、老师及企业开发者,可直接用于毕业设计、课程设计或安全帽检测场景的快速落地与二次开发。该项目的核心代码已通过实际测试运行,作者标明为高分毕业设计,评审达到95分,说明完整性和可靠性有保障。资源包共13个文件,整体约49.48MB,涵盖Python脚本(训练、导出)、YAML模型配置、预训练权重pt、数据集压缩包、License、使用说明文档及notebook示例,结构清晰,便于按需取用。其中pt权重可加载即用,yaml便于调整网络结构,py脚本支持重新训练或自定义修改,ipynb则适合逐步学习和演示。目前已有134人学习浏览,适合从零入门YOLOv5的目标检测新手,也适合需要快速完成课设、毕设或项目初稿的开发者,下载后即可依据操作说明运行,并在此基础上扩展其他检测功能。 安全帽识别是Yolov5在工业视觉里落地最成功的场景之一,但和Faster R-CNN这类两阶段模型相比,它在边缘设备上的推理速度优势实在太明显。尤其以yolov5s为骨架的轻量版本,模型体量只有十几MB,在Jetson Nano上就能达到每秒20帧以上的检测能力,这正好满足工地实时监控的需求。这套资源把源码、训练好的权重、数据集和操作说明都打包好了,适合直接拿来做毕业设计、课程设计,或者作为工程初版的验证环境。接下来我从数据组织开始,把整个链路拆开看一遍,顺便标记出那些容易翻车的参数和路径问题。
2. 项目结构和数据准备:从hat.yaml看Yolov5的数据组织
2.1 解压后我们拿到了什么
压缩包解开以后,目录结构和官方yolov5-master基本一致,但额外带了好几个定制文件。按我的习惯,拿到资源的第一件事不是跑训练,而是先把文件作用理清楚,否则后面改错配置文件,损失的是训练时间。下面是我整理出来的关键文件清单,后续所有操作都围绕这些文件展开。
| 文件/目录 | 作用 | 使用场景 |
|---|---|---|
| yolov5-master/ | 完整的Yolov5训练推理框架 | 训练、验证、导出 |
| hat.yaml | 安全帽数据集的配置入口 | 训练时告知数据路径和类别名 |
| yolov5s.yaml | 模型结构定义文件 | 修改类别数后传给train.py |
| Safety helmet.pt | 训练好的安全帽检测权重 | 直接推理,或者重新训练起点 |
| yolov5s.pt | COCO预训练权重 | 迁移学习初始化 |
| YOLO-hat.py | 针对安全帽场景的推理脚本 | 单张图片、文件夹、视频检测 |
| export.py | 官方模型导出工具 | 导出ONNX、TensorRT等格式 |
| 导出数据库格式.ipynb | 标签格式转换工具 | 把VOC或别的格式转成Yolo标签 |
| 171265889347208773632.zip | 原始数据集备份 | 解压后用于重新训练 |
这里面hat.yaml是核心配置,它决定了训练阶段去哪里读图片、目标类别有哪些。出现训练完模型但检测结果完全离谱的情况,十有八九是这里的类别顺序和标注文件不一致。Yolo是用类别ID索引来对应名字的,names顺序错了,模型学到的语义就错了。
2.2 hat.yaml的字段和路径规则
hat.yaml的内容按我的标准写法是这样的,我直接加了注释说明每个字段的坑:
# hat.yaml train: ../datasets/helmet/images/train # 训练集图片目录 val: ../datasets/helmet/images/val # 验证集图片目录 nc: 2 # 类别数:helmet和head names: ['helmet', 'head'] # 类别名列表,索引0和1逻辑说明:train和val路径是相对于yolov5根目录的相对路径。我把数据集放在yolov5的上级目录里的datasets/helmet下,这样才能用../datasets/helmet/images/train定位。如果你的数据集放在别处,需要改成对应的绝对路径或相对路径。nc必须和标注txt里的最大类别ID一致,比如只有helmet和head两类,那索引只有0和1;如果多了一个person类,就要把nc改成3,names里也要对应加上。
参数说明:Windows下很容易忽略路径分隔符问题,建议把所有反斜杠统一成/,否则会报FileNotFoundError。另外,Yolov5不会自动划分训练集和验证集,必须手动在images和labels下分好train、val两个目录,且图片和对应的txt文件名要完全一致,否则训练时提示“found no labels”。
2.3 数据集划分与标签格式转换
项目中的导出数据库格式.ipynb专门处理标签转换。如果你手里是来自LabelImg的VOC xml,或者Labelme的json,都需要转成Yolo的txt格式。我一般用下面这段脚本来做转换,纯Python,不依赖额外库,方便改成json格式。
import os import xml.etree.ElementTree as ET from pathlib import Path classes = ['helmet', 'head'] # 必须和hat.yaml的names顺序一致 def convert_box(size, box): dw = 1.0 / size[0] dh = 1.0 / size[1] x = (box[0] + box[2]) / 2.0 * dw y = (box[1] + box[3]) / 2.0 * dh w = (box[2] - box[0]) * dw h = (box[3] - box[1]) * dh return x, y, w, h def xml_to_yolo(xml_dir, out_dir): # 遍历xml目录,将每个xml转成同名txt for xml_file in Path(xml_dir).glob('*.xml'): tree = ET.parse(xml_file) root = tree.getroot() size = (int(root.find('size/width').text), int(root.find('size/height').text)) out_path = Path(out_dir) / (xml_file.stem + '.txt') with open(out_path, 'w') as f: for obj in root.iter('object'): cls = obj.find('name').text if cls not in classes: continue cls_id = classes.index(cls) box = [float(obj.find('bndbox/xmin').text), float(obj.find('bndbox/ymin').text), float(obj.find('bndbox/xmax').text), float(obj.find('bndbox/ymax').text)] x, y, w, h = convert_box(size, box) f.write(f"{cls_id} {x:.6f} {y:.6f} {w:.6f} {h:.6f}\n")逻辑说明:convert_box把VOC格式的绝对坐标转成中心点和宽高的相对值,同时除以图片长宽归一化。Yolov5训练时会把输入图片缩放成640×640,如果用绝对坐标,缩放后的框位置就全错了。xml_to_yolo函数遍历所有xml,找到合法的类别,写出每一行的目标框。
参数说明:如果xml里有目标被标记成helmet但你在classes里拼写成了helm,那这个目标会被直接跳过,最终标签数量减少,模型会漏检。建议转换完以后统计一下每张图的标签数量,少得离谱的图要重点排查。
接下来划分数据集可以用一条shell命令配合脚本,也可以直接在Jupyter里用random.shuffle。我倾向于用Python完成随机抽样,保证验证集分布和训练集一致。
cd yolov5 mkdir -p datasets/helmet/images/train datasets/helmet/images/val mkdir -p datasets/helmet/labels/train datasets/helmet/labels/val python split_data.py逻辑说明:前两行创建目录结构,split_data.py负责把图片和对应txt文件按照8:2比例随机复制到train和val里。注意txt和图片要同进同出,否则训练过程中会出现找不到标签的警告。
参数说明:如果你的原始标注有大量背景很相近的负样本,建议验证集比例高一些,比如9:1,避免验证时mAP虚高。
3. 训练自己的安全帽数据集:yolov5超参数调整与模型训练
3.1 环境配置和依赖安装
Yolov5的框架依赖Pytorch,常规安装步骤是先建虚拟环境,再装依赖。项目根目录自带requirements.txt,直接执行:
pip install -r requirements.txt pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118逻辑说明:第一行安装的是Yolov5运行所需的基础库,包括numpy、opencv、matplotlib、pyyaml等。第二行安装带CUDA 11.8支持的Pytorch。如果你用的是最新RTX 40系显卡,cu118版本能够稳定支持;如果是30系,也可以降到cu113。如果你不打算用GPU训练,跑这一步可以省略,但训练速度会慢到不可接受。
参数说明:安装完以后,用python -c "import torch; print(torch.cuda.is_available())"验证,输出True才说明GPU可用。很多训练卡住的问题都是Pytorch装成了CPU版本,训练时虽然不报错,但loss一直不降。
3.2 修改yolov5s.yaml的模型结构配置
Yolov5s.yaml开头的nc默认是80,对应COCO数据集。训练自己的类别前,必须把它改成2。打开文件,只需改动这一行:
# yolov5s.yaml nc: 2 # number of classes逻辑说明:yolov5s.yaml定义了模型的深度因子、通道数和检测头结构。它不算完整网络定义,而是让Yolov5自动生成Backbone和Head。更改nc后,训练时就会输出2个类别的预测结果。如果你想要更高精度,可以换yolov5l.yaml或yolov5x.yaml,但显存占用和推理延迟都会成倍增加。
参数说明:有些项目会直接把整个yaml里的nc改成类别数,而忽略anchors也需要对应调整。Yolov5会自动重新计算anchors,但需要加--noautoanchor参数来禁止,多数情况下保持默认即可。
3.3 训练命令的核心参数拆解
我用实际训练安全帽数据集的命令来拆解参数选择,这个命令和官方文档保持一致,也符合hat.yaml的配置结构。
python train.py --img 640 --batch 16 --epochs 100 \ --data hat.yaml --cfg yolov5s.yaml \ --weights yolov5s.pt --name helmet_exp逻辑说明:--img 640表示输入图片尺寸为640×640,这是速度和精度的平衡点;--batch 16在8G显存上比较稳妥,如果你的显卡是12G以上,可以调到32;--epochs 100对于二分类任务来说能充分收敛,再多就容易过拟合;--data hat.yaml是刚才配置好的数据集入口;--cfg yolov5s.yaml指定模型结构;--weights yolov5s.pt表示加载COCO预训练权重进行迁移学习。用预训练权重比从头训练收敛速度快得多,这也是Yolov5在小型数据集上的最佳实践。
参数说明:如果你显存只有6G,把batch改为8,同时加--cache-images来缓存图片到内存,减少磁盘IO压力。如果看到loss数值震荡严重,可以把--lr0改成0.005,降低初始学习率。
3.4 训练过程中的loss曲线与超参数调整
训练结束后会在runs/train/helmet_exp/目录下生成weights/best.pt和last.pt。best.pt是验证集上mAP最高的权重,也就是项目里那个Safety helmet.pt的来源。训练过程中,我习惯用下面表格里的超参数做微调:
| 参数 | 建议值 | 影响 |
|---|---|---|
| batch | 8-32 | 越大收敛越稳定,但显存占用高 |
| lr0 | 0.01 | 初始学习率,过大会导致震荡 |
| mosaic | 1.0 | 拼接4张图做增强,过拟合时调大 |
| fl_gamma | 0.0 | focal loss参数的强弱,正负样本极不平衡时调为1.5 |
逻辑说明:mosaic是Yolov5最核心的数据增强手段,它把四张图片拼接成一张训练样本,极大提高模型对遮挡和小目标的鲁棒性。如果你自己训练的模型在检测远处人员时经常漏检,把mosaic从1.0提高到1.5会有效果,但训练时间也会变长。fl_gamma是focal loss的调节因子,当数据集中正样本(戴头盔)和负样本(不戴头盔)数量悬殊时,提高它能让模型更多关注难分类样本。
参数说明:修改超参数有两种方式,一是直接改data/hyps/hyp.scratch-low.yaml文件,二是在命令行追加--hyp /path/to/yaml。我推荐用后者,这样不同实验之间不会互相污染配置文件。
训练过程中,可以通过tensorboard --logdir runs/train实时观察loss曲线。如果发现验证集loss在第60轮开始反弹,说明过拟合了,需要减小模型复杂度或增加数据增强。
4. 加载训练好的模型:推理与ONNX导出
4.1 用YOLO-hat.py做单张图片和视频推理
项目自带的YOLO-hat.py是官方detect.py的精简版,把标签和输出格式调成了安全帽场景。实际操作时,一条命令就可以测试模型:
python YOLO-hat.py --source ./test.jpg --weights 'Safety helmet.pt' --conf 0.25逻辑说明:--source支持图片路径、目录、视频文件,甚至摄像头RTSP流。脚本会先做letterbox缩放,然后推理并画出边界框。绿色框是helmet类,红色框是head类。--conf 0.25表示置信度阈值低于0.25的预测会被过滤掉,如果你的现场误检较多,可以调到0.5,但会牺牲一部分召回率。
参数说明:如果你输入的视频帧率很高,可以用--vid-stride 2让模型每隔一帧推理一次,这样在CPU上也能做到接近实时的效果。输出结果保存在runs/detect/exp目录,每次执行自动递增下标。
4.2 用export.py导出ONNX格式
项目中的BestONNX.zip说明作者已经把模型转成了ONNX格式。实地部署时,ONNX是无处不在的标准交换格式,因为很多推理引擎都支持它。导出命令如下:
python export.py --weights 'Safety helmet.pt' --include onnx --simplify逻辑说明:--include onnx指定导出ONNX,--simplify调用onnx-simplifier对计算图做简化,减少冗余算子。导出的Safety helmet.onnx会放在weights目录下。ONNX模型可以再接上OpenVINO、TensorRT或者ONNX Runtime运行,适合将推理逻辑从训练框架中解耦。
参数说明:如果你后续要部署到NVIDIA嵌入式设备,可以加--half导出半精度FP16权重,体积缩小一半,速度也有提升。如果遇到导出后模型输出维度对不上,先确认Pytorch和onnx的版本兼容。
4.3 ONNX模型输出维度和NMS后处理
导出后的ONNX模型,输出形状是[1, 25200, 7],25200等于三个尺度的锚框总数,7分别代表[x, y, w, h, conf, class0, class1]。直接用onnxruntime推理时,还需要自己写NMS。参考这个代码片段:
import onnxruntime as ort import numpy as np import cv2 sess = ort.InferenceSession('Safety helmet.onnx') # 假设输入是640x640,先做letterbox,这里用简化示例 image = cv2.imread('test.jpg') resized = cv2.resize(image, (640, 640)) x = np.transpose(resized.astype(np.float32) / 255.0, (2, 0, 1))[None] preds = sess.run(None, {sess.get_inputs()[0].name: x})[0] # preds形状为(1, 25200, 7),这里对第一个batch做解析 boxes = preds[0] # 过滤低置信度,按类别分别NMS逻辑说明:这段代码展示的是从ONNX推理到拿到原始预测框的过程。preds[0]是25200个候选框,每个框有位置、置信度和类别得分。NMS通常用torchvision.ops.nms或onnxruntime扩展实现,但最基本的做法是先过滤掉conf小于0.25的框,再按IoU阈值去除重复框。这一部分在YOLO-hat.py里已经实现了,你自己处理ONNX时要补上。
参数说明:不同Yolov5版本导出的ONNX输出格式可能不一样,有的是一个张量,有的是三个尺度的输出。建议导出后用onnxruntime打印输出节点的shape,再做后续处理。
5. 跑通整个流程的常见坑与实用技巧
5.1 数据集路径错误与标签类别ID错位
我在几十次实验里见过的最典型错误是:训练后模型完全无法检测,或者把所有的框都画错颜色。原因几乎都指向两个地方——路径和类别顺序。hat.yaml里的train和val路径要确保yolov5的工作目录能从相对路径找到你的图片,否则训练会正常启动但数据量为0。标签转换时,classes列表的顺序必须和names一致,不然标注文件中写0,模型就会认为它是names[0]里的helmet。
5.2 显存不足时从yolov5s开始迭代
训练安全帽模型时,不需要一开始就上yolov5x。用yolov5s把流程跑通,再把模型切换成yolov5l或yolov5m,这能为你省下大把的调试时间。当显存溢出时,第一时间把batch降到4,并检查--workers参数是否过高,推荐改成4。另外,在训练命令中加入--cache-images可以大幅提升数据读取速度,但需要至少4G可用内存,否则会拖慢系统。
5.3 用TensorRT加速边缘部署
如果你的最终目标是进入真实生产,我建议把ONNX再转成TensorRT engine。TensorRT在NVIDIA显卡上能获得3到5倍的推理速度提升,尤其适合Jetson Nano这类功耗受限设备。转换方式很简单,NVIDIA官方提供了trtexec工具,一条命令即可完成:trtexec --onnx=Safety helmet.onnx --saveEngine=safety.engine --fp16。转换时需要显卡与目标部署环境一致,比如在PC上转好再拷到Jetson上,往往需要重新构建。这个优化留给那些想继续在项目上做扩展的同学,答辩时提到这点会显得项目更完整。
本文还有配套的精品资源,点击获取