简介:面向AI目标检测开发者与工地安全管理人员的YOLOv5安全帽佩戴检测项目,解决施工现场人员是否规范佩戴安全帽的自动识别问题。压缩包共54个文件,以Python脚本(21个py)、YAML配置(14个yaml)和测试图片(8个jpg)为主体,另含Shell权重下载脚本、Dockerfile、Markdown说明及Jupyter Notebook,整体约3.91MB,目录结构遵循YOLOv5标准工程布局,便于直接定位代码与配置。已有308人学习浏览,适合希望快速复现安全帽检测场景的算法初学者与工程落地人员。资源提供从数据标注格式、模型训练(train.py)到实时推理(detect.py)的完整流程,包含hatPerson.yaml专属数据集配置、yolov5s/yolov5m/yolov5l等模型结构定义,以及通用工具模块(utils)与模型导出功能;搭配tutorial.ipynb和README可辅助完成环境配置、权重获取与测试图片演示,帮助读者理解YOLOv5在特定目标检测任务中的完整应用链路,并可根据实际工地数据微调模型。 工地上的安全事故,十起有八起跟安全帽有关。不是工人不知道戴,而是监管不可能二十四小时盯着每一个角落。我接过不少类似的需求,最后都落在同一个方向上:用YOLOv5做安全帽佩戴检测,把视频流里“没戴帽子”的瞬间自动抓出来报警。这篇博文就完全围绕这个项目展开,从数据标注、模型训练到边缘端部署,把每个环节的坑和取舍都摊开讲一遍。不管你是拿它做毕业设计,还是想在公司内部搞一套安监系统,这篇内容都能让你少走几周弯路。
1. 项目思路与技术选型
1.1 安全帽检测的本质是什么
安全帽检测在计算机视觉里属于典型的目标检测任务,输入是一帧图像或一段视频,输出是每个人头的位置框和对应的类别——戴帽(helmet)或未戴帽(no-helmet)。听起来简单,但落地时牵扯的东西不少:摄像头安装角度、逆光、安全帽颜色与背景融合、工人只把帽子顶在头上不系下颌带……这些都是检测模型要扛住的真实干扰。
从业务闭环看,单有模型还不够。一套完整的“安全帽智能检查系统”通常是这样跑的:摄像头持续采集画面,检测模型对每一帧做人头定位与分类,如果连续若干帧出现未戴帽目标,就触发截图、声光报警,并在后台记录到工人违规台账里。也就是说,模型只是核心算法组件,前后还得接视频流接入、报警逻辑和前端展示。我在做这个项目时把主力放在模型训练上,但架构上从一开始就按“可扩展”来搭——这样后面要加入反光衣检测、区域入侵检测时才不用推翻重来。
1.2 为什么选了YOLOv5而不是其他方案
目标检测的模型选型,市面上选项非常多:传统图像处理、YOLOv3/R4/R5/R8、SSD、Faster R-CNN,甚至各种Transformer检测器。我最终锁定YOLOv5,主要是从技术成熟度和工程效率两方面考虑。
传统方法完全不考虑。有人会提议“安全帽颜色固定,用颜色分割不就行了”,但工地光线一变、帽子颜色跟背景撞了,算法直接崩。深度学习是必须的。
在深度学习框架里,Faster R-CNN这种两阶段检测器精度确实稳,但推理速度扛不住多路视频流,一张图几十毫秒还只是GPU端,部署成本不划算。YOLO系列是单阶段检测的典型代表,速度和精度平衡得最好。至于为什么没用更新的YOLOv8或v9,核心原因是YOLOv5的生态太成熟了。它的社区教程、预训练权重、部署工具链都是最全的,遇到问题一搜就有答案。毕竟是给工程落地用,不是追新技术潮,稳定的方案就是最好的方案。另一个实际原因是团队里其他人之前都接触过YOLOv5,接手成本最低。
YOLOv5本身的结构其实也不复杂。Backbone用CSPDarknet提取特征,Neck用PANet做多尺度特征融合,Head负责输出不同尺寸下的预测结果。它把anchor计算、数据增强、网络结构都封装得很干净,训练入口就是一个train.py,即使你没读过源码也能快速跑通。对这个项目来说,不需要自己改网络,直接用默认结构配合适合的模型尺寸就够了。
2. 数据准备与标注:模型上限由这里决定
2.1 数据场景多样性比数量更关键
很多人上来就问“我该准备多少张图”,这个问题的优先级其实排第二。排第一的是:你的数据能不能覆盖真实现场的变化。
安全帽检测容易翻车的地方有几个,我在标注前会专门对着摄像头实拍素材排查一遍。
一是角度问题。监控摄像头通常装在工地出入口或塔吊高处,是俯拍视角,而网上公开数据集很多是平拍甚至自拍视角的。直接用公开数据集训练,到现场大概率漏检,因为模型没见过这个角度的“头”。
二是光照问题。逆光时人脸和帽子细节都在阴影里,戴不戴帽很难区分。我在数据里专门加了清晨和傍晚逆光时段抓拍的样本,让模型学会在这种条件下也能通过帽檐轮廓和环境对比度做判断。
三是遮挡问题。工人排队路过闸机时,前面的人会挡住后面人的头;弯腰搬砖时,头盔可能只露出一半。标注这种遮挡样本时,我要求标注员只框可见部分,不要凭“感觉”把被挡住的半边也画进框里,否则会把背景学进特征里。
数据集来源上,我用了公开的SHWD安全帽数据集打底,再补充现场摄像头采集的3000多张真实场景图。SHWD大约有7000多张,类别是hat和person,我会把它重新映射成我们需要的helmet和no-helmet。注意公开数据集大多不是专门为你的摄像头角度准备的,必须按上面的要点筛选一遍,不能无脑全用。
2.2 标注规范和工具选择
标注工具我用的是LabelImg,它可以直接导出YOLO格式的txt文件,每行是“类别id x_center y_center width height”,坐标是归一化后的值,省去转换的麻烦。Labelme也能用,但要额外转一次格式,没必要。
标注规范必须提前定死,特别是这个项目的类别边界。我见过不少标注翻车案例,问题都出在“什么叫戴帽”的定义上。我定的规则很简单:帽子覆盖头顶主要区域且明显可见,就算helmet;帽子拿在手上、放在头上但完全歪斜露出大部分头顶、或者只是挂在脖子上,全部算no-helmet。这个二分类标准必须在标注前跟所有标注员对齐,否则同一个“半戴帽”的目标,有人标helmet,有人标no-helmet,会把模型训成“薛定谔的安全帽”,推理时同一张图结果忽好忽坏。
画框也有讲究。框要紧贴人头的边界,把帽子边缘包进去,但不要把肩膀、脖子、背景杂物带进去太多。框大了模型会学到多余的背景信息,框小了帽子特征不完整,这两种情况都会拉低精度。类别不平衡也需要留意:现场素材里戴帽的样本通常比没戴帽的多很多,我处理的办法是在采样阶段把no-helmet样本适当重复加入训练集,或者直接用YOLOv5自带的类别权重参数,避免模型“偷懒”把所有目标都判成helmet。
数据划分上,我按8:1:1分成训练集、验证集、测试集。注意划分前要打乱,并且保证同一个场景的视频帧不要同时出现在训练集和验证集里,否则验证指标虚高。做这一步时就要想清楚:验证集是用来模拟“没见过的场景”的,不是用来背答案的。
3. 环境配置与训练实操
3.1 环境配置清单与踩坑记录
YOLOv5的环境配置网上教程一抓一把,但版本组合不对,会浪费大量时间。我试过几套组合,实测下来最顺手的版本是:
| 组件 | 推荐版本 | 备注 |
|---|---|---|
| Python | 3.8 / 3.9 | 3.10以上某些版本在Windows下容易报编码错误 |
| PyTorch | 1.12.1 或 2.0.0 | 2.x对训练加速更好,但N卡驱动要新一点 |
| CUDA | 11.6 / 11.7 / 11.8 | 跟PyTorch对应,不要盲目装最新 |
| cuDNN | 与CUDA匹配即可 | 默认装就行 |
| 显卡 | 显存6GB以上为佳 | 8GB可以较舒服跑YOLOv5s/m |
装PyTorch建议直接用官方命令,比如CUDA 11.8就执行:
pip install torch==2.0.0 torchvision==0.15.0 --index-url https://download.pytorch.org/whl/cu118然后再git clone YOLOv5仓库并安装依赖:
git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt依赖安装看似简单,实际踩坑最多的是opencv-python版本不匹配导致cv2读不了视频流,以及pycocotools在Windows下编译失败。后者可以直接用pip安装预编译版,或者把requirements.txt里这行注释掉,不用它也不影响YOLOv5训练。
3.2 修改配置文件,开始训练
训练前需要准备三样东西:数据集配置文件、模型结构配置、预训练权重。数据集配置文件是我每次都要反复检查的重点,它长这样:
# helmet.yaml train: /data/helmet/images/train val: /data/helmet/images/val nc: 2 names: ['helmet', 'no-helmet']路径要用绝对路径或改成相对yaml文件位置的写法,我因为路径写错导致训练跑一半报错的情况至少有三次。这个yaml文件里的train和val指向的是存放图片的文件夹,YOLOv5会自动读取同目录下同名的txt标签文件。
模型结构配置我直接复制yolov5s.yaml,只把nc改成2。网络深度和宽度选择上,YOLOv5提供了n/s/m/l/x五档,我在显存有限的机器上用s,追求更高精度用m。直接上l或x对这个项目来说没必要,安全帽是大目标而不是密集小目标,s/m的容量完全够用。
训练命令如下:
python train.py \ --data helmet.yaml \ --cfg yolov5s.yaml \ --weights yolov5s.pt \ --batch-size 16 \ --epochs 150 \ --img 640 \ --patience 30这里有几个参数需要多解释两句。batch-size在显存不足时报错“CUDA out of memory”,解决办法是调小batch-size,比如8或4,同时开启梯度累积。--patience 30的意思是验证集指标连续30个epoch不提升就提前停止训练,可以避免后期过拟合。--img 640是训练分辨率,更高分辨率精度会稍微提升但训练速度明显下降,640对安全帽检测是性价比最高的档位。
关于超参数,YOLOv5自带一份hyp.scratch-low.yaml,里面配置了学习率、动量、数据增强强度等。这个项目我直接用默认配置,没有单独调。初次接触的不建议动超参数,默认值在大多数视觉检测任务上已经调得比较均衡。等跑完第一轮,再看mAP指标决定要不要微调。
3.3 训练过程中的问题与判断
训练过程中输出日志会一直刷新,主要看几个指标:box_loss、obj_loss、cls_loss,以及验证集的mAP@0.5和mAP@0.5:0.95。正常曲线应该稳步下降或震荡下降,如果loss快速降到很低但mAP不涨,大概率是过拟合了,back to数据增强或减epochs。
跑第一轮时常见的报错就那几类。找不到标签文件:检查yaml路径和标签文件是否与图片同名;assert image not found:数据集路径里有中文或空格,改成纯英文路径;CUDA error: device-side assert triggered:类别数不匹配或标签里出现了超过nc的类别id,检查标注文件最后一行有没有多出多余数字。
显存不足是新手遇到最多的问题。除了调小batch-size,还有一招是用--gradient-accumulate 4,相当于每4个step做一次参数更新,效果等同放大了batch-size,但显存占用不会翻倍。我在8GB显存的笔记本上就是用batch-size 8加梯度累积正常训完了YOLOv5s。
4. 推理部署与结果应用
4.1 用训练好的模型做图片和视频检测
训练完成后,模型权重保存在runs/train/exp/weights/best.pt。做推理最直接的方式是用YOLOv5自带的detect.py:
python detect.py \ --weights runs/train/exp/weights/best.pt \ --source test.jpg \ --conf-thres 0.45 \ --iou-thres 0.45conf-thres是置信度阈值,这个参数在实际使用中非常关键。阈值调太高(比如0.8)会漏检,略有遮挡的未戴帽目标就被放过去了;阈值调太低(比如0.2)会出现大量误报,把安全帽下面的背景物体当成目标。安全帽检测场景我通常建议0.4到0.5之间。iou-thres是NMS去重阈值,处理密集人群时如果发现两个人头框重叠得厉害,可以调低到0.4让NMS更激进地合并重叠框。
摄像头实时检测时,直接对每一帧跑detect.py当然不行,那样FPS太低。实际做法是直接调用模型而不是走命令行脚本,读取视频流后按帧推理。为了提升速度,我做了两个优化:一是跳帧策略,每3帧取1帧检测,检测结果在中间帧上做框的平滑延续,肉眼几乎看不出延迟;二是把视频解码放到独立线程里,用队列缓存最近的几帧,避免解码耗时阻塞检测线程。经过这样优化后,在同一张1080p视频流上,YOLOv5s的推理速度从带解码时的8FPS提升到接近25FPS,已经能满足安监实时性要求。
4.2 导出ONNX与边缘端部署
如果要把模型部署到无PyTorch环境的Windows机器或嵌入式设备上,需要导出成通用格式。最常用的是导出ONNX:
python export.py --weights best.pt --include onnx --opset 12导出后可以用ONNX Runtime在CPU上做推理,速度比PyTorch的CPU模式快不少。我导出后在一台不带独立显卡的i5工控机上跑,640x640输入分辨率,单帧推理耗时大约100毫秒左右,对工地闸机这种低并发场景完全够用。
边缘端部署是很多人问的方向,最近也有不少人在树莓派5上跑YOLOv5。树莓派5的算力比前代强很多,但跑YOLOv5s仍然吃力,实测在树莓派5上用ONNX Runtime CPU推理,单帧大约200到300毫秒。真要上树莓派5做安全帽检测,最好先用torchvision库里的量化接口把模型转成int8量化模型,或者导出成TensorRT Lite格式(如果跑的是带GPU的Jetson)。至于STM32这类单片机,跑完整YOLOv5不现实,通常只能做简化分类任务或者靠外接NPU协处理器。如果你是做毕设,用树莓派展示安全帽检测demo是合理的;但如果要做真实的工地监控,还是建议用普通PC工控机加GPU,或者海康/大华摄像头内置的AI算力来做。
4.3 实时视频流检测的一个易漏点
推理脚本只处理单张图片时一切正常,但一接实时视频流就会出现一个隐蔽问题:置信度分数会剧烈震荡。同一个工人,在画面远处时检测框置信度可能只有0.35,走近后变成0.9。如果阈值卡死在0.45,远处未戴帽的人就会被漏报。
我的解决办法是加一个“二次确认”逻辑:对连续视频帧检测到的同一个目标,如果置信度平均分超过阈值,就触发报警,而不是用单帧分数做判断。这样既避免了漏报,也不会因为个别帧抖动产生误报。这个逻辑在落地项目中比调模型参数更重要,因为安全帽检测的价值在于“稳定报警”,而不是“某几帧检测得很准”。
5. 实测效果与常见问题排查
5.1 检测效果实测数据
我用一批现场摄像头素材做了完整测试,测试集包含5个不同场景,共800张图。最终YOLOv5s模型在我自建验证集上的mAP@0.5在0.93左右,mAP@0.5:0.95在0.78左右。看单个类别的话,helmet的precision和recall都比较高,都在0.95附近;no-helmet的precision在0.9左右,recall略低,大概0.85。recall偏低的主要原因是个别俯拍角度下,工人低头时安全帽看不清边界,模型会把戴帽误判为未戴帽。这也是这类项目最常见的精度瓶颈。
我尝试换用YOLOv5m做比较,精度提升了大概1.5个点,但推理时间从18毫秒涨到了28毫秒。考虑到安监系统往往同时跑4路以上的视频流,我最终还是选择了YOLOv5s做主力模型,用YOLOv5m作为高精度备用模型,在核心出入口这类最关键的位置启用。
5.2 常见问题速查表
| 现象 | 原因 | 解决办法 |
|---|---|---|
| 训练时loss不降 | 学习率过大或数据标签错误 | 先检查标签可视化,确认框和类别没错位;调低学习率到0.001以下 |
| 验证集mAP高但现场效果差 | 训练数据场景不够多样 | 补充现场真实场景数据,特别是角度和光照差异大的素材 |
| 漏检远处小目标 | 输入分辨率不够 | 推理时使用--img 1280做测试,或者把摄像头安装位置调近 |
| 戴帽误报为未戴帽 | 安全帽颜色与背景相近 | 增加三种不同颜色安全帽的数据,或提升conf-thres到0.5 |
| 推理速度慢 | 没有开启GPU推理或模型尺寸过大 | 确认CUDA可用torch.cuda.is_available();换YOLOv5s/n模型 |
| 视频流检测有卡顿 | 解码和检测串行耗时 | 用多线程把视频解码和检测分开,采用跳帧策略 |
5.3 这个项目的扩展思路
做完安全帽检测,整套流程其实可以平移到很多类似的工业安全场景。把标注数据换成“反光衣/无反光衣”就是反光衣检测系统;换成“口罩/无口罩”就是口罩佩戴检测。模型结构和训练脚本一行都不用改,只换数据集和yaml配置里的nc、names就行。我后来在这个框架上接了安全背心检测和区域入侵检测,共用同一个训练推理底座,运维成本没有明显增加。
再往深一层,如果要做更完整的工地智能化管理,可以在检测结果后面接一个多目标跟踪模块,比如ByteTrack或DeepSORT,这样就能统计同一个人的违规次数,而不是每次出现都重新计算。再接上定时抓拍和Webhook报警,整个系统的商业价值比单做一个检测模型要高一截。
我在实际做这个项目的过程中体会最深的一点是:YOLOv5作为工具本身非常成熟,项目的成败几乎都取决于训练数据是否贴合现场、阈值和报警策略是否合理。很多团队拿着开源模型直接跑,效果不好就归咎于模型不行,其实问题出在数据角度和阈值策略上。安全帽检测作为YOLOv5入门到实战的经典项目,最大的价值不是代码本身,而是让你完整走一遍“数据——训练——调优——部署——迭代”的闭环。跑通一次这个流程,后面做其他目标检测项目都会轻松非常多。
本文还有配套的精品资源,点击获取