ARTICLE DETAIL

资讯详情

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

反光服与安全帽检测:YOLOv5训练自己的数据集实战指南

反光服与安全帽检测:YOLOv5训练自己的数据集实战指南 简介这份资源面向计算机视觉初学者与工地安全智能监控开发者提供一套围绕YOLOv5构建的安全装备检测项目覆盖反光服、安全帽及施工人员穿戴识别等场景可用于模型训练、推理验证与二次开发。压缩包共47个文件约16.25MB包含16个Python脚本、14个YAML配置、6张JPG示例图、4个Shell脚本及3份Markdown说明文档另有pt权重、ipynb教程与txt提示文件兼顾训练、测试与部署流程。项目内附中英文README与操作说明并给出预训练权重best.pt、推理脚本detect.py、训练脚本train.py及voc_label转换工具方便读者直接复现检测效果并替换自有数据。目前已有387人学习下载适合希望快速上手YOLOv5目标检测、搭建施工安全穿戴识别系统的读者参考。1. 反光服与安全帽检测从一份数据集到能跑通的 YOLOv5 训练链路工地出入口的摄像头每天拍下几万帧画面真正需要报警的往往只有几十帧——有人没戴安全帽或者反光服被外套遮住。靠人盯着屏幕翻录像漏检几乎是必然的。反光服检测数据集、helmet 检测 yolov5、工作服反光服检测数据集、安全帽检测、施工人员佩戴检测这几个词指向的是同一件事用目标检测模型自动判断施工人员有没有按规定穿戴防护装备。这类需求在智慧工地、厂区安防、电力巡检里非常普遍落地路径也相对成熟——YOLOv5 训练自己的数据集部署到边缘盒子或服务器上做实时推理。这篇文章面向想自己跑通这条链路的工程师从数据集结构讲到训练参数再到部署前的量化取舍把中间容易翻车的地方一次说清。2. 数据集怎么组织反光服、安全帽、工作服三类标注的目录与格式2.1 先搞清楚要检测的类别边界拿到一份标注数据第一件事不是急着训练而是把类别定义对齐。施工人员佩戴检测常见的类别划分有三种粒度粗粒度只分person和helmet反光服不单独标靠颜色后处理判断。中粒度分helmet、vest、person这是大多数反光服检测数据集采用的方案。细粒度把安全帽再拆成helmet_yes/helmet_no反光服拆成vest_yes/vest_no直接输出穿戴状态。我一般推荐中粒度起步。原因是细粒度虽然省去了后处理逻辑但标注成本高而且helmet_no这类负样本在不同光照下边界很模糊模型容易学偏。中粒度配合简单的区域匹配逻辑反而更稳。类别确定后检查标注文件里有没有混入其他类。常见的情况是数据集里混了head、hat、clothes这类同义类训练前必须统一映射否则模型会在相似目标上反复震荡。2.2 YOLOv5 要求的数据目录结构YOLOv5 对目录结构有固定约定不按这个来会在训练启动时报路径错误。标准结构如下dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamlimages/train和labels/train里的文件必须同名只是扩展名不同。比如images/train/0001.jpg对应labels/train/0001.txt。如果标注是 VOC 的 XML 格式需要先转成 YOLO 的 txt 格式每行是class_id x_center y_center width height坐标全部归一化到 0~1。转换脚本的核心逻辑import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, classes, img_w, img_h): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in classes: continue cls_id classes.index(cls_name) bbox obj.find(bndbox) x1 float(bbox.find(xmin).text) y1 float(bbox.find(ymin).text) x2 float(bbox.find(xmax).text) y2 float(bbox.find(ymax).text) # 归一化并转为中心点宽高 x_c (x1 x2) / 2.0 / img_w y_c (y1 y2) / 2.0 / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h lines.append(f{cls_id} {x_c:.6f} {y_c:.6f} {w:.6f} {h:.6f}) return lines这段代码里classes的顺序必须和data.yaml里的names完全一致否则类别会错位。img_w和img_h要从对应图片读取不能写死因为数据集里往往混了不同分辨率的图。2.3 data.yaml 的写法与路径坑data.yaml是训练入口配置文件内容大致如下path: /home/user/dataset train: images/train val: images/val nc: 3 names: [helmet, vest, person]path用绝对路径最稳。用相对路径时YOLOv5 会相对于它自己的运行目录去解析经常出现「找不到训练集」的报错。nc是类别数必须和names长度一致。names的顺序就是标注文件里class_id的顺序改一个就得全改。提示如果训练启动后 loss 一直是 nan 或者不下降先检查data.yaml里的nc和标注里的最大 class_id 是否匹配。类别数写多了或写少了模型输出层维度对不上训练会直接崩。3. 用 YOLOv5 训练自己的数据集从环境到第一个能收敛的模型3.1 环境准备与版本选择YOLOv5 的仓库更新比较频繁不同版本对 PyTorch 和 CUDA 的要求不一样。我一般会锁定一个稳定组合PyTorch 1.13 CUDA 11.7或者 PyTorch 2.0 CUDA 11.8。太新的组合有时候会和torchvision的算子对不上报一些莫名其妙的错。安装步骤git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt如果要用 GPU 训练装完后再确认一下python -c import torch; print(torch.cuda.is_available())输出True才算正常。输出False的话大概率是 PyTorch 装成了 CPU 版需要去官网按 CUDA 版本重新装。3.2 训练命令与关键参数最小可跑的训练命令python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data dataset/data.yaml \ --weights yolov5s.pt \ --project runs/train \ --name helmet_vest逐项说明--img 640输入分辨率。反光服和安全帽在画面里通常不会太小640 够用。如果小目标多可以提到 1280但显存占用会翻倍。--batch 16批大小。显存不够就降到 8 或 4但太小会让 BatchNorm 统计不稳收敛变慢。--epochs 100施工场景的数据集一般 100~300 轮足够。看val/obj_loss和mAP0.5曲线如果 50 轮后还在明显下降可以再加。--weights yolov5s.pt从预训练权重开始。反光服检测数据集通常几千到几万张从头训容易过拟合预训练权重能省很多时间。--data指向data.yaml的路径。训练过程中重点看几个指标box_loss、obj_loss、cls_loss应该整体下降mAP0.5应该上升。如果obj_loss不降反升通常是标注里有大量空文件或者框的位置严重偏移。3.3 超参数怎么调反光服场景的几个经验值YOLOv5 的超参数在data/hyp.scratch.yaml里训练时可以用--hyp指定自定义文件。针对反光服和安全帽场景我一般会改这几个参数默认值建议值原因lr00.010.005数据集不大时降低初始学习率减少震荡mosaic1.00.5马赛克增强太强会让小目标安全帽变形适当降低hsv_v0.40.6工地光照变化大提高亮度扰动增强泛化fl_gamma0.01.5开启 Focal Loss缓解正负样本不均衡mosaic降到 0.5 是我踩过坑之后的习惯。默认 1.0 时四张图拼在一起安全帽经常被裁掉一半模型学到的特征不完整。降到 0.5 后验证集上的mAP0.5通常能涨 2~3 个点。fl_gamma开启后要观察cls_loss的变化。如果降得太快可能是负样本被过度抑制反而漏检增多这时候把值调回 0.5 左右。3.4 训练完怎么验证混淆矩阵和 PR 曲线训练结束后runs/train/helmet_vest/下会生成confusion_matrix.png和PR_curve.png。混淆矩阵能直接看出类别之间的误判情况。反光服检测里最常见的是vest被误判成person因为反光服穿在人身上标注框经常有重叠。如果这个误判比例高说明vest的标注框不够紧或者person类里包含了太多穿反光服的样本。PR 曲线看每个类别的 AP。helmet的 AP 通常最高因为安全帽形状固定、颜色鲜明。vest的 AP 往往低一些因为反光条在不同角度下反光强度差异很大模型不容易学稳。注意验证时不要只看mAP0.5还要看mAP0.5:0.95。后者对框的定位精度更敏感。如果两者差距很大说明框的位置不够准可能需要检查标注质量或者调整--img分辨率。4. 避坑与排查训练反光服检测模型时最容易翻车的 5 个地方4.1 现象训练 loss 正常下降但验证 mAP 一直是 0原因data.yaml里的val路径指向了空目录或者验证集图片和标注没有对应上。YOLOv5 在验证时如果找不到标注会跳过所有样本mAP 自然为 0。解决手动检查labels/val/下的 txt 文件数量是否和images/val/下的图片数量一致。不一致的话用脚本对比文件名把缺失的补上或删掉多余的图片。4.2 现象模型把所有人都框成 vesthelmet 几乎不检出原因vest和person的标注框高度重叠模型学到的特征区分度不够。另外如果helmet的样本数远少于vest类别不均衡会让模型偏向多数类。解决先统计每个类别的标注框数量。如果helmet占比低于 15%考虑对helmet类做过采样或者在hyp里调高cls的损失权重。更直接的办法是检查标注把戴安全帽的人头区域单独框出来而不是框整个人。4.3 现象推理时反光服漏检严重尤其是背对镜头的人原因反光服的反光条主要在正面和侧面背面反光面积小。如果训练集里背对镜头的样本少模型没学到背面特征。解决在数据增强里开启flipud和fliplr增加视角多样性。另外可以收集一些背对镜头的负样本手动标注后加入训练集。如果条件允许用--img 1280提高分辨率让反光条的细节更清晰。4.4 现象训练到一半突然报 CUDA out of memory原因--batch设大了或者--img分辨率太高。YOLOv5 在训练过程中会缓存一些中间特征显存占用不是线性的。解决先把--batch减半如果还报错就降--img。另外可以加--workers 4限制数据加载进程数有时候显存是被数据加载线程占满的。如果用的是多卡检查--device参数有没有指定错。4.5 现象模型在测试集上表现很好部署到实际摄像头后误报暴增原因训练集和实际场景的分布不一致。训练集里的图片可能是从公开数据集来的背景干净、光照均匀实际摄像头画面里有雨雾、逆光、遮挡模型没见过。解决从实际摄像头截取一批画面人工标注后加入训练集哪怕只有几百张也能明显改善。另外可以在推理前加一个简单的图像预处理比如直方图均衡化减少光照差异的影响。5. 从训练到部署量化、导出与边缘设备上的取舍5.1 导出 ONNX 和 TensorRT 的差异训练完的.pt权重不能直接上边缘设备需要先导出。YOLOv5 自带export.pypython export.py --weights runs/train/helmet_vest/weights/best.pt --include onnx导出 ONNX 后可以用onnxruntime做推理也可以用 TensorRT 进一步加速。两者的区别格式推理速度精度损失适用场景PyTorch .pt基准无服务器 GPUONNX快 1.5~2 倍几乎无跨平台 CPU/GPUTensorRT FP16快 3~5 倍很小NVIDIA 边缘设备TensorRT INT8快 5~8 倍需要校准对延迟极敏感反光服检测对精度要求不算极端FP16 通常够用。INT8 量化需要准备校准集如果校准集选得不好vest类的 AP 可能掉 5~10 个点。5.2 树莓派和 RK3568 上的部署注意点树莓派 4B 跑 YOLOv5s 的 ONNX 模型单帧推理大概 200~400ms勉强能到 3~5 FPS。如果要做实时检测建议用yolov5n或者把输入分辨率降到 320。树莓派 5 的 CPU 强一些但瓶颈还是在内存带宽上--img 640的模型跑起来依然吃力。RK3568 这类带 NPU 的芯片需要把模型转成 RKNN 格式。转换时注意量化方式hybrid量化比全整型量化精度好但速度稍慢。反光服检测里vest类的反光条在量化后容易丢失细节建议对vest类单独做一轮校准。5.3 一个实用的后处理技巧用颜色辅助判断反光服模型输出的vest框可以再用一个简单的颜色判断做二次确认。反光服通常是荧光黄或荧光橙在 HSV 空间里有明显的色相范围。对vest框内的区域做颜色直方图统计如果荧光色占比低于阈值就把这个框的置信度降权。import cv2 import numpy as np def check_vest_color(image, box, threshold0.15): x1, y1, x2, y2 box roi image[y1:y2, x1:x2] hsv cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) # 荧光黄和荧光橙的色相范围 mask_yellow cv2.inRange(hsv, (20, 100, 100), (35, 255, 255)) mask_orange cv2.inRange(hsv, (10, 100, 100), (20, 255, 255)) mask mask_yellow | mask_orange ratio np.count_nonzero(mask) / mask.size return ratio threshold这个函数返回True表示框内确实有反光服颜色False则可能是误检。threshold设 0.15 是我在几个工地场景里试出来的经验值太低会放过误检太高会漏掉被遮挡的反光服。这个后处理不增加多少计算量但能明显降低误报率。5.4 我自己的习惯先跑通再优化每次拿到新的反光服检测数据集我不会一上来就调参。先用yolov5s.pt跑 10 个 epoch看看 loss 曲线和验证集上的预测效果。如果 10 轮后模型已经能框出大部分安全帽和反光服说明数据质量没问题再换yolov5m或yolov5l加轮数。如果 10 轮后什么都框不出来先回去查标注格式和data.yaml别在训练参数上浪费时间。这个习惯帮我省过很多次「调了半天参结果是路径写错」的后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表