ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于YOLOv11的工地安全帽检测:从数据到部署全流程实战

基于YOLOv11的工地安全帽检测:从数据到部署全流程实战

1. 工地安全监管的真实痛点与YOLOv11的切入逻辑

干过工地安全管理的都清楚,安全帽佩戴检查这件事,说起来简单,落地起来能让人脱一层皮。传统做法无非两种:一是安排专职安全员在各个出入口和作业面来回巡查,二是靠班组长的自觉上报。前者人力成本高得离谱,一个中型工地至少得配三到五个安全员轮班,而且人总有走神的时候;后者基本靠运气,班组长忙着赶工期,哪有闲工夫盯着每个人头上那顶帽子。

我在前几年接触过几个做智慧工地解决方案的团队,他们早期尝试过用RFID标签或者红外感应来做安全帽识别,效果都不太理想。RFID的问题是只能判断“帽子在不在附近”,没法确认“帽子是不是戴在头上”——工人把帽子挂在腰间或者放在工具箱旁边,系统照样显示正常。红外方案更麻烦,夏天工地温度本身就高,人体和帽子的热辐射特征容易混淆,误报率居高不下。

真正让这个场景出现转机的是视觉检测技术的成熟。从最早的HOG+SVM传统方法,到后来的Faster R-CNN两阶段检测,再到YOLO系列的单阶段实时检测,技术路线越来越清晰。YOLOv11作为这个系列较新的版本,在保持实时性的同时把精度又往上推了一截,对于安全帽检测这种需要兼顾速度和准确率的场景来说,算是一个比较合适的选型。

这个系统的核心目标很明确:在工地现有的监控摄像头画面上,实时框出每一个人员,并判断其头部是否佩戴了安全帽。如果发现未佩戴的情况,立即触发告警并记录。适合谁来参考?如果你是有一定Python基础、了解深度学习基本概念、想做一个完整落地项目的开发者,或者你是工地信息化负责人想评估技术方案,再或者你是学生想做毕业设计但不想做得太水,这套东西都值得花时间研究。

我下面要聊的,不只是“怎么跑通一个YOLOv11的demo”,而是从数据准备、模型训练、工程部署到现场调优的完整链路。很多教程只告诉你model.train()就完事了,但真正到了工地上,光照变化、遮挡、小目标、误报这些问题会把你折磨得够呛。我会把这些坑一个个拆开讲。

2. 整体方案设计与技术选型背后的考量

2.1 为什么是YOLOv11而不是其他版本

YOLO系列发展到今天,版本多得让人眼花缭乱。v5、v7、v8、v9、v10、v11,每个版本都有各自的拥趸。我选v11主要基于三个维度的权衡。

第一是精度和速度的平衡。安全帽检测的场景对实时性要求很高,工地摄像头通常是25帧每秒的视频流,如果模型推理速度跟不上,画面就会卡顿,告警延迟也会变大。YOLOv11在COCO数据集上的mAP相比v8有提升,同时推理延迟控制在可接受范围内。具体来说,在RTX 3060这个级别的显卡上,YOLOv11s模型处理640x640的输入,单帧推理时间大约在8到12毫秒,加上前后处理,跑到30FPS以上没什么压力。

第二是训练效率。v11在训练策略上做了一些优化,比如更好的数据增强策略和损失函数设计,使得在相同数据量下收敛更快。我实测下来,用大概3000张标注图片训练,v11比v8能早收敛大概15%到20%的epoch。这意味着你可以用更少的算力完成训练,对于个人开发者或者小团队来说,这个优势很实际。

第三是生态兼容性。Ultralytics这个框架把训练、验证、导出、部署的流程做得非常统一,从v8到v11的API基本一致,你之前写的v8代码稍微改改就能迁移过来。而且它支持导出ONNX、TensorRT、OpenVINO等多种格式,方便后续在不同硬件上部署。

当然,v11也不是没有缺点。相比v8,它的模型文件稍微大一点,在极端边缘设备上可能要多考虑一下量化的问题。但总体来说,对于安全帽检测这个具体任务,v11的收益是大于成本的。

