资讯动态

反光服与安全帽检测数据集:YOLOv5训练与边缘部署实战

发布时间:2026/10/4 5:50:31 来源:尧图企业网站定制
简介这份资源面向计算机视觉初学者与工地安全智能监控方向的开发者提供一套围绕YOLOv5构建的安全装备佩戴检测方案覆盖反光服、安全帽及施工人员穿戴等典型场景可用于训练与验证目标检测模型。压缩包共47个文件约16.25MB包含16个Python脚本、14个YAML配置、6张示例图片以及4个Shell脚本、3份Markdown说明、2个TXT文档、1个Jupyter Notebook和1个预训练权重文件涵盖训练、推理、数据配置与结果展示等环节。目前已有387人学习下载。资源内附项目说明与解压提示目录结构清晰便于读者快速理解YOLOv5在安全装备检测中的工程组织方式并基于现有脚本与权重开展训练、推理和效果验证适合作为课程设计、毕业设计或工地安全监控原型的参考起点。1. 反光服与安全帽检测数据集从一堆标注图到能跑的训练集工地上真正难的不是把 YOLOv5 跑起来而是拿到一份能直接训练的反光服检测数据集、安全帽检测数据集。标题里这个压缩包本质上是把「工作服反光服检测数据集」和「安全帽检测」两类标注图打包在一起目标场景是施工人员佩戴检测——判断画面里的人有没有穿反光背心、有没有戴安全帽。这类数据集的典型形态是 VOC 的 XML 或 YOLO 的 txt 标注配一堆 jpg 原图类别通常就三五个person、helmet、vest、head 之类。它解决的是「从零标注成本太高」的问题。一个工人戴没戴安全帽人工标一千张图要一两天而现成的施工人员佩戴检测数据集能让你当天就把 yolov5 训练自己的数据集这条链路跑通。适合两类人一类是想验证工地安全监控方案可行性的算法工程师一类是要在树莓派4b部署yolov5、rk3568 这类边缘设备上做落地的嵌入式开发者。前提是你得先搞清楚手里的标注格式、类别定义和划分比例否则后面全是玄学。2. 拆开压缩包先看什么标注格式、类别与划分拿到数据集别急着写训练脚本先花二十分钟把目录结构和标注格式摸清楚。这一步做扎实后面能省掉大量「训练 loss 不降」的血泪经验。2.1 判断是 VOC XML 还是 YOLO txt打开标注目录如果每个 jpg 对应一个同名 xml里面是objectnamehelmet/namebndbox...这种结构那就是 VOC 格式如果对应的是同名 txt每行是class_id cx cy w h五个归一化到 0~1 的数那就是 YOLO 格式。两种格式的转换逻辑完全不同先确认再动手。# 看标注文件后缀分布快速判断格式 find ./annotations -type f | sed s/.*\.// | sort | uniq -c # 输出示例 # 1200 xml - VOC 格式 # 1200 txt - YOLO 格式上面这条命令统计标注目录里所有文件的后缀。如果 xml 和 txt 数量一致且都等于图片数说明标注是完整的如果某个后缀数量明显偏少说明有图漏标训练前必须处理掉否则这些图会被当成纯背景样本模型学不到目标特征。2.2 类别名和类别 id 必须对齐VOC 里类别是字符串YOLO 里是整数 id这个映射关系一旦错位模型会把安全帽学成反光服。常见做法是建一个classes.txt每行一个类别名行号就是 id。# 生成 classes.txt 并统计各类别实例数 import os, glob from collections import Counter import xml.etree.ElementTree as ET classes set() counter Counter() for xml_file in glob.glob(./annotations/*.xml): tree ET.parse(xml_file) for obj in tree.findall(object): name obj.find(name).text.strip() classes.add(name) counter[name] 1 classes sorted(classes) with open(classes.txt, w) as f: f.write(\n.join(classes)) print(类别列表:, classes) print(实例分布:, dict(counter))这段代码遍历所有 XML收集类别名并统计每个类别的实例数量。classes.txt的行号从 0 开始就是 YOLO 训练时用的 class_id顺序必须和后续 data.yaml 里的 names 完全一致。实例分布能帮你判断类别是否均衡——如果 helmet 有 8000 个实例而 vest 只有 500 个训练时 vest 的召回率会明显偏低需要做重采样或加权。2.3 训练集/验证集划分的坑很多人直接按 8:2 随机切分结果同一段视频的连续帧被分到训练集和验证集两边验证指标虚高。正确做法是按「场景」或「视频源」划分让验证集里的背景、光照、角度和训练集不重叠。import os, random, shutil random.seed(42) img_dir ./images train_dir, val_dir ./dataset/images/train, ./dataset/images/val os.makedirs(train_dir, exist_okTrue) os.makedirs(val_dir, exist_okTrue) imgs [f for f in os.listdir(img_dir) if f.endswith(.jpg)] random.shuffle(imgs) split int(len(imgs) * 0.8) for i, img in enumerate(imgs): dst train_dir if i split else val_dir shutil.copy(os.path.join(img_dir, img), os.path.join(dst, img))random.seed(42)保证划分可复现换台机器跑结果一致。split控制比例施工场景一般 8:2 够用样本少于 2000 张时建议 7:3让验证集更有代表性。复制而不是移动是为了保留原始数据后面调参要反复重新划分。3. 用 YOLOv5 训练反光服与安全帽检测模型数据理顺了接下来是训练。YOLOv5 的仓库结构成熟但施工人员佩戴检测这个场景有几个参数需要专门调默认配置直接跑往往效果一般。3.1 环境准备与最小可跑命令先确认 PyTorch 和 CUDA 版本匹配然后克隆 YOLOv5 仓库装依赖。不要用最新版 torch 硬配老 CUDA版本对不上会报一堆看不懂的错。# 创建环境并安装依赖 conda create -n yolov5 python3.9 -y conda activate yolov5 pip install torch1.13.1 torchvision0.14.1 --index-url https://download.pytorch.org/whl/cu117 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txttorch 1.13.1 配 cu117 是经过大量项目验证的稳定组合树莓派和 rk3568 的模型导出也兼容。装完用python -c import torch; print(torch.cuda.is_available())确认 GPU 可用返回 False 就先解决驱动问题别急着训练。3.2 data.yaml 与模型配置在 yolov5/data 下新建safety.yaml指向你的数据集并声明类别。# safety.yaml path: ../dataset train: images/train val: images/val nc: 3 names: [person, helmet, vest]nc是类别数必须和 classes.txt 行数一致。names顺序就是 class_id 顺序写反了模型输出全乱。路径用相对路径方便整个项目打包迁移到别的机器。3.3 训练命令与关键参数python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data data/safety.yaml \ --weights yolov5s.pt \ --cfg models/yolov5s.yaml \ --hyp data/hyps/hyp.scratch-low.yaml \ --cache--img 640是输入分辨率工地监控画面里安全帽占比小可以提到 960 或 1280但显存翻倍。--batch 16在 8G 显存上跑 640 分辨率比较稳显存不够就降到 8 并加--accumulate 2模拟大 batch。--weights yolov5s.pt用预训练权重比从头训收敛快得多。--cache把图片缓存到内存小数据集能明显加速数据集超过 2 万张就别开内存扛不住。3.4 训练过程看什么指标启动后重点盯三个数box_loss、obj_loss、mAP0.5。box_loss 持续下降说明框回归在学obj_loss 震荡不降通常是学习率太大或标注有问题。mAP0.5 在 30 epoch 后应该开始爬升如果 50 epoch 还趴在 0.1 以下八成是类别 id 对不上或标注坐标没归一化。# 训练结束后用验证集跑一遍看每类指标 python val.py --data data/safety.yaml --weights runs/train/exp/weights/best.pt --img 640val.py 会输出每类的 P、R、mAP。如果 person 类 mAP 0.9 而 helmet 只有 0.4说明安全帽样本太少或太小需要针对性补充数据或调 anchor。4. 施工人员佩戴检测的避坑与排查清单这一节是我踩过的坑里最费时间的几条按「现象 → 原因 → 解决」写遇到问题直接对号入座。4.1 训练 loss 不降mAP 一直是 0现象跑了几十个 epochbox_loss 在 0.5 附近横盘mAP 始终 0。原因最常见的是标注坐标没归一化YOLO 要求 cx cy w h 都在 0~1 之间如果直接填了像素值模型完全学不到。解决写脚本检查所有 txt 标注任何一行有大于 1 的值就是没归一化重新转换。4.2 验证集指标很高实际推理一塌糊涂现象val 的 mAP 0.85拿工地实拍图一测安全帽全漏。原因训练集和验证集来自同一批视频背景高度相似模型过拟合了场景而不是目标。解决按视频源划分数据集验证集里必须包含训练集没见过的工地、光照和角度。4.3 反光服和普通衣服混淆现象模型把穿白色 T 恤的工人也框成 vest。原因反光服的特征是反光条如果训练图里反光条不明显或类别定义把「工作服」和「反光服」混在一起模型学到的就是颜色而非反光特征。解决统一类别定义只标有反光条的背心为 vest普通工装不标补充逆光、夜间等反光条明显的样本。4.4 小目标安全帽检测不到现象远处工人头顶的安全帽完全没框。原因640 分辨率下远处安全帽可能只有十几个像素YOLOv5 的 P3 特征图也覆盖不到。解决提高输入分辨率到 1280或在数据增强里加mosaic和copy_paste把安全帽复制粘贴到不同位置增加小目标样本。4.5 训练到一半显存爆了现象前几个 epoch 正常突然 CUDA out of memory。原因--cache把图片全加载进内存数据集大时内存耗尽或者 dataloader 的 worker 数太多。解决去掉--cache把--workers从默认 8 降到 4batch 从 16 降到 8 并加--accumulate 2。5. 从训练到部署导出 ONNX 与边缘设备验证模型训完只是开始施工人员佩戴检测最终要落到摄像头或边缘盒子上。这一步的核心是把 PyTorch 权重转成推理引擎能吃的格式并验证转换前后精度不掉。5.1 导出 ONNX 并检查输出节点python export.py \ --weights runs/train/exp/weights/best.pt \ --include onnx \ --img 640 \ --batch 1 \ --simplify--include onnx指定导出格式--simplify用 onnx-simplifier 精简计算图去掉冗余节点边缘设备上推理更快。--batch 1是推理时的批大小部署场景一般单张输入。导出后在同级目录生成 best.onnx用 netron 打开确认输入是1x3x640x640输出是1x25200x(5nc)。5.2 转换前后精度对齐导出后必须验证 ONNX 和原模型输出一致否则部署上去精度掉点都找不到原因。import onnxruntime as ort import torch, numpy as np # 加载 ONNX 和原模型同一张图推理对比 sess ort.InferenceSession(best.onnx) img np.random.rand(1, 3, 640, 640).astype(np.float32) onnx_out sess.run(None, {sess.get_inputs()[0].name: img})[0] model torch.hub.load(ultralytics/yolov5, custom, pathbest.pt) torch_out model(torch.from_numpy(img)).detach().numpy() diff np.abs(onnx_out - torch_out).max() print(最大输出差异:, diff) # 应小于 1e-3这段代码用同一张随机图分别跑 ONNX 和 PyTorch比较输出张量的最大差异。差异小于 1e-3 说明转换无损大于 0.01 就要检查导出时的 opset 版本和 simplify 是否引入了不兼容算子。随机图只是验证数值一致性真正评估精度还要用验证集跑一遍 mAP。5.3 边缘设备上的输入预处理对齐树莓派4b 或 rk3568 上部署时最容易翻车的是预处理。训练时 YOLOv5 做了 letterbox 填充保持长宽比推理时如果直接 resize 到 640x640目标比例变形精度会掉。部署代码里必须复现 letterbox按长边缩放到 640短边居中填充灰色 114。def letterbox(img, new_shape640, color(114, 114, 114)): h, w img.shape[:2] r min(new_shape / h, new_shape / w) new_unpad (int(round(w * r)), int(round(h * r))) dw, dh new_shape - new_unpad[0], new_shape - new_unpad[1] dw, dh dw // 2, dh // 2 img cv2.resize(img, new_unpad) img cv2.copyMakeBorder(img, dh, dh, dw, dw, cv2.BORDER_CONSTANT, valuecolor) return imgr是缩放比例取长边缩放到 640 的最小值保证整图放得下。dw, dh是两侧填充量居中填充。填充色 114 是 YOLOv5 训练时的默认值部署时用别的颜色会造成输入分布偏移这个细节很多人忽略实测能差 2~3 个点 mAP。5.4 量化到 INT8 的取舍rk3568 这类 NPU 支持 INT8 量化速度能翻倍但安全帽这种小目标量化后容易掉点。我的习惯是先在验证集上对比 FP16 和 INT8 的 mAP如果 INT8 掉超过 3 个点就只量化 backbone检测头保留 FP16。量化校准集必须用真实工地图不能用随机噪声否则量化参数完全偏掉。# 用 onnxruntime 做动态量化示例 python -m onnxruntime.quantization.preprocess --input best.onnx --output best_pre.onnx python -m onnxruntime.quantization.quantize --input best_pre.onnx --output best_int8.onnx --calibrate_dataset calib/calib/目录放 100~200 张真实工地图量化时统计激活值分布。校准集覆盖的场景越全量化后精度越稳。这一步没有后悔药校准集偷懒部署上去就是各种漏检。这套流程我从数据集清洗到边缘部署跑过好几轮最大的教训是别在标注格式和类别对齐上省时间前面省十分钟后面调参能搭进去两天。数据集的质量决定模型上限YOLOv5 只是帮你逼近这个上限。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