ARTICLE DETAIL

资讯详情

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

YOLOv8高空作业安全带检测实战:从数据集构建到TensorRT部署全复盘

YOLOv8高空作业安全带检测实战:从数据集构建到TensorRT部署全复盘 做施工安全和工业视觉落地的人肯定绕不开一个场景高空作业人员有没有系安全带。以前靠安全员盯监控眼睛能看花而且画面上人一多、背影一多根本看不过来。后来我把“YOLOv8高空作业安全带检测数据集”和“安全行为检测”这件事从头到尾做完了一遍从数据采集、标注、训练、评估到TensorRT 8.6部署和现场报警联动踩了不少坑也总结了一套能直接落地的流程。这篇文章就把整个项目复盘一遍重点讲清楚数据怎么整、类别怎么定、YOLOv8怎么训、部署时要注意什么以及那些文档上不会写的坑。想用YOLOv8做安全行为检测的同学、做施工安全项目的集成商或者正在准备相关毕设的人都可以参考。1. 项目整体设计与数据集构建思路1.1 高空作业场景下安全带检测为什么难很多人以为安全带检测就是训练一个模型把“背带”框出来就行真正上手才发现远没那么简单。高空作业的摄像头通常架在塔吊、杆塔、建筑外沿或者吊篮上机位高、角度刁画面上的人往往只有三四十个像素高背带在图上就是几条斜线模型很容易当成背景纹理丢掉。遮挡问题也很致命。脚手架、护栏、安全网会把人的下半身挡掉有时候只露出一个头和一截肩膀背带被反光背心遮住模型根本看不到“绑带交叉”这个关键特征。再加上工地背景特别乱钢筋、吊绳、斜拉索和背带形态接近单靠一个目标检测网络去区分确实要靠数据砸。还有一个很容易被忽略的问题安全带的形态差异很大。全身式安全带和半身式安全带视觉特征不一样不同厂家生产的背带反光条位置不同有些工人把背带穿在棉袄外面有些穿在里面只露出一根带子。只要现场样本不够全模型在白天晴天表现很好一到阴天或者傍晚就崩。所以这个项目的核心难点不在于“模型结构”而在于“数据能不能覆盖现场真实分布”。我在设计数据集时第一优先级不是追求yolov8的什么trick而是把高空作业的视角、光照、姿态、遮挡情况尽量铺满。1.2 数据集的类别设计与判定逻辑最开始我做的是单类别检测只检测safety_harness也就是把背带框出来。上线测试后发现误报非常严重工人手里拿着背带、背带挂在栏杆上、甚至地面堆着一团安全绳都会被当成“已佩戴安全带”。因为目标检测模型看到的是局部它不知道这条背带到底穿没穿在人身上。后来把方案改成两类检测worker_safe人员已正确穿戴安全带worker_unsafe人员未穿戴安全带或穿戴不规范这样做的逻辑是把“安全行为判定”直接转化成“人员目标分类”。检测器先定位人再判断这个人属于安全还是不安全模型学到的是“人背带同时出现且位置关系合理”的组合特征而不是单独的背带特征。对于安全监管场景报警信号直接来自worker_unsafe这一类不用再做额外的空间匹配逻辑流程简单也更容易满足实时性要求。类别数量还能扩展到三类比如worker_safe、worker_unsafe、uncertain。uncertain用来处理那些遮挡严重、难以判断的样本。但实际使用中uncertain这个类别很容易被模型当成“垃圾桶”导致原本能分清的样本也往里面丢。我在项目里最终放弃了uncertain而是把这些难样本通过background类或者忽略区域处理效果反而更好。1.3 数据集规模与划分策略这个项目的数据集我最终定了大约12000张图其中安全样本约8000张不安全样本约4000张。比例不是随便拍的而是根据现场真实分布来的。施工现场系安全带的合规率通常在80%左右按这个比例去采样模型才能学到合理的先验。训练集、验证集、测试集的划分有一个大坑视频抽帧出来的连续帧非常相似如果随机划分同一段视频的相邻帧会同时出现在训练集和验证集里验证指标会虚高。必须按“视频片段”划分保证同一个摄像头、同一段时间的视频帧全部落在同一个集合中。我在项目里是这样做的先按日期和机位把视频切片比如每3分钟一个片段然后按片段分配train/val/test比例大概8:1:1。这样验证集的指标才真正反映模型面对新场景的能力。2. 数据采集、标注与预处理实战2.1 数据从哪来现场、公开集、合成数据数据集是这类项目的命根子但大多数人一开始手里根本没数据。我的经验是分三条线同步推。第一条线是现场监控视频抽帧。这是质量最高、最贴合业务的来源。从工地监控系统里导出不同机位、不同班次、不同天气的视频按每秒1帧或者每5秒1帧抽抽完先做一次人工粗筛把模糊、过暗、遮挡太严重的图丢掉。实际筛下来10000张原始抽帧里能留下6000张就不错了。第二条线是公开数据。网上有安全帽检测数据集、建筑工地人员数据集里面多少会带一些安全带样本。这类数据可以补足不同角度、不同服装的多样性但一定要人眼过一遍因为公开数据集的标注质量参差不齐有些图把安全绳的绳端当成了背带主体直接用会污染模型。第三条线是合成数据。用3D仿真软件或者图像合成工具把人物和安全带的贴图随机贴到工地背景上能补充极端罕见场景比如工人站在吊篮边缘、背带被完全遮住但能看出没系。合成数据只建议占训练集5%-10%纯度不够的话模型容易学到假的纹理。2.2 标注规范这些细节决定模型上限标注工具我用过LabelImg、X-AnyLabeling、CVAT最终项目里主力是X-AnyLabeling支持自动标注预标注、效率高适合大批量数据。但工具是次要的标注规范才是决定模型上限的东西。我的标注规范里有几条硬性要求每个被检测的人员目标必须有一个bbox框要贴住人不能把安全绳延伸到框外太长。worker_safe和worker_unsafe的判断标准安全带穿戴完整、卡扣扣好才算safe只披在身上没扣、或者完全没穿都算unsafe。人目标被遮挡超过70%时不标注避免给模型传递混乱信号。远小于20x20像素的目标不标注。硬标会让模型在训练时产生大量低质量正样本拉低整体精度。视频连续帧中同一个人的状态突变比如上一帧safe下一帧unsafe要重点核查经常是标错了。标注字段我还会额外记录“遮挡程度”“目标尺度”“是否模糊”这几个属性虽然YOLOv8训练时不会直接用这些字段但在做错误分析和数据集补充时非常有用。比如我发现模型在“中等遮挡远小目标”上误报集中就专门去补充这一类样本比盲目加数据高效得多。2.3 数据增强与规模控制的平衡YOLOv8自带了一些增强策略比如Mosaic、MixUp、HSV扰动、随机透视效果很好但不是越猛越好。高空作业场景的背景本身就比较单一大量使用Mosaic会把工地背景切成碎片模型容易学到奇怪的特征。我的做法是分阶段调整增强参数。第一遍用默认增强跑一个baseline看loss曲线和验证集表现。如果存在过拟合再逐步增强Mosaic和MixUp的权重如果模型在远小目标上漏检就增加多尺度训练的强度比如让输入尺寸在960到1280之间随机波动。针对现场摄像头普遍存在的运动模糊问题我在训练集中随机加了高斯模糊和轻微的运动模糊增强模拟工人快速移动、摄像头抖动的情况。加了之后模型在早晚高峰工人集中上工时的表现提升特别明显这个增强在常规项目里很少有人注意。另外尽量不要对视频抽帧连续截图做同样的增强后全部塞进训练集这些增强后的图在背景上高度相似只会增加训练时间对泛化能力帮助很小。正确的做法是先把连续帧去重只保留画面变化比较大的帧再进行增强。3. YOLOv8训练全流程与参数调优3.1 数据集组织与配置文件YOLOv8的数据集目录结构很简单按官方约定组织就行datasets/harness/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── harness.yamlharness.yaml内容path: /data/datasets/harness train: images/train val: images/val nc: 2 names: 0: worker_safe 1: worker_unsafe这里有一个不起眼但很重要的点类别顺序一旦定下来就不要频繁改动。你训练出模型后导出ONNX做TensorRT部署写C后处理解析结果的索引全部依赖这个顺序。如果中途改了类别顺序之前训练的权重就全部作废部署端也要同步改非常折腾。3.2 训练命令与关键参数选择我用的训练命令大概是这样yolo detect train \ dataharness.yaml \ modelyolov8m.pt \ epochs200 \ imgsz1280 \ batch16 \ patience30 \ optimizerSGD \ lr00.01 \ lrf0.001 \ weight_decay0.0005 \ warmup_epochs3.0 \ cos_lrTrue有些参数值得展开说。输入尺寸imgsz我选了1280而不是默认的640。原因很简单高空作业摄像头画面视野大人员目标小640尺寸下一个人就十几个像素特征基本糊掉。用到1280后小目标mAP提升了将近8个百分点。如果你的部署设备性能有限建议先用1280训练再在导出模型时用640做TensorRT的输入尺寸虽然有些精度损失但还能保留一部分小目标特征。模型规模选了yolov8m不是最大最好的yolov8x。高空作业安全带检测的难点在召回率而不在类别细分能力yolov8m在精度和速度之间最均衡。真上了yolov8x精度提升不到1%推理速度掉了近一半做边缘端部署时非常不划算。batch size的设定要兼顾显存。在GTX 1660Ti这种6GB显存的卡上训练imgsz1280时batch16会爆显存可以降到4-8或者干脆把imgsz降到960。YOLOv8对batch size不敏感batch小一点最多收敛慢一点不会出大问题。3.3 损失函数曲线怎么看别等训练完才发现问题YOLOv8训练会生成results.csv里面包含box_loss、cls_loss、dfl_loss、precision、recall、mAP50等字段。我习惯用一段简单脚本把曲线画出来import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/detect/train/results.csv) epochs df[epoch] fig, ax plt.subplots(2, 2, figsize(14, 10)) ax[0, 0].plot(epochs, df[train/box_loss], labelbox_loss) ax[0, 1].plot(epochs, df[train/cls_loss], labelcls_loss) ax[1, 0].plot(epochs, df[train/dfl_loss], labeldfl_loss) ax[1, 1].plot(epochs, df[metrics/mAP50(B)], labelmAP50) for a in ax.flat: a.legend() a.set_xlabel(epoch) plt.tight_layout() plt.savefig(training_curves.png)看曲线有几个判断方法。前30个epoch如果box_loss从1.6左右降到1.2以下说明模型在正常学习。如果loss曲线震荡非常剧烈先看batch size是不是太小、学习率是不是太高。如果训练loss还在降、验证集的mAP50已经连续20个epoch不涨那就是过拟合信号patience参数会自动触发早停但我会更早介入先降低增强强度或者加数据。我那个项目到最后box_loss稳定在0.7左右mAP50到了0.93mAP50-95在0.63看起来不算特别夸张但在现场部署时漏报率控制得很好因为更关键的指标是recall尤其对worker_unsafe这个类别。训练时要专门看每个类别的召回率别被整体mAP糊弄过去。3.4 模型评估与置信度阈值怎么定训练完用验证集跑一遍评估yolo detect val dataharness.yaml modelruns/detect/train/weights/best.pt imgsz1280除了mAP我还会重点看PR曲线和F1曲线。YOLOv8会在验证目录下生成F1_curve.png和PR_curve.png。安全行为检测和一般目标检测不一样它对worker_unsafe的召回率要求极高宁可误报也不能漏报。实际使用中我把默认的conf0.25调到conf0.15让模型对不安全状态更敏感。代价是误报会增加但配合后面的时序判定和区域过滤误报能压下去。单纯看单帧准确率conf0.15时的precision只有78%但连续10帧里有8帧报警才触发联动实际现场误报率可以控制在每天几次以内完全可以接受。4. 安全行为判定逻辑与后处理4.1 从单帧检测到连续行为判定目标检测模型输出的每一帧结果只是单帧判断直接拿着去报警会被瞬间误检搞得痛苦不堪。防风打火机闪一下、工人弯腰捡东西、摄像头抖动一下都可能导致单帧误判。所以我在检测后面加了一层轻量级的行为状态机。做法是用IoU匹配算法对相邻帧的检测框做关联给每个目标维护一个状态结构体大致逻辑是track_state { track_id: 1, unsafe_count: 0, total_count: 0, is_alerting: False }每来一帧先做检测然后做目标匹配。如果某个目标匹配上就更新它的类别计数。判定规则是连续10帧中worker_unsafe占7帧以上并且持续时间超过5秒才触发报警。一旦触发报警进入5分钟冷却期等现场处理完再重新判定。这个逻辑能把大部分偶发误检过滤掉但有一个代价真正发生危险动作时报警会有几秒延迟。对施工安全来说5秒以内的延迟可以接受因为报警本来就是为了通知安全员去现场处理不是做毫秒级紧急制动。4.2 区域联动与电子围栏高空作业摄像头画面很大并不是所有区域都需要做安全带检测。比如画面上有地面通道、材料堆放区工人路过时没系安全带不应该触发报警。我给每个摄像头配置了ROI多边形只有检测框中心点落在ROI内才参与行为判定。ROI配置在界面上就是画一个多边形存成json文件。现场改动很容易。这套区域联动机制还有一个好处同一路摄像头可以配置多个ROI比如塔吊臂上是一个ROI钢平台上又是一个ROI每个ROI的判定阈值可以单独设灵活很多。4.3 边缘部署TensorRT 8.6与RK3588模型训练完只是第一步现场设备大多不是插着4090的服务器而是Jetson、RK3588这种边缘盒子。我落地时主要做了两条部署路径。首先是TensorRT 8.6部署。流程是先用Ultralytics导出ONNXyolo export modelbest.pt formatonnx imgsz1280 opset12 simplifyTrue然后用TensorRT构建enginetrtexec --onnxbest.onnx --saveEnginebest.engine --fp16 --workspace2048C端用TensorRT的C API加载engine输入输出是float数组后处理里要做NMS过滤和坐标换算。这一步坑很多最典型的是TensorRT各版本API不兼容编译时一定要锁死版本我用的是8.6.1.6配套的CUDA和cudnn版本也要一致。另一个坑是动态shape。如果导出的ONNX是动态输入尺寸TensorRT构建engine时会多花时间而且容易报错。我直接固定输入尺寸为1280x1280舍弃动态输入换来更快的推理速度和更稳定的构建过程。第二条路径是RK3588的NPU部署。流程是先导出ONNX然后用rknn-toolkit2转成rknn模型再烧到3588的NPU上跑。RK3588部署YOLOv8有几个注意点ONNX的opset要设成12太高某些算子不支持转模型时要指定mean_values和scale_values不同训练代码出来的预处理参数不一样转完一定要用同一张测试图对比输出看误差在不在接受范围。我的经验是用TensorRT跑在Jetson Orin Nano上FP16精度下1280x1280输入YOLOv8m推理速度大约25毫秒用RK3588 NPU跑640x640输入YOLOv8s大约35毫秒。边缘端如果资源紧张就退而求其次用640输入虽然小目标检测能力变弱但通过扩大ROI和时序判定工程上还是可以接受。5. 常见问题与排查技巧实录5.1 数据集与标注问题这个项目里最常见的数据问题是样本不均衡。我一开始标注时安全样本远多于不安全样本比例接近9:1训练出的模型对worker_unsafe不敏感。解决方法是单独采集不安全场景的视频或者用数据增强针对不安全类别做过采样。我当时是把不安全样本重复复制并做轻度增强把训练集比例调整到7:3召回率提升很明显。还有一个很隐蔽的问题标注框的类别标反了。几个标注员对“安全带穿但不扣”算safe还是unsafe理解不一致导致同一批数据里同类样本特征互相冲突训练loss很难降下去。后来我建了一个标注FAQ把安全穿戴的几个关键判断点用截图列出来让所有标注人员照着执行问题才慢慢消失。5.2 训练效果不理想的排查如果你遇到底层loss降不下去或者mAP波动大先检查三件事类别概率是否均匀、标注框是否越界、训练集是否包含大量重复帧。YOLOv8训练过程中如果loss在某个数值附近持续震荡大概率是数据有噪声而不是模型结构有bug。显存不够也是高频问题。GTX 1660Ti跑1280输入时batch只能设4这时候不要硬扛可以开启cacheTrue减少磁盘IO或者把workers调高但最有效的还是降batch、降输入尺寸。我遇到过最典型的训练问题是训练集mAP很高验证集mAP很低。原因是视频抽帧的数据泄漏。后来按视频片段划分数据集后这个现象立刻消失了。5.3 部署运行阶段的坑部署阶段的高频问题我整理成了速查表问题现象可能原因解决方案TensorRT推理结果和PyTorch差异大ONNX导出时opset或预处理不一致对比同一张图的预处理统一mean/std和缩放方式推理速度慢帧率不高输入尺寸太大、模型过大、没有开FP16改用640输入、换yolov8s、开启FP16报警总是漏报置信度阈值太高、ROI没覆盖目标区域调低conf、扩大ROI报警总是误报缺少时序判定、单帧直接报警增加连续帧计数和状态机夜间红外画面检测效果差训练集里缺乏红外样本单独采集夜间数据或在训练时加灰度化和亮度增强RK3588转换报错ONNX包含不支持的算子降低opset、固定输入尺寸、逐层检查算子经验就是部署阶段的问题绝大多数不是因为模型训练得不好而是数据格式和预处理不一致造成的。所以我每次换部署平台第一件事不是看算法而是拿同一张现场图走一遍完整链路对比输出框是否一致。这一条建议能帮你省掉至少一半的排查时间。6. 个人心得与后续扩展建议做了整个项目之后我最真实的体会是做安全行为检测不要一上来就想着改YOLOv8的结构、加注意力机制、魔改head。对这个小目标、强干扰、真实落地的场景来说数据质量、标注一致性、时序判定和部署优化才是决定项目成败的四个支柱。模型本身用官方YOLOv8m就足够能打了真正拉开差距的是你愿不愿意在数据清洗、难样本挖掘上下功夫。还有一个经验是现场算法要留人工接管的口子。安全行为检测再准也不可能100%判断所有情况尤其是工人背对摄像头、背带被完全遮住的时候。给现场安全员做一个简单的一键确认和报警复核流程比追求模型完美更实际。最后再分享一个小技巧采集数据时不要只在天气好的白天拍。一定要安排夜间、雨天、逆光时段各拍一批哪怕数量少。因为摄像头部署后的真实运行环境往往是模型训练时最缺少的那部分。把这些“不好看”的样本补进去模型在夜间和恶劣天气下的鲁棒性会提升一大截。这个项目后续如果要扩展可以往两个方向走一是加上安全帽、反光衣、人员越界检测合成一套完整的施工安全行为识别方案二是把安全带检测从检测框升级为关键点检测识别双钩是否挂好、安全绳是否系在挂点上这种更细的行为判断才是施工安全AI真正值钱的地方。
返回列表