2.2 检测策略:两阶段还是一步到位

安全帽检测从逻辑上可以拆成两个子任务:先找到人,再判断头上有没有帽子。这就引出了两种技术路线。

第一种是两阶段方案:先用一个人体检测模型把画面中所有人员框出来,然后对每个人体框的上半部分(头部区域)做裁剪,再送进一个分类模型判断是否戴帽。这种方案的好处是逻辑清晰,每个模型各司其职,人体检测和帽子分类可以分别优化。但缺点也很明显:推理链路长,两个模型串行跑,延迟翻倍;而且人体检测框的准确性会直接影响后续分类的效果,如果人体框偏了,头部裁剪区域就可能不对。

第二种是一步到位的方案:直接训练一个多类别检测模型,把“戴安全帽的人”和“未戴安全帽的人”作为两个类别来检测。YOLOv11本身就支持多类别检测,你只需要在标注的时候把这两类分开标就行。这种方案推理速度快,端到端一次出结果,工程实现也简单。

我最终选的是第二种方案。原因很简单:工地场景对实时性要求高,两阶段方案的延迟在高峰期可能达到几百毫秒,告警就不及时了。而且一步到位的方案在标注阶段虽然稍微麻烦一点,但后续维护成本低很多。你不需要去调两个模型的参数,也不用担心两个模型之间的配合问题。

不过这里有个细节需要注意:标注的时候,“未戴安全帽的人”这个类别,框应该框在头部还是整个人?我的做法是框在头部区域,因为安全帽是戴在头上的,框头部能让模型更聚焦于头部特征。如果框整个人,模型可能会学到一些和帽子无关的特征,比如衣服颜色、体型等,反而影响泛化能力。

2.3 数据策略:自建数据集还是用公开数据

安全帽检测有一些公开数据集可以用,比如SHWD(Safety Helmet Wearing Dataset),里面大概有7000多张标注好的图片。但我建议不要完全依赖公开数据集,原因有三。

一是场景差异。公开数据集大多来自网络爬取或者特定工地,和你实际要部署的工地环境可能差别很大。光照条件、摄像头角度、工人着装、安全帽颜色这些因素都会影响模型表现。你拿一个在北方工地训练的模型去南方工地用,效果可能打折扣。

二是标注标准不一致。不同数据集的标注规范不一样,有的框整个人,有的框头部,有的把“未戴帽”标成“人头”,有的标成“人”。如果你混合使用多个数据集,需要先做标注统一,这个工作量不小。

三是数据量需求。YOLOv11虽然对小数据集比较友好,但要想达到可用的精度,至少需要2000到3000张有效标注图片。公开数据集加上你自己采集的,凑到这个量级不难,但关键是质量要把控。

我的建议是:公开数据集可以用来做预训练或者作为补充,但核心训练数据一定要来自你自己的目标场景。哪怕只采集1000张,只要覆盖了各种光照、角度、遮挡情况,效果也比用5000张不匹配的公开数据好。

3. 数据准备与标注的实操细节

3.1 数据采集:摄像头选型和采集策略

数据采集这一步,很多人随便拿手机拍几张就完事了,这是大忌。工地场景的数据采集有几个关键点要注意。

首先是摄像头角度。实际部署时摄像头通常安装在塔吊、围墙或者立杆上,俯视角度大概在15度到45度之间。你采集数据时就要模拟这个角度,不能全用平视或者仰视的图片。我见过一个项目,训练数据全是平视拍的,部署到俯视摄像头后,模型几乎认不出人来。

其次是光照覆盖。工地从早到晚的光照变化很大,早晨和傍晚有逆光,中午有强阴影,阴天光线又很平。采集数据时要覆盖这些情况,每个时间段都拍一些。如果条件允许,最好在不同天气下都采集一轮。

第三是安全帽颜色和款式。不同施工单位的安全帽颜色不一样,有黄色的、红色的、蓝色的、白色的。款式也有差异,有带帽檐的、不带帽檐的、带透气孔的。采集时要尽量覆盖这些变体,否则模型可能只认某一种颜色的帽子。

