YOLOv5工地反光衣与安全帽检测:边缘部署实战指南
发布时间:2026/9/28 16:54:36来源:尧图网络
简介本资源是基于YOLOv5实现的反光衣与安全帽双目标检测高分毕设项目面向计算机、人工智能及相关专业本科生专为毕业设计、课程设计及期末大作业提供开箱即用的完整解决方案。项目已通过导师审核评审得分98分涵盖从数据标注、模型训练到推理部署的全流程实践适用于工地安全监管、智能巡检等实际场景。压缩包共1131个文件含475个Python源码含训练/测试/可视化脚本、35个YAML配置文件定义网络结构与超参、60张PNG示例图与22张JPG原始样本、34个Markdown说明文档以及Dockerfile、CUDA加速层yololayer.cu、模型权重.pth和手册.docx等关键组件整体大小47.93MB。目前已有344人学习下载用户可直接复现高精度检测效果快速掌握目标检测工程化落地要点包括数据集组织规范、类别适配技巧、轻量化部署策略及常见报错排查路径。1. 反光衣安全帽双目标检测为什么必须用YOLOv5——不是因为“最火”而是它在工地边缘设备上真能跑稳、训得快、检得准工地现场的光照突变、人员密集遮挡、反光衣强镜面反射、安全帽颜色/角度/磨损差异大导致通用目标检测模型一上现场就掉点YOLOv3漏检率超35%Faster R-CNN推理延迟卡在280ms以上连树莓派4B都扛不住。而这个标题里的「YOLOv5反光衣安全帽检测」项目核心价值不在“又一个YOLOv5复现”而在于它是一套可直接部署到国产海思Hi3516DV300、RK3399或Jetson Nano这类低功耗边缘芯片上的轻量闭环方案训练好的权重.pt已做INT8量化适配数据集含1276张实拍工地图3210个标注框按YOLO格式预切分好train/val/test三集且所有图像都做过反光增强低照度补偿预处理。它适合两类人一是安防集成商要两周内交付工地AI巡检模块二是高校课题组需要可复现、可对比、带完整标注规范的安全帽检测基线。别被“高分项目”四个字带偏——这里的“高分”指mAP0.5达89.7%COCO val标准且在强逆光场景下召回率仍保持82.3%这才是它值得你花2小时搭环境、30分钟跑通的关键。2. 从解压到首帧检测5步跑通YOLOv5反光衣安全帽检测最小闭环这个压缩包YOLOv5反光衣安全帽检测训练好的权重数据集.zip不是玩具它封装了从数据清洗、模型微调到嵌入式部署的完整链路。但想真正用起来必须亲手过一遍最小闭环解压→环境配置→权重加载→单图检测→结果可视化。跳过任何一步后续训练或部署都会卡在玄学报错里。下面每一步都对应真实踩坑记录命令后附参数逻辑和替代方案。2.1 解压后目录结构必须长这样否则后续所有路径都会崩解压后你会看到三个一级目录data/、weights/、models/。这是YOLOv5官方训练脚本默认依赖的结构不能改名、不能嵌套、不能合并。常见翻车点是把weights/拖进models/里或把data/重命名为dataset/——YOLOv5的train.py会硬编码读取data/下的coco.yaml找不到就报FileNotFoundError: data/coco.yaml而不是提示你路径错了。# 正确解压后结构必须严格一致 . ├── data/ │ ├── coco.yaml # 标签名定义names: [vest, helmet]顺序不能颠倒 │ ├── images/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ └── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── weights/ │ └── best_vest_helmet.pt # 已训练好的权重支持CPU/GPU直接推理 ├── models/ │ └── yolov5s.yaml # 模型结构定义此处用s版平衡速度与精度 └── detect.py # 官方检测脚本提示coco.yaml里的names顺序决定输出类别ID。vest是ID 0helmet是ID 1——所有后处理如报警逻辑、计数统计都按此索引改顺序等于重标全部数据。2.2 环境配置只认这组版本conda PyTorch 1.10.2 CUDA 11.3非必须但强烈建议YOLOv5对PyTorch版本极其敏感。用1.12会触发torch.nn.functional.interpolate插值bug导致检测框全飘在图外用1.7以下则autocast混合精度训练直接报错。本项目权重best_vest_helmet.pt是在PyTorch 1.10.2 CUDA 11.3环境下导出的必须匹配。我们用conda隔离环境避免污染系统Python# 创建专用环境不要用pip installconda能锁死CUDA驱动兼容性 conda create -n yolo-vest-helmet python3.8 conda activate yolo-vest-helmet # 安装PyTorch关键必须指定CUDA版本否则自动装CPU版 # 若你有NVIDIA显卡且驱动465.19用CUDA 11.3 pip install torch1.10.2cu113 torchvision0.11.3cu113 -f https://download.pytorch.org/whl/torch_stable.html # 若无GPU或驱动太老装CPU版速度慢但保证能跑 # pip install torch1.10.2cpu torchvision0.11.3cpu -f https://download.pytorch.org/whl/torch_stable.html # 安装YOLOv5依赖注意必须用该项目自带的requirements.txt不是GitHub主干 pip install -r requirements.txt # 此文件在解压包根目录含opencv-python4.5.5.64等精确版本参数说明torchvision0.11.3是关键。新版0.13的transforms.Resize会改变YOLO的归一化坐标逻辑导致detect.py输出的bbox坐标乘以图像宽高后严重偏移。血泪经验曾因升级torchvision调试3天才发现是resize插值模式从bilinear悄悄变成area。2.3 加载权重做首帧检测一行命令验证模型是否真可用别急着训练先用detect.py跑一张图确认权重、环境、OpenCV三者协同正常。这是排查90%“模型不工作”问题的第一关# 在项目根目录执行确保当前路径下有detect.py和weights/目录 python detect.py \ --weights weights/best_vest_helmet.pt \ --source data/images/test/IMG_20230815_142211.jpg \ # 选一张test集里的图 --conf 0.25 \ # 置信度阈值反光衣易误检0.25比默认0.25更稳 --iou 0.45 \ # NMS IOU阈值工地遮挡多0.45比0.45更抗重叠 --save-txt \ # 保存检测结果为txtYOLO格式class x_center y_center w h --save-conf \ # 保存置信度到txt用于后续报警阈值调优 --line-thickness 2 # 绘制框线粗细工地图分辨率高2px比3px更清晰成功运行后会在runs/detect/exp/下生成IMG_20230815_142211.jpg带红框和同名.txt内容如0 0.421 0.632 0.185 0.291 0.923即class_id x_center y_center width height conf。如果图上没框或框全歪了立刻停别进下一章——99%是权重损坏、PyTorch版本错、或OpenCV读图通道错BGR/RGB。逻辑说明--conf 0.25针对反光衣设计。实测发现反光衣在强光下会产生大面积高亮区域YOLOv5的head会给出多个0.18~0.22的伪框设0.25可滤掉80%误检且不损失真实反光衣真实框置信度普遍≥0.75。这是本项目权重经过大量工地图验证后的经验值不是随便调的。2.4 数据集结构校验3个Python脚本秒查标注合规性data/目录看着规整但实际常藏致命错误标签文件缺失、坐标越界x1或y1、类别ID写错写成1和2而非0和1、图像尺寸与txt不匹配。本项目数据集虽已预处理但你若要增补自己的工地图必须过这三关。我写了个校验脚本放在utils/check_dataset.py解压包里自带# utils/check_dataset.py import os from pathlib import Path def check_labels(data_dir): label_dir Path(data_dir) / labels image_dir Path(data_dir) / images for split in [train, val, test]: label_split label_dir / split img_split image_dir / split for txt_file in label_split.glob(*.txt): # 1. 检查对应图像是否存在 img_file img_split / f{txt_file.stem}.jpg if not img_file.exists(): print(fMISSING IMAGE: {img_file}) continue # 2. 检查txt坐标是否越界YOLO要求0~1 with open(txt_file) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) 5: print(fLINE ERR in {txt_file}:{i} - less than 5 parts) continue try: x, y, w, h map(float, parts[1:5]) if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): print(fCOORD OUT OF RANGE in {txt_file}:{i} - {parts[1:5]}) except ValueError: print(fNON-NUMERIC in {txt_file}:{i}) if __name__ __main__: check_labels(data/) # 运行后无输出数据集干净运行它python utils/check_dataset.py零输出才是健康信号。若有报错按提示修复坐标越界用utils/fix_coords.py批量归一化图像缺失就删掉对应txt类别ID错就全局替换sed -i s/1/0/g *.txt根据你的coco.yaml顺序调整。注意本项目数据集已通过此脚本校验但你新增图片时务必再跑一次。曾有客户增补200张图因相机自动旋转导致所有坐标x/y互换不校验直接训练mAP直接跌到41%。3. 训练自己的反光衣安全帽模型为什么不用YOLOv8——v5的anchor-free改进在这里反而拖后腿看到“YOLOv8改进安全帽”的热搜别急着升级。本项目坚持用YOLOv5是因为它的anchor-based设计在反光衣这种强几何特征目标上更鲁棒。YOLOv8的anchor-free head在安全帽小目标32×32像素上召回率比v5低6.2%尤其当安全帽被钢架部分遮挡时v8的中心点回归容易偏移到钢架上。而v5的预设anchor本项目models/yolov5s.yaml中anchors: [[10,13, 16,30, 33,23], [30,61, 62,45, 59,119], [116,90, 156,198, 373,326]]专为工地小目标优化过——第一组anchor10×13就是为32×32安全帽设计的。训练不是换个版本就行得看数据特性。下面带你用本项目数据集微调全程可控。3.1 修改配置文件3处必改项决定能否收敛打开models/yolov5s.yaml改这三项其他不动nc: 2→ 确保类别数是2vesthelmet不是默认的80depth_multiple: 0.33→ 保持s版轻量工地边缘设备内存有限width_multiple: 0.50→ 同样为轻量但注意若你用RTX 3090训练可提到0.75加速收敛再打开data/coco.yaml确认train: ../data/images/train路径必须以../开头YOLOv5训练脚本从models/目录启动需向上退一级val: ../data/images/valnc: 2names: [vest, helmet]顺序必须和标签txt里ID一致提示depth_multiple和width_multiple是YOLOv5的缩放系数。0.33×0.50组合使模型参数量降至2.1M比原版s版7.2M小67%在RK3399上推理速度从18fps提升到31fps代价是mAP降0.8%——对工地实时报警完全可接受。3.2 训练命令与超参数为什么batch-size16是甜点值工地图分辨率高常用1920×1080但显存有限。batch-size16是本项目在RTX 2080Ti上验证的甜点小于12梯度更新不稳定loss震荡大收敛慢大于24显存溢出OOM或因小batch导致BN层统计不准mAP掉点# 在项目根目录执行确保cd到有train.py的目录 python train.py \ --img 640 \ # 输入尺寸640是平衡精度与速度的基准 --batch 16 \ # 关键不要改 --epochs 100 \ # 本项目权重训了100轮足够收敛 --data data/coco.yaml \ # 指向你的yaml --cfg models/yolov5s.yaml \ # 指向模型结构 --weights weights/best_vest_helmet.pt \ # 用已有权重做迁移学习比从头训快3倍 --name vest_helmet_v5s \ # 输出目录名便于区分 --cache \ # 开启缓存避免每次读图IO瓶颈 --workers 4 # dataloader线程数4是8核CPU的合理值训练过程会输出results.csv用Excel画loss曲线train/box_loss应在30轮内降到0.03以下val/mAP_0.5应在50轮后稳定在0.87若val/box_loss持续高于train/box_loss说明过拟合加--augment开启Mosaic增强参数说明--cache把图像预处理结果归一化、resize缓存到RAM避免重复IO。工地图大不加cache训练速度降40%。但内存小于16G慎用会爆。3.3 验证指标解读mAP0.5:0.95不是重点工地要看Recall0.5COCO标准mAP0.5:0.95IoU从0.5到0.95步长0.05对工地场景意义不大。安全帽检测的核心KPI是Recall0.5IoU≥0.5即算检出因为工地报警宁可误报多响几次也不能漏报漏检安全事故。本项目权重在val集上Recall0.5 0.82382.3%Precision0.5 0.85185.1%mAP0.5 0.89789.7%即标题“高分”来源验证命令python val.py \ --data data/coco.yaml \ --weights runs/train/vest_helmet_v5s/weights/best.pt \ --task test \ # 用test集验证非val --verbose \ # 输出详细指标 --save-hybrid \ # 保存hybrid预测含NMS前所有框用于分析漏检输出的test_results.txt里找all行all 3210 2792 2645 0.851 0.823 0.837→P0.851, R0.823, mAP0.837。R0.823意味着100个安全帽平均漏检18个——对三级风险工地这个数字是可接受的底线。4. 避坑指南反光衣安全帽检测的5个血泪现场问题这5个问题是我给8家工地AI项目落地时客户打电话问得最多、最崩溃的。每个都按“现象→原因→解决”写不绕弯。4.1 现象检测框全在图像右下角且大小固定为100×100像素原因OpenCV读图后未转RGBYOLOv5训练时用的是RGB输入但cv2.imread()返回BGR。模型把BGR当RGB喂进去特征提取完全错乱head输出的坐标回归失效。解决在detect.py的run()函数里im0 cv2.imread(path)后加一行im0 cv2.cvtColor(im0, cv2.COLOR_BGR2RGB)。或者更彻底在datasets.py的LoadImages类中self.cap.read()后统一转RGB。4.2 现象训练loss降不下去val/mAP卡在0.3左右不上升原因data/coco.yaml里的train路径写成data/images/train/带尾部斜杠YOLOv5会把它拼成../data/images/train//*.jpgglob匹配失败实际只读了0张图训练在空数据上跑。解决检查coco.yaml确保路径是../data/images/train无尾部斜杠。用python -c import glob; print(glob.glob(../data/images/train/*.jpg))手动验证路径是否真能匹配到图。4.3 现象同一张图CPU推理结果和GPU推理结果bbox位置差5像素以上原因PyTorch 1.10.2的torch.nn.functional.interpolate在CPU和GPU上插值算法不同CPU用bilinearGPU用area导致FP16推理时特征图尺寸微差最终bbox偏移。解决强制统一插值模式。在models/common.py的Upsample类中将modenearest改为modebilinear并加align_cornersFalse。或者训练时禁用FP16删掉train.py里的--half参数。4.4 现象反光衣检测框很多但全是虚警金属栏杆、白色墙壁反光区也被框原因置信度阈值--conf设得太低如0.1而反光衣的纹理特征与金属反光高度相似模型难以区分。解决不调阈值改数据。用utils/extract_reflection_patches.py从训练图中裁出所有反光区域用HSV阈值lower_hsv (0,0,200)提取高亮块加入负样本negative samples到data/images/train/并在data/labels/train/里建空txt只含换行符。负样本让模型学会“这不是反光衣”。4.5 现象模型在测试集上mAP 0.89但部署到海思芯片后检测率暴跌到0.45原因海思NNIE引擎不支持YOLOv5的Focus层切片拼接操作模型转换时该层被跳过导致特征图尺寸错乱。解决替换models/common.py中的Focus类为Conv层卷积代替切片class Focus(nn.Module): def __init__(self, c1, c2, k1, s1, pNone, g1, actTrue): # ch_in, ch_out, kernel, stride, padding, groups super().__init__() self.conv Conv(c1 * 4, c2, k, s, p, g, act) # 直接卷积放弃切片 def forward(self, x): # x(b,c,w,h) - y(b,4c,w/2,h/2) return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))然后重新导出ONNXpython export.py --weights best_vest_helmet.pt --include onnx --opset 11。海思工具链才能正确解析。5. 边缘部署实战如何把YOLOv5反光衣安全帽模型塞进RK3399的1GB内存训练完模型只是开始工地摄像头是RK33991GB RAM Mali-T860 GPU或海思Hi3516DV300512MB RAM内存比显存还金贵。本项目权重best_vest_helmet.pt经INT8量化后仅4.2MB但直接跑PyTorch会吃掉800MB内存根本跑不起来。必须走轻量推理引擎。这里只讲RK3399的Rockchip NPU部署因为它是目前工地项目采用率最高的方案成本200元。5.1 量化前准备ONNX导出必须加这3个flagPyTorch模型不能直跑NPU得先转ONNX。但普通export.py导出的ONNX含动态shape、自定义opRKNN工具链无法解析。必须加flag锁定python export.py \ --weights weights/best_vest_helmet.pt \ --include onnx \ --opset 11 \ # RKNN只支持opset 11 --dynamic \ # 关键让输入shape可变适应不同分辨率图 --simplify \ # 简化计算图去掉冗余节点 --imgsz 640 640 # 指定输入尺寸避免动态shape引发NPU编译失败生成best_vest_helmet.onnx后用Netron打开检查输入节点名必须是imagesRKNN默认识别名输出节点名必须是outputYOLOv5的head输出若名字不对在export.py里改model.model[-1].names [output]提示--dynamic是玄机。RK3399的NPU不支持纯静态shape必须允许batch维度动态-1否则编译时报Input shape is not supported。但--imgsz又固定了H/W所以实际是[-1,3,640,640]既满足NPU要求又保证推理稳定。5.2 RKNN转换4行Python搞定但dtype必须设为uint8RKNN SDK提供Python API转换脚本convert_rknn.py解压包里有核心就4行from rknn.api import RKNN rknn RKNN(verboseTrue) rknn.config(mean_values[[0,0,0]], std_values[[255,255,255]], target_platformrk3399) # 输入归一化0~255→0~1 rknn.load_onnx(modelbest_vest_helmet.onnx, inputs[images], input_size_list[[1,3,640,640]]) rknn.build(do_quantizationTrue, dataset./dataset.txt, dtypeuint8) # 关键dtype必须uint8int8会掉点 rknn.export_rknn(./best_vest_helmet.rknn)dataset.txt是校准图列表100张典型工地图路径每行一个dtypeuint8是重点RK3399的NPU对int8支持不完善用uint8量化后mAP仅降0.3%而int8降2.1%。./dataset.txt内容示例data/images/calib/IMG_001.jpg data/images/calib/IMG_002.jpg ...5.3 C推理代码内存占用从800MB压到120MB的关键3个操作RKNN模型.rknn要在RK3399上跑必须用C。Python版rknn_api会额外吃500MB内存。C代码infer.cpp解压包cpp/目录做了三件事压内存内存池预分配rknn_init()时传入RKNN_FLAG_PRIORITIZE_SPEED让NPU优先用片上内存on-chip memory减少DDR访问输入缓冲区复用rknn_input结构体里index0的input buffer每次rknn_inputs_set()前不清零直接memcpy新图数据省掉malloc/free输出解析轻量化不调用rknn_outputs_get()全量拷贝改用rknn_output指针直接读output[0].bufYOLO的3个head输出用utils/nms_fast.c实现C版NMS比OpenCV的dnn::NMSBoxes省内存60%编译命令在RK3399板子上gcc -o infer infer.cpp -I${RKNN_SDK_PATH}/runtime/include -L${RKNN_SDK_PATH}/runtime/lib -lrknnrt -lpthread -O2运行后ps aux | grep infer显示内存占用118MBCPU占用32%帧率24fps1080p输入完全满足工地实时报警需求。血泪经验曾用Python版内存峰值冲到920MB系统直接OOM重启。换C后同一块RK3399板子7×24小时跑温度稳定在52℃没再重启过。这就是为什么我说——在边缘语言不是选择题是生存题。6. 进阶技巧用热力图定位反光衣检测失效的“黑匣子”区域训练好的模型在测试集上mAP 0.89但客户总说“现场还是漏检”。这时候别急着重训先用Grad-CAM生成热力图看模型到底在“看”哪里。本项目已集成utils/gradcam.py3步定位失效根源6.1 生成单图热力图找到模型“视而不见”的区域# utils/gradcam.py import torch from pytorch_grad_cam import GradCAM from models.experimental import attempt_load model attempt_load(weights/best_vest_helmet.pt, map_locationcpu) target_layers [model.model[-1].m[0]] # YOLOv5的Detect层第一个head cam GradCAM(modelmodel, target_layerstarget_layers, use_cudaFalse) rgb_img cv2.imread(data/images/test/IMG_20230815_142211.jpg)[..., ::-1] # BGR→RGB input_tensor torch.from_numpy(rgb_img.astype(float32).transpose(2,0,1)[None]/255.0) targets [lambda x: x[:, 0, :, :]] # 只看vestID 0的热力图 grayscale_cam cam(input_tensorinput_tensor, targetstargets)[0] # 叠加热力图 cam_image show_cam_on_image(rgb_img / 255.0, grayscale_cam, use_rgbTrue) cv2.imwrite(vest_heatmap.jpg, cam_image[..., ::-1]) # RGB→BGR存图运行后生成vest_heatmap.jpg。重点看如果反光衣区域如胸口亮条热力图是冷色蓝/黑说明模型根本没关注那里 → 数据集里反光衣样本太少或亮度不足如果安全帽顶部热力图弱但钢架热力图强 → 模型把安全帽当背景学了需加安全帽特写图close-up到训练集6.2 批量分析统计100张漏检图的热力图激活中心写个脚本analyze_missed.py对val集中所有漏检图GT有框但pred没框跑Grad-CAM统计热力图激活中心argmax位置与GT框中心的距离# 对每张漏检图 gt_center [(x1x2)/2, (y1y2)/2] # GT框中心 cam_center np.unravel_index(np.argmax(grayscale_cam), grayscale_cam.shape) # 热力图最强点 dist np.linalg.norm(np.array(gt_center) - np.array(cam_center)) # 统计100张图的dist均值 # 若dist均值 80像素640×640图→ 模型注意力严重偏移需重训 # 若dist均值 20像素但仍有漏检 → 是NMS或置信度过滤问题调--iou和--conf本项目实测100张漏检图dist均值12.3像素证明模型“看见”了但后处理丢了。于是把--iou 0.45调到0.35漏检率降11%。6.3 真正的后悔药不重训也能提点的3个后处理技巧热力图确认模型“看得见”那就在后处理上做文章。这三个技巧我在3个工地项目里都用过不改模型、不重训mAP提升0.5~1.2%技巧原理代码位置效果Soft-NMS传统NMS暴力删除重叠框Soft-NMS对重叠框只降分不删保留更多候选utils/general.py的non_max_suppression函数替换为soft_nms安全帽密集场景召回率3.2%Weighted Boxes Fusion (WBF)对同一目标的多个框来自不同尺度head加权融合比单框更准utils/wbf.py在detect.py输出后调用反光衣框定位误差降低1.8像素Confidence Calibration用Platt Scaling校准置信度让0.85置信度真正对应85%准确率utils/calibrate.py训练时用val集拟合sigmoid参数误报率下降22%报警更可信最后说句实在的这个YOLOv5反光衣安全帽项目不是为发论文是为让工地AI真正活下来。我见过太多模型在实验室mAP 0.95一上现场就跪——因为没人告诉你要校验OpenCV通道、没人提醒你RK3399的NPU不认Focus层、更没人告诉你热力图能帮你省下两周重训时间。希望这篇笔记里每一个命令、每一行参数、每一个避坑点都是你少走的弯路。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网