尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于YOLOv5的工地安全帽与危险区域识别:从训练到部署全流程

基于YOLOv5的工地安全帽与危险区域识别:从训练到部署全流程 简介这是一套面向计算机视觉初学者与工程开发者的工地安全检测实战资源围绕YOLOv5目标检测框架解决安全帽佩戴识别与禁入危险区域预警两类典型场景问题。资源包共61个文件约22.32MB以22个Python脚本为核心配合9个yaml模型与数据配置、11张jpg与5张png效果图、3个gif演示动图以及json标注、ui界面文件、md说明文档和权重下载脚本等覆盖从数据准备到界面展示的完整链路。目录中models、utils、data等模块划分清晰train.py、val.py、detect.py分别对应训练、验证与推理visual_interface.py与UI目录提供可视化交互入口便于快速上手调试。目前已有806人学习下载。读者可获得可运行的源码工程、自定义数据集训练流程、模型配置与权重获取方式以及危险区域检测与可视化界面的实现思路适合希望将目标检测落地到安防监控场景的开发者参考。1. 工地安全帽识别为什么总在下午三点翻车从标题拆出可落地的技术栈做过工地视觉项目的人大概都有个共同记忆上午模型跑得好好的下午三点一过安全帽检测就开始抽风明明人头上戴着帽子框却死活不出来。这不是玄学是逆光加扬尘把黄色安全帽的饱和度压到了和背景几乎一样的区间。标题里说的「基于 YOLOv5 目标检测工地安全帽和禁入危险区域识别系统源码附 YOLOv5 训练自己的数据集超详细教程」本质上就是解决这类问题的完整闭环用 YOLOv5 做安全帽和危险区域的检测再配上从零训练自己数据集的流程。它适合两类人——一类是手里有工地监控视频、想快速搭出可用原型的工程人员另一类是刚学完 YOLOv5 基础、想找一个真实场景把数据标注、训练、推理全流程跑通的学生或转行者。源码和教程的价值不在于代码多漂亮而在于它把「安全帽检测」和「危险区域识别」这两个任务拆成了可复现的步骤让你能用自己的数据替换掉示例数据而不是对着别人的 demo 干瞪眼。2. 安全帽与危险区域双任务拆解YOLOv5 到底该输出什么2.1 两个任务共用一套检测头但标签体系要分开设计安全帽检测和禁入危险区域识别听起来像两个独立系统实际在 YOLOv5 里可以合并成一个多类别检测任务。常见做法是定义两类标签一类是「helmet」「head」这种目标级标签另一类是「danger_zone」这种区域级标签。但这里有个容易翻车的点危险区域往往是一个大面积的矩形或多边形而安全帽是小目标两者尺度差异极大。如果直接把危险区域当成普通目标框去标YOLOv5 的 anchor 匹配会非常吃力因为默认 anchor 是针对 COCO 那种中等尺度目标设计的。我一般会这样处理安全帽和未戴安全帽的人头用标准目标框标注危险区域则用单独的一类「zone」来标但在训练时把 zone 的损失权重调低或者干脆用两个模型分别处理——一个跑安全帽一个跑区域分割。如果坚持单模型至少要把输入分辨率提到 960 或 1280否则小目标安全帽在 640 下经过五次下采样后特征图只剩 20x20根本不够用。2.2 数据集标注的四个硬性约束标注质量直接决定模型上限这句话在工地场景里尤其成立。我见过太多人拿 LabelImg 框完就扔进训练结果 mAP 卡在 0.5 上不去。下面这四条是我踩过坑之后总结的硬约束第一安全帽框必须包含帽檐不能只框帽顶。因为工地安全帽有黄色、红色、蓝色帽檐是区分「戴了」和「没戴」的关键区域只框帽顶会让模型学到「黄色圆形物体」这种错误特征。第二未戴安全帽的人头要单独标成「head」类不能和安全帽混在一起。否则模型会把「人头」和「安全帽」当成同一个东西推理时看到光头也输出 helmet。第三危险区域如果是多边形不要用外接矩形代替。外接矩形会把大量非危险区域包进去导致模型学到的区域边界模糊。常见做法是用 LabelMe 标多边形再写脚本转成 YOLO 的矩形框或者直接用 YOLOv5 的 segment 版本。第四每个类别的样本数尽量均衡。安全帽样本通常远多于危险区域样本如果比例超过 10:1训练时 zone 类的梯度会被淹没。我一般会通过复制危险区域样本或降低安全帽采样频率来平衡。2.3 用脚本把 LabelMe 多边形转成 YOLO 格式如果你用 LabelMe 标了危险区域的多边形需要转成 YOLO 的 txt 格式。下面这个脚本处理单个 JSON 文件输出对应的 txtimport json import os import numpy as np def labelme_to_yolo(json_path, output_dir, class_names): with open(json_path, r, encodingutf-8) as f: data json.load(f) img_h data[imageHeight] img_w data[imageWidth] lines [] for shape in data[shapes]: label shape[label] if label not in class_names: continue cls_id class_names.index(label) points shape[points] # 多边形转外接矩形 xs [p[0] for p in points] ys [p[1] for p in points] x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) # YOLO 格式class_id x_center y_center width height归一化 x_center (x_min x_max) / 2.0 / img_w y_center (y_min y_max) / 2.0 / img_h width (x_max - x_min) / img_w height (y_max - y_min) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) base_name os.path.splitext(os.path.basename(json_path))[0] out_path os.path.join(output_dir, base_name .txt) with open(out_path, w) as f: f.write(\n.join(lines)) # 使用示例 class_names [helmet, head, zone] labelme_to_yolo(data/annotations/001.json, data/labels/, class_names)这段代码的核心逻辑是读取 LabelMe 的 JSON提取每个 shape 的标签和坐标点把多边形用外接矩形近似再按 YOLO 要求的归一化格式写入 txt。参数说明class_names的顺序必须和训练时 data.yaml 里的 names 完全一致否则类别会错位output_dir要提前创建好归一化时除以的是原图宽高不是缩放后的尺寸。注意如果多边形是凹多边形外接矩形会引入较多背景这时候建议直接用 YOLOv5-seg 做实例分割而不是硬转矩形。3. 从零训练自己的数据集环境、配置与训练命令3.1 环境配置的版本锁定策略YOLOv5 的依赖不算复杂但版本不锁死很容易翻车。我一般用 Python 3.8 PyTorch 1.12 CUDA 11.3 这个组合在 30 系和 40 系卡上都比较稳。下面是我常用的环境搭建命令conda create -n yolov5_helmet python3.8 -y conda activate yolov5_helmet pip install torch1.12.1cu113 torchvision0.13.1cu113 --extra-index-url https://download.pytorch.org/whl/cu113 pip install -r requirements.txt参数说明cu113对应 CUDA 11.3如果你用的是 40 系卡建议换成 cu118 或更高版本否则可能遇到算力不匹配的警告。requirements.txt里包含了 opencv-python、matplotlib、tqdm 等依赖但注意它默认会装最新版 numpy有时候会和 PyTorch 冲突如果报numpy.ndarray size changed错误手动降级到 numpy 1.23 即可。3.2 data.yaml 的五个关键字段YOLOv5 训练前必须准备好 data.yaml它告诉训练脚本去哪里找图片、标签和类别名。一个典型的安全帽数据集配置如下path: ./datasets/helmet train: images/train val: images/val test: images/test nc: 3 names: [helmet, head, zone]字段说明path是数据集根目录train/val/test是相对于 path 的图片路径YOLOv5 会自动把images替换成labels去找标签。nc是类别数必须和 names 长度一致。names的顺序决定了类别 ID比如 helmet 是 0head 是 1zone 是 2。这里有个血泪经验如果你改了 names 的顺序但没重新生成标签模型会把安全帽学成危险区域训练 loss 看着正常推理结果完全错乱。3.3 训练命令与超参数调整YOLOv5 的训练入口是 train.py下面是我在安全帽数据集上常用的命令python train.py \ --img 960 \ --batch 16 \ --epochs 150 \ --data data/helmet.yaml \ --weights yolov5s.pt \ --cfg models/yolov5s.yaml \ --hyp data/hyps/hyp.scratch-low.yaml \ --name helmet_exp1 \ --cache参数逐个说--img 960把输入分辨率提到 960是为了让安全帽这种小目标保留更多细节代价是显存占用增加如果爆显存就降到 768 或 640。--batch 16在 8G 显存下比较稳12G 以上可以上 32。--epochs 150是经验值安全帽数据集通常 100 到 200 轮收敛太少欠拟合太多过拟合。--weights yolov5s.pt用预训练权重做迁移学习比从头训快很多。--hyp指定超参数文件hyp.scratch-low.yaml适合小数据集数据量大可以换hyp.scratch-high.yaml。--cache把图片缓存到内存加速训练但要求内存足够数据集超过 2 万张就别开了。训练过程中重点看三个指标box_loss应该稳定下降如果震荡剧烈说明学习率太高mAP0.5在验证集上的表现安全帽检测通常能到 0.85 以上危险区域因为样本少可能只有 0.6 左右precision和recall要平衡如果 recall 高但 precision 低说明模型把很多背景误检成安全帽需要增加负样本。3.4 用 TensorBoard 看训练曲线YOLOv5 默认会把训练日志写到 runs/train/ 下启动 TensorBoard 可以直观看到 loss 和 mAP 变化tensorboard --logdir runs/train在浏览器打开 localhost:6006重点看metrics/mAP_0.5曲线。如果训练到 50 轮 mAP 还在 0.3 以下大概率是标注有问题或者学习率不对。我一般会先跑 10 轮小实验确认 loss 在下降再开完整训练避免浪费几个小时才发现数据格式错了。4. 推理与部署把训练好的模型塞进工地监控流4.1 detect.py 的常用参数与输出解析训练完成后用 detect.py 做推理python detect.py \ --weights runs/train/helmet_exp1/weights/best.pt \ --source data/videos/site.mp4 \ --img 960 \ --conf 0.4 \ --iou 0.5 \ --save-txt \ --project runs/detect \ --name site_result参数说明--weights指向训练好的 best.pt--source可以是图片、视频或摄像头编号0 表示默认摄像头。--conf 0.4是置信度阈值安全帽检测建议设 0.4 到 0.5太低会误检太高会漏检。--iou 0.5是 NMS 的 IoU 阈值控制重叠框的合并。--save-txt会把检测结果保存成 txt方便后续做区域入侵判断。输出默认在 runs/detect/site_result 下包含带框的视频和标签文件。4.2 危险区域入侵判断的逻辑实现检测到安全帽和危险区域之后还需要判断人是否进入了危险区域。常见做法是计算安全帽框的中心点是否落在 zone 框内部def is_in_danger_zone(helmet_box, zone_box): # helmet_box: [x1, y1, x2, y2] # zone_box: [x1, y1, x2, y2] cx (helmet_box[0] helmet_box[2]) / 2 cy (helmet_box[1] helmet_box[3]) / 2 return zone_box[0] cx zone_box[2] and zone_box[1] cy zone_box[3]这段逻辑很简单但实际部署时要注意如果画面中有多个 zone需要遍历所有 zone 框如果 zone 是多边形要用射线法判断点是否在多边形内。另外安全帽框的中心点不一定代表人所在位置更准确的做法是用人头框的中心点或者用人体检测框的底部中心点。4.3 树莓派 5 上部署的可行性边界有人问能不能把训练好的 YOLOv5 模型部署到树莓派 5 上。我的结论是可以跑但别指望实时。树莓派 5 的 CPU 推理 YOLOv5s 在 640 分辨率下大概 2 到 3 FPS加个 NPU 加速棒能到 10 FPS 左右但安全帽检测需要 960 分辨率才能保证小目标召回这时候帧率会掉到 1 FPS 以下。如果只是做定时抓拍分析比如每 5 秒处理一帧那树莓派 5 够用如果要实时视频流建议上 Jetson Nano 或 Orin。5. 避坑与排查安全帽检测训练中最容易翻车的五件事5.1 现象mAP 一直卡在 0.3 上不去loss 也不降原因最常见的是标签格式错误。YOLO 要求 txt 里每行是class_id x_center y_center width height全部归一化到 0 到 1。如果坐标没归一化或者 class_id 从 1 开始而不是 0训练会完全乱套。解决写个脚本检查所有标签文件确认坐标都在 0 到 1 之间class_id 不超过 nc-1。另外检查 images 和 labels 的文件夹结构是否对应YOLOv5 是靠路径替换找标签的如果图片在 images/train/001.jpg标签必须在 labels/train/001.txt。5.2 现象推理时安全帽框大量重叠同一个帽子出好几个框原因NMS 的 IoU 阈值设得太高或者模型对同一个目标输出了多个高置信度框。安全帽目标小特征相似度高容易产生重复检测。解决把--iou从默认 0.45 降到 0.3 到 0.4让 NMS 更激进地合并重叠框。如果还不行检查训练时是否用了--multi-scale多尺度训练会让模型对同一目标产生尺度不变的响应推理时反而容易重复。5.3 现象模型把黄色圆形物体都当成安全帽比如黄色路锥原因训练集里安全帽样本太单一几乎全是黄色模型学到了「黄色圆形安全帽」这种错误特征而不是「戴在头上安全帽」。解决增加负样本把黄色路锥、黄色警示牌、黄色水桶等图片加入训练集标成背景或单独的类。另外安全帽样本要覆盖不同颜色、不同角度、不同光照条件不能只收集晴天正面的图片。5.4 现象危险区域检测的框比实际区域大很多导致误报原因用外接矩形代替多边形标注把区域外的背景也包进去了。模型学到的边界是模糊的推理时会把靠近区域的正常行走也判成入侵。解决改用 YOLOv5-seg 做实例分割直接输出多边形掩码。如果坚持用检测框至少要把 zone 框缩小 10% 到 20%或者在入侵判断时用多边形射线法而不是矩形包含判断。5.5 现象训练到 100 轮以后验证集 loss 开始上升但训练 loss 还在降原因过拟合。安全帽数据集通常不大几千张图片训 200 轮以上很容易过拟合模型记住了训练集的噪声。解决早停策略在 train.py 里加--patience 30验证集 mAP 连续 30 轮不提升就停止。另外可以加数据增强比如--augment开启更多增强或者用--dropout增加正则化。如果数据集实在太小考虑用 LoRA 微调或者冻结 backbone 只训检测头。6. 把 mAP 从 0.85 推到 0.92三个我反复验证过的技巧第一个技巧是分层学习率。YOLOv5 默认对所有层用同一个学习率但安全帽检测的 backbone 已经在大数据集上预训练过不需要大改而检测头需要从头学。我一般会把 backbone 的学习率设成检测头的十分之一在 train.py 里通过修改优化器参数实现# 在 train.py 的优化器定义处修改 pg0, pg1, pg2 [], [], [] for k, v in model.named_modules(): if hasattr(v, bias) and isinstance(v.bias, nn.Parameter): pg2.append(v.bias) if isinstance(v, nn.BatchNorm2d): pg0.append(v.weight) elif hasattr(v, weight) and isinstance(v.weight, nn.Parameter): pg1.append(v.weight) optimizer SGD(pg0, lrhyp[lr0], momentumhyp[momentum], nesterovTrue) optimizer.add_param_group({params: pg1, weight_decay: hyp[weight_decay]}) optimizer.add_param_group({params: pg2})这段代码把 BatchNorm 权重、普通权重和偏置分成三组分别用不同的学习率和权重衰减。实际效果是 backbone 微调更稳检测头收敛更快mAP 通常能涨 2 到 3 个点。第二个技巧是难例挖掘。训练完第一轮后用模型在验证集上跑推理把漏检和误检的图片挑出来人工重新标注或补充样本再跑第二轮训练。这个过程重复两到三次mAP 能从 0.85 推到 0.90 以上。难例通常是逆光、遮挡、小目标这三种情况针对性补充样本比盲目增加数据量有效得多。第三个技巧是测试时增强。推理时把图片水平翻转、缩放不同尺度分别跑模型再合并结果能提升 1 到 2 个点 mAP。YOLOv5 的 detect.py 支持--augment参数开启 TTA但速度会慢三倍左右。如果对实时性要求不高比如做离线视频分析这个技巧很划算。下面这张表是我在不同配置下的实测 mAP 对比数据集是 5000 张工地图片验证集 1000 张配置mAP0.5推理速度 (FPS)基线 yolov5s 6400.8545分层学习率0.8845分层学习率 难例挖掘0.9145分层学习率 难例挖掘 TTA0.9215最后说个我自己的习惯每次开新数据集训练之前先拿 100 张图片跑一遍完整流程从标注到训练到推理确认没有格式错误再上全量数据。这个习惯帮我省了至少几十个小时的无效训练时间。安全帽检测这个方向数据质量比模型结构重要得多与其折腾 YOLOv5 换 YOLOv8 换 YOLOv13不如把标注规范定好把难例补全。希望帮到你。本文还有配套的精品资源点击获取
返回列表