采集设备方面,用工地现有的监控摄像头直接截取视频帧是最理想的,因为训练和推理的数据分布完全一致。如果摄像头还没装,可以用手机或者运动相机模拟,但要注意焦距和视场角要接近实际摄像头。

采集频率上,不需要连续截取每一帧,因为相邻帧之间差异很小,会造成数据冗余。我的做法是每隔10到15帧取一帧,这样既能覆盖时间上的变化,又不会让数据集过于臃肿。一个摄像头点位采集一天,大概能拿到2000到3000张原始图片,足够筛选出1000张左右的有效数据。

3.2 标注规范:框哪里、怎么分类

标注是安全帽检测里最容易被忽视但影响最大的环节。我见过太多项目因为标注不规范导致模型学偏了。

先说分类。我建议至少分三类:helmet(戴安全帽的人)、no_helmet(未戴安全帽的人)、person(不确定是否戴帽的人,比如背对镜头或者头部被遮挡)。第三类是为了处理那些模棱两可的情况,避免强行归类导致标注错误。

框的位置上,helmet和no_helmet都框头部区域,person框整个人。为什么这么设计?因为安全帽检测的核心是判断头部状态,框头部能让模型更聚焦。而person类作为兜底,框整个人是为了在头部信息不足时至少能检测到人的存在。

标注工具推荐用LabelImg或者CVAT。LabelImg简单轻量,适合个人开发者;CVAT功能更强,支持多人协作和视频标注,适合团队。标注格式用YOLO格式,就是每个图片对应一个txt文件,每行是类别id x_center y_center width height,坐标都归一化到0到1之间。

这里有个实操技巧:标注的时候不要只标一遍就完事。我通常会让两个人分别标同一批数据,然后对比差异。如果两个人对同一张图的标注差异超过10%,说明这张图本身就有歧义,要么重新定义标注规则,要么直接丢弃。这个交叉验证的过程能显著提升标注质量。

还有一个细节:对于小目标(远处的人),头部区域可能只有十几个像素,标注起来很困难。我的做法是,如果头部区域小于20x20像素,就归到person类,不强行区分是否戴帽。因为这么小的目标,模型本身也很难判断,强行标注只会引入噪声。

3.3 数据增强:不是越多越好

YOLOv11内置了数据增强功能,包括Mosaic、MixUp、随机缩放、随机裁剪等。这些增强策略在训练时自动生效,你不需要手动做。但有几个参数需要根据安全帽检测的特点调整。

Mosaic增强是把四张图拼成一张,这个策略对小目标检测很有效,能增加小目标的出现频率。但安全帽检测里,如果拼接后的图片中头部区域被截断,反而会引入错误标签。我建议把Mosaic的概率从默认的1.0降到0.5左右,减少这种风险。

MixUp是把两张图按透明度叠加,这个策略在安全帽检测里要慎用。因为叠加后可能出现“一个人有两个头”的诡异画面,模型会学乱。我通常把MixUp关掉,或者把概率设得很低。

随机缩放和随机裁剪是安全的,可以保留默认设置。但要注意缩放范围,如果缩得太小,头部区域可能变成几个像素,模型根本学不到东西。我一般把缩放范围控制在0.5到1.5之间。

除了内置增强,我还会额外做一些针对性的增强。比如模拟夜间低照度情况,把图片亮度调低、加一些噪声;模拟雨天模糊,加高斯模糊;模拟摄像头脏污,随机加一些遮挡块。这些增强能让模型对工地上的恶劣条件更鲁棒。

但记住一个原则:增强是为了模拟真实可能发生的情况,不是为了增加数据量而增加。如果你增强后的图片在现实中根本不可能出现,那这种增强就是有害的。

4. 模型训练与调优的完整流程

4.1 环境搭建与依赖安装

训练环境我推荐用Ubuntu 20.04或者22.04,Windows也能跑但有时候会遇到一些路径和CUDA的坑。Python版本用3.9到3.10比较稳,太高了有些库还不兼容。

显卡方面,至少需要8GB显存。YOLOv11s模型在640分辨率下训练,batch size设为16大概占用6到7GB显存。如果显存不够,可以减小batch size或者用梯度累积。我用过RTX 3060 12GB和RTX 4070 Ti,都能流畅跑。

安装步骤不复杂,但有几个细节要注意:

# 创建虚拟环境 conda create -n helmet_detection python=3.10 conda activate helmet_detection # 安装PyTorch,注意CUDA版本要匹配 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装Ultralytics pip install ultralytics # 验证安装 yolo checks

yolo checks这个命令会输出环境信息,包括PyTorch版本、CUDA是否可用、显卡型号等。如果CUDA显示不可用,大概率是PyTorch版本和CUDA驱动不匹配,需要重新装。

还有一个容易忽略的点:OpenCV的版本。Ultralytics依赖OpenCV做图像处理,如果版本太老或者太新,可能会报一些奇怪的错误。我一般锁定在4.8到4.9之间。

4.2 数据集配置文件与训练参数

Ultralytics用YAML文件来管理数据集配置。你需要创建一个helmet.yaml,内容大概是这样:

path: /path/to/your/dataset train: images/train val: images/val test: images/test nc: 3 names: 0: helmet 1: no_helmet 2: person

path是数据集根目录,train、val、test是相对于根目录的子目录。nc是类别数量,names是类别名称映射。

数据集划分比例我一般用7:2:1,就是70%训练、20%验证、10%测试。如果数据量少于2000张,可以用8:1:1,把更多数据留给训练。验证集的作用是监控训练过程中的过拟合情况,测试集是最后评估模型性能用的,训练过程中不能碰。

训练命令很简单:

yolo detect train data=helmet.yaml model=yolov11s.pt epochs=100 imgsz=640 batch=16 patience=20

但参数的选择有讲究。epochs设100是保守估计,如果验证集loss在20个epoch内没有下降,patience会触发早停。imgsz设640是平衡精度和速度的选择,如果目标普遍较小,可以提到1280,但显存占用会翻倍。

学习率方面,Ultralytics默认用余弦退火策略,初始学习率0.01。如果训练不稳定,可以降到0.001。我一般会加一个warmup_epochs=3,让模型在前3个epoch慢慢升温,避免一开始就震荡。

还有一个关键参数是optimizer。默认是SGD,但AdamW在小数据集上往往收敛更快。我实测下来,3000张数据用AdamW比SGD能早收敛大概10个epoch。但AdamW的最终精度可能略低一点,需要根据实际情况权衡。

4.3 训练过程监控与调参

训练启动后,Ultralytics会在runs/detect/train/目录下生成日志和权重文件。你需要关注几个关键指标。

box_loss和cls_loss是训练损失,正常情况下应该随着epoch逐渐下降。如果loss震荡很厉害,可能是学习率太高或者batch size太小。如果loss下降很慢,可能是学习率太低或者模型容量不够。

mAP50和mAP50-95是验证集上的精度指标。mAP50是IoU阈值为0.5时的平均精度,mAP50-95是IoU从0.5到0.95取平均,后者更严格。安全帽检测里,mAP50能达到0.9以上就算不错了,mAP50-95在0.6到0.7之间是正常水平。

如果发现验证集mAP在上升但训练集loss还在下降,说明开始过拟合了。这时候可以增加数据增强、加Dropout、或者减小模型复杂度。如果验证集mAP一直上不去,可能是欠拟合,需要增加模型容量或者训练更久。

我踩过的一个坑是:一开始用默认参数训练,mAP50卡在0.75上不去。后来发现是学习率太高,模型在最优解附近震荡。把学习率从0.01降到0.001后,mAP50直接跳到0.88。所以调参这件事,有时候就是差那么一点。

还有一个技巧是使用预训练权重。model=yolov11s.pt就是加载在COCO上预训练的权重,这比从零开始训练能快很多。如果你的数据集和COCO差异很大,也可以先在自己的数据上做一轮预训练,再fine-tune。

4.4 模型评估与导出

训练完成后,用测试集评估模型性能:

yolo detect val model=runs/detect/train/weights/best.pt data=helmet.yaml split=test

这个命令会输出各类别的precision、recall、mAP等指标。重点关注no_helmet类的recall,因为漏检未戴安全帽的人比误检戴了的人后果更严重。如果recall偏低,可以适当降低置信度阈值,但会牺牲一些precision。

模型导出方面,如果要在服务器上部署,导出ONNX格式最通用:

yolo export model=best.pt format=onnx opset=12 simplify=True

simplify=True会优化计算图,减少冗余算子,推理速度能提升10%到20%。如果要在NVIDIA显卡上部署,导出TensorRT引擎性能最好:

yolo export model=best.pt format=engine half=True device=0

half=True是FP16量化,精度损失很小但速度提升明显。不过TensorRT引擎和显卡型号绑定,换显卡需要重新导出。

5. 工程部署与现场调优的实战经验

5.1 推理服务架构设计

训练好的模型要变成可用的系统,还需要一套推理服务。我的架构设计是这样的:视频流接入层负责从摄像头拉流,解码成帧;推理层加载模型,对每一帧做检测;业务逻辑层根据检测结果判断是否告警,并记录到数据库;展示层提供Web界面,实时显示画面和告警信息。

视频流接入用OpenCV的VideoCapture就能搞定,但要注意摄像头的RTSP流有时候会断,需要加断线重连机制。我一般会起一个独立线程专门拉流,把最新的帧放到一个队列里,推理线程从队列取帧。这样即使推理慢一点,也不会阻塞拉流。

推理层可以用Flask或者FastAPI起一个HTTP服务,接收图片返回检测结果。但HTTP的开销比较大,如果对延迟敏感,可以用gRPC或者直接进程内调用。我实测下来,Flask处理单张图片的额外开销大概在5到10毫秒,对于25FPS的视频流来说可以接受。

业务逻辑层的关键是告警策略。不能每一帧检测到未戴安全帽就告警,那样会刷屏。我的做法是:连续3帧检测到同一个位置有未戴安全帽的人,才触发告警;告警后30秒内同一位置不再重复告警。这样既能及时发现问题,又不会产生大量冗余告警。

5.2 误报和漏报的现场调优

模型在测试集上表现好,不代表在现场就没问题。我遇到过几种典型的误报和漏报情况,这里分享一下排查和解决思路。

误报最常见的是把安全帽的帽檐或者阴影误判成未戴安全帽。这种情况通常是因为训练数据里缺少类似负样本。解决办法是收集这些误报的图片,加入训练集重新训练。我一般会做一个“误报收集”功能,把系统误报的图片自动保存下来,定期人工筛选后加入训练。

漏报最常见的是远处的小目标或者被遮挡的人。远处的人头部可能只有十几个像素,模型确实很难判断。解决办法一是提高输入分辨率,比如从640提到1280;二是用切片推理,把大图切成小块分别检测,但这样会增加计算量。我通常先试提高分辨率,如果显存不够再考虑切片。

还有一种情况是逆光。早晨和傍晚,摄像头对着太阳方向,人变成剪影,模型完全认不出来。这种问题靠模型本身很难解决,需要在摄像头层面做调整,比如加遮光罩或者调整安装角度。如果实在避不开,可以在训练数据里加入逆光样本,让模型学会从轮廓判断。

5.3 性能优化与硬件选型

如果要在边缘设备上部署,性能优化就很重要了。我试过几种方案,这里做个对比。

硬件平台模型格式推理速度(FPS)功耗适用场景
RTX 3060TensorRT FP1645-60170W服务器端多路
Jetson Orin NanoTensorRT FP1620-3015W边缘单路
树莓派5ONNX2-55W极低功耗场景
Intel NUCOpenVINO15-2530W边缘多路

从表格可以看出,如果对性能要求高,NVIDIA显卡加TensorRT是最优解。如果功耗受限,Jetson系列是首选。树莓派虽然便宜,但性能确实不够看,只能做极低帧率的检测。

还有一个优化点是模型量化。FP16量化基本不损失精度,速度提升30%左右。INT8量化速度更快,但精度可能下降5%到10%,需要做校准。我一般先用FP16,如果还不够快再考虑INT8。

5.4 常见问题速查表

问题现象可能原因排查方法解决方案
训练loss不下降学习率太低、数据标注错误检查标注文件、打印loss曲线提高学习率、重新标注
验证mAP远低于训练mAP过拟合对比训练和验证曲线增加数据增强、加Dropout
推理速度慢模型太大、未量化用yolo benchmark测试换小模型、导出TensorRT
误报多负样本不足收集误报图片分析加入负样本重新训练
漏报多小目标、遮挡可视化检测结果提高分辨率、切片推理
摄像头断流网络不稳定检查RTSP连接加断线重连、降低码率

这个表是我在实际项目中总结的,基本上覆盖了80%的常见问题。遇到问题先查表,能省不少时间。

6. 从项目到产品的几个关键思考

6.1 数据闭环的重要性

一个安全帽检测系统上线后,不是就完事了。现场环境会变化,工人着装会变化,摄像头角度可能被风吹偏。如果没有数据闭环,模型性能会随着时间推移逐渐下降。

我的做法是在系统里加一个“数据回流”功能:每次告警时,自动保存告警前后的视频片段和检测结果;每天定时把这些数据打包上传到训练服务器;每周做一次增量训练,用新数据fine-tune模型。这样模型能持续适应现场变化,保持较高的准确率。

数据闭环的关键是标注效率。如果每次都要人工标几千张图,没人受得了。我的经验是,只标注那些模型置信度在0.3到0.7之间的“难样本”,这些样本对模型提升最大。置信度很高的样本模型已经学会了,标了也是浪费时间。

6.2 告警策略的人性化设计

技术做完了,最后落地效果好不好,很大程度上取决于告警策略设计得是否人性化。如果系统一天告警几百次,安全员很快就会麻木,最后直接把告警关掉,系统就形同虚设了。

我的设计原则是:分级告警、聚合展示、闭环处理。分级告警是根据未戴安全帽的持续时间和位置来定告警级别,比如持续10秒以上或者在高风险区域,才触发高级别告警。聚合展示是把同一区域、同一时间的告警合并成一条,避免刷屏。闭环处理是要求安全员对每条告警做出响应(已处理/误报/忽略),系统记录响应情况,形成管理闭环。

还有一个细节是告警推送渠道。工地管理人员不一定一直盯着电脑屏幕,所以告警要能推送到手机。我一般用企业微信或者钉钉的机器人接口,把告警图片和位置信息推送到群里。这样响应速度能快很多。

6.3 成本与效益的平衡

最后聊一下成本。一套安全帽检测系统的成本主要包括:摄像头(如果已有监控系统可以复用)、边缘计算设备、软件开发和部署、后期维护。以一个中型工地为例,部署10路摄像头,用一台带RTX 3060的工控机做推理,硬件成本大概在1.5到2万之间。软件开发如果自己团队做,人力成本另算;如果买现成方案,大概每年几千到几万不等。

效益方面,最直接的是减少安全员人力成本。一个安全员一年成本大概8到10万,系统能替代至少2到3个安全员的巡查工作。更重要的是,安全事故的代价是巨大的,一次未戴安全帽导致的事故,赔偿和停工损失可能几十万起步。从这个角度看,系统的投入产出比是很高的。

当然,技术不是万能的。系统能发现未戴安全帽的人,但没法强制他戴上。最终还是要和管理制度配合,把告警和考核挂钩,才能真正发挥作用。我见过一些工地,系统装了但没人管,告警响了也没人处理,那就白装了。

我个人在实际项目中的体会是,安全帽检测这个方向技术已经比较成熟了,YOLOv11这类模型能提供足够好的基础能力。真正的挑战不在模型本身,而在数据质量、工程细节和现场配合。把这几块做好了,系统才能真正落地,而不是停留在演示阶段。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进