资讯动态

YOLOv8训练工地安全目标检测:600张图从标签体检到部署实践

发布时间:2026/10/1 13:21:16 来源:尧图企业网站定制
简介建筑工地安全目标检测数据集提供了一套面向AI视觉开发者和工地安防系统研发的YOLO标准训练资源。数据源自真实工地监控画面共600张已标注图片训练集426张、验证集117张、测试集57张覆盖靴子、安全帽、机械、人员、安全背心等8个类别同时标注无安全帽、无口罩、无安全背心等违规行为可用于装备佩戴检测与违规预警。包体共1202个文件以jpg图片与txt标注文件为主另含yaml配置及docx说明文档整体压缩后约37.43MB可接入YOLOv5、YOLOv8等常用框架快速部署。目前已有264人学习下载。依托这份数据用户可开展多类别目标检测实验搭建工地安全智能监控原型降低数据采集与标注成本也能为工业安全管理及高校计算机视觉研究提供贴近真实场景的支撑素材。1. 建筑工地安全目标检测数据集600张真实监控图能训出什么做工地安全监控的人拿到这份建筑工地安全目标检测数据集最容易犯的错是直接丢给YOLOv8开训。600张真实工地监控画面、8个类别、YOLO格式标注看起来一步就能跑通实际上拆开看才发现违规类无安全帽、无口罩、无安全背心和装备类高度重叠机械类样本稀少类名还有拼写坑。这些信息不提前盘清楚后面盯着训练日志调参就是瞎调。这篇文章按我拆数据集的习惯来写先查目录和标签结构再配置YOLOv8跑通训练评估时看混淆矩阵和badcase最后补两个部署阶段的实用动作。适合做工业安防、工地智能监控以及想拿真实场景练手目标检测的开发者。2. 先盘数据集目录结构、YOLO标签格式与8个类别分布拿到zip包第一件事不是解压了就跑而是把压缩包内的目录结构搞清楚。这个数据集来自Roboflow导出从文件名里那一串_jpg.rf.就能看出来——这是平台处理过后重命名的产物中间那段十六进制哈希是图片增强链路的标记。真正在训练时起作用的是文件名主体和标注文件的同名对应关系哈希部分不影响训练但会影响你后续人工核对badcase时认图。2.1 解压后的目录600张图片和600个txt怎么对应Roboflow导出的YOLO格式压缩包解压后一般是train / valid / test三个子集每个子集里再分images和labels。这份数据集对应关系是训练集426张、验证集117张、测试集57张。images里放.jpg图片labels里放同名.txt标注文件一个jpg对应一个txt没有txt的图片在训练时会被静默跳过。# 解压后先核对三个子集数量 find train/images -name *.jpg | wc -l # 应为426 find train/labels -name *.txt | wc -l # 应为426 # 再检查同名对应缺标签的文件会被跳过 for img in train/images/*.jpg; do txttrain/labels/$(basename $img .jpg).txt [ -f $txt ] || echo missing label: $img done这段脚本的价值在于YOLO训练框架不会因为你少几个txt报错而是直接把对应图片剔除出训练队列。如果缺失发生在某个稀有类别上你连日志都看不出问题只会发现某个类的AP莫名偏低。我一般会把这个检查脚本在train、valid、test三个子集上都跑一遍确保图片和标注是完整配对的。另外注意test子集在训练阶段完全不用碰它是留给你最后验证模型泛化能力的。很多新手把test也塞进训练导致评估时分数虚高那叫自欺欺人。2.2 YOLO标签格式归一化坐标与标签体检脚本YOLO格式的每个txt文件里一行代表一个目标共5个数值类别ID、归一化中心点x、归一化中心点y、归一化宽度w、归一化高度h。所有坐标都除以了图片宽高值域在0到1之间。看不懂这个后面排查标签越界问题就无从下手。import random from glob import glob txts glob(train/labels/*.txt) sample random.choice(txts) with open(sample) as f: for line in f.read().strip().splitlines(): class_id, cx, cy, w, h line.split() print(fclass{class_id}, cx{cx}, cy{cy}, w{w}, h{h})我们随机抽一个标签文件打开看class6, cx0.482, cy0.531, w0.118, h0.204。意思是类别ID为6对应Person类目标中心点在图片水平48.2%、垂直53.1%的位置宽度占整图11.8%高度占20.4%。要换算成像素坐标就用cx*图片宽、cy*图片高。这种归一化格式的好处是和图片分辨率解耦训练时无论缩放到640还是1280坐标比例都不变。下一个动作是体检检查所有txt的坐标值是否都在0到1范围内。越界坐标会导致训练时边界框计算异常轻则loss波动重则训练崩掉。import os from glob import glob bad 0 for txt in glob(train/labels/*.txt) glob(valid/labels/*.txt): for line in open(txt).read().strip().splitlines(): cid, cx, cy, w, h map(float, line.split()) if not (0 cx 1 and 0 cy 1 and 0 w 1 and 0 h 1): print(fout-of-range: {txt} - {line}) bad 1 print(ftotal bad lines: {bad})这个脚本看起来简单但实际作用很大。常见情况是某些增强脚本把物体放到了画布外导致w或h超过1模型在loss计算时对这类框给出的梯度是畸形的。我见过有人因为这类越界标签训练了50轮loss都降不下去最后定位到是几百个脏标注在拖后腿。2.3 8个类别逐个拆解装备类、违规类和机械类数据集涵盖8个类别按语义可以分成三组安全装备Boots、Hardhat、Safetyvest、违规行为No-Hardhat、No-mask、No-safetyvest、以及人和设备Person、Machinary。类别ID按摘要里列出的顺序从0到7排列实际以压缩包内data.yaml的names字段为准我按常见顺序整理如下类别ID名称类型业务含义0Boots装备工地防护靴1Hardhat装备佩戴安全帽2Machinary设备起重机等施工机械3No-Hardhat违规未佩戴安全帽4No-mask违规未佩戴口罩5No-safetyvest违规未穿反光安全背心6Person人员工地工作人员7Safetyvest装备穿戴反光安全背心这里有两个容易被忽略的细节。第一Machinary这个类名在数据集里就是拼写错误的正确拼写是Machinery但训练时千万别手滑改成正确拼写因为标签txt里的类别ID和data.yaml的names是一一对应的改名字不改ID不影响改错位置就会错位。第二违规类和装备类是成对出现的一个人戴了安全帽图上会有Person和Hardhat两个框没戴安全帽就会有Person和No-Hardhat。这就是第4章要展开讲的标签语义重叠问题它直接影响你在混淆矩阵里看到的误检分布。从业务视角看这个数据集对应的就是一个智能安全巡检系统识别工人有没有戴安全帽、穿反光背心、佩戴口罩同时识别工地上的大型机械。600张图对8个类别来说属于中小规模数据集如果某个类别的样本量特别稀少比如机械训练时就需要特殊处理这个在第4章的Machinary问题里具体展开。3. 用YOLOv8把它训起来目录整理、data.yaml与训练命令数据集结构盘清楚了接下来就是把它喂给YOLOv8。这里我不推荐拿着Roboflow原始目录结构直接用而是建议统一成Ultralytics官方推荐的布局images和labels两个大目录内部再按train/val/test切分。这样做的好处是后续换数据集、换模型版本时训练脚本和data.yaml可以完全复用。3.1 统一目录结构与data.yaml配置先建目录、把文件归位。这一步纯粹是体力活但目录不统一后续每次训练都要改路径很烦。mkdir -p datasets/site_safety/images/train mkdir -p datasets/site_safety/images/val mkdir -p datasets/site_safety/images/test mkdir -p datasets/site_safety/labels/train mkdir -p datasets/site_safety/labels/val mkdir -p datasets/site_safety/labels/test cp train/images/*.jpg datasets/site_safety/images/train/ cp train/labels/*.txt datasets/site_safety/labels/train/ cp valid/images/*.jpg datasets/site_safety/images/val/ cp valid/labels/*.txt datasets/site_safety/labels/val/ cp test/images/*.jpg datasets/site_safety/images/test/ cp test/labels/*.txt datasets/site_safety/labels/test/复制完之后用前面的find | wc -l再核对一遍确保每个子集的图片和标签数量一致。然后创建data.yaml。这里注意path字段使用相对路径不要写/home/xxx/这种绝对路径否则换机器跑就得改配置。# datasets/site_safety/data.yaml path: ./datasets/site_safety train: images/train val: images/val test: images/test names: 0: Boots 1: Hardhat 2: Machinary 3: No-Hardhat 4: No-mask 5: No-safetyvest 6: Person 7: Safetyvestnames的顺序必须和标签txt里的类别ID完全对齐这是YOLO系列训练框架的硬性要求错一位就是灾难性的类别错位。test字段写上并不会影响训练只是在训练完调用val时可以指定用test子集来评估这样得到的指标才是模型在没见过的数据上的真实表现。3.2 训练命令与关键超参img、batch、epochs怎么定600张图、8个类别这个规模下我不建议直接用YOLOv8m或者更大的模型。常见做法是从最小的yolov8n开始用COCO预训练权重做迁移。COCO上训过的权重已经学会了通用的边缘、纹理和物体形状特征迁移到工地场景能显著缓解小数据量带来的欠拟合问题。# 在项目根目录执行 yolo detect train \ modelyolov8n.pt \ datadatasets/site_safety/data.yaml \ epochs100 \ img640 \ batch16 \ patience20 \ projectruns/site_safety \ nameyolov8n_600img逐项说明参数含义。modelyolov8n.pt表示加载COCO预训练权重启动训练而不是随机初始化如果不加这个参数从零训练600张图的效果会差很多。epochs100对600张图是合理范围配合patience20早停机制如果验证集mAP连续20轮不涨就自动停止避免浪费时间。img640是训练分辨率也是默认推理分辨率如果你发现监控画面里远处的人很小可以尝试img1280效果可能有明显提升但显存占用和推理耗时都会上涨。batch16在8GB显存上刚好如果显存告急就降到8。Ultralytics默认开启了mosaic、hsv扰动等数据增强在小数据集上默认配置通常不用改这也是YOLOv8这类框架对小数据集友好的原因之一。我自己在600张图规模上一般不加额外增强参数先跑一个baseline有问题再针对性地开增强。这里隐含的策略是先拿baseline暴露问题而不是一上来就堆技巧。3.3 训练产物best.pt、results.csv、confusion_matrix去哪找训练结束后输出目录下会有完整的过程记录和控制台输出的汇总ls runs/site_safety/yolov8n_600img/ # weights/ best.pt last.pt # results.csv 每轮的loss、mAP、PR曲线数据 # confusion_matrix.png 验证集混淆矩阵图 # PR_curve.png 每个类别的PR曲线 # train_batch*.jpg 训练批次的增强可视化这里最重要的两个文件是weights/best.pt和weights/last.pt。best.pt是验证集mAP最高那轮的权重后续做推理、导出ONNX都用它last.pt只是最后一轮的状态通常直接用best。results.csv是判断训练是否健康的关键依据看loss曲线是否平稳下降、mAP50是否逐步爬升。如果loss降了但mAP不动说明模型在死记训练集而没有学到可泛化的特征这种问题在标签语义重叠的数据集里特别常见下一章展开说。4. 常见问题排查这份工地数据集训练时的五个坑这一章是整篇文章里最值钱的部分。前面几章是流程这里是我实际拆数据时踩过的坑。每一条都按“现象→原因→解决”来写你在训练这份数据集时如果碰到类似症状直接对号入座。4.1 标签体检漏掉图片比预期少某个类完全学不出来现象训练日志里显示的图片数比426少或者某个类别在混淆矩阵里一整行都是黑的AP数值在0.05以下徘徊。原因jpg和txt不同名导致图片被静默跳过。Roboflow导出的文件名很长里面带哈希和rf标记有些人用脚本批量移动文件时按.切割文件名切出来的主体对不上造成label丢失。还有一种情况是txt里存在空文件YOLO训练框架读到空标签会跳过该图。解决训练前强制跑一遍2.1和2.2里的脚本把缺失标签的图片和空txt文件全部列出来。缺失的看能不能从原始数据补补不了就直接删掉对应图片保证训练集“图标配对”是干净的。从那以后我每次拿到新数据集都会先做这一步几分钟的时间能省下后面好几轮的排查。4.2 安全帽和人员互相误检Hardhat与Person严重混淆现象验证集上Hardhat的检出框经常压在Person框上明明没戴安全帽的人也被打上Hardhat标签。混淆矩阵里Hardhat和Person两块交叉位置亮度很高。原因这是标注语义本身的问题。一个戴安全帽的工人图片上同时有Person框和Hardhat框两个框的中心高度重叠模型学到的特征是“凡是像人的地方大概率有安全帽”。如果训练数据里戴帽子的正例远多于背景反例模型就会把Person和Hardhat当成强绑定关系。解决先看混淆矩阵确认混淆程度然后再决定策略。轻度的可以用后处理规则修正——同一位置如果同时出现Hardhat和No-Hardhat按置信度取高者严重的可以考虑干脆把标注合并成二分类只检测Hardhat戴帽和No-Hardhat没戴帽去掉Person类让模型专注解决戴没戴的问题。我在类似场景做过这种删类合并因为对工地安全监控来说真正要报警的就是“有人且没戴帽”Person类本身并没有独立业务价值。4.3 Machinary类持久学不出来mAP一直趋近于0现象loss正常下降其他类别AP都在涨只有Machinary类的AP曲线贴着0轴走混淆矩阵里这一行几乎全黑检测结果偶尔把它预测成Person或背景。原因机械类样本太少。这份数据集总共600张图、8个类别分配到Machinary上的可能只有几十个实例而且起重机和挖掘机在不同角度、不同距离下的外观差异极大几十个样本根本覆盖不了类内差异。模型在有限的迭代轮次里只能记住训练集里那几张图的样子泛化自然无从谈起。解决短期内把Machinary类别从训练里去掉把它对应的框忽略掉先保住其他7个类别的精度。长期看如果你真的需要机械检测就得单独补充机械类数据哪怕补100张也比在这600张图里硬扛强。另外注意一个操作细节删类时标签txt里的其他类别ID要重新排不能留空洞否则ID对不上names。4.4 远处安全帽漏检近处能检远处一塌糊涂现象靠近摄像头的工人检测效果不错越远的画面漏检越严重。mAP50可能还行但mAP50-95低得离谱。原因640分辨率下远处一个安全帽可能只有十几个像素宽的小目标特征。YOLOv8n本身对小目标不敏感加上训练分辨率压到640小目标信息在特征图下采样过程中被抹掉了。工地监控的特点是视野宽、目标密集这个问题几乎一定会出现。解决第一步把img提到1280训练和推理通常小目标AP会有肉眼可见的提升代价是显存占用翻倍、推理速度变慢。如果后期要部署到实时监控就用切图推理把大图切成512×512的块分别检测再合并结果。这个方案现在已经很成熟推荐给有实时需求的场景。4.5 训练中途loss变成NaN先查脏标签和坏图现象训练进行到十几轮loss突然变成nan之后每个epoch的loss都是nan训练实际上已经失效。原因最常见的是数据集里混入了损坏图片jpg文件不完整或者标签里有极端坐标值比如w或h为0的框甚至类别ID超出names长度。这种脏数据在训练中被随机采样到导致loss计算出现除零或梯度爆炸。解决写一个脚本遍历所有图片用OpenCV读取读不出来的标记为损坏并剔除同时用2.2的越界检查脚本把所有txt过滤一遍发现w或h为0的行直接删掉。如果是梯度爆炸导致的把lr0从默认的0.01降到0.005再试但优先还是处理数据。5. 验证模型而不是相信训练日志val评估、PR曲线与badcase分析训练完看loss曲线觉得“稳了”就收工是很多新手的习惯。但在这个数据集上训练loss下降只能说明模型记住了训练集验证集上的表现才是真正要关注的。第3章里训练日志最后输出的mAP值只是训练过程中对验证集的一个快照远不够全面。这里用测试集做独立评估再结合badcase分析得到的是可落地判断。5.1 用测试集评估命令与指标取舍# 用57张测试集图片评估而不是默认的验证集 yolo detect val \ modelruns/site_safety/yolov8n_600img/weights/best.pt \ datadatasets/site_safety/data.yaml \ splittest \ conf0.25 \ iou0.5splittest是这里的要点。Ultralytics默认用val目录做评估但我们在第3章配置了test字段加上这个参数就会用那57张从未参与训练和验证的图片来评估结果更接近部署时的真实表现。conf0.25是默认置信度阈值iou0.5是NMS的IoU阈值刚开始评估就用默认值跑出baseline再说。输出会给出每个类别单独的mAP50和mAP50-95这才是判断每个类健康状况的第一手资料。mAP50和mAP50-95的区别要明确mAP50只要求预测框和真实框交并比超过0.5就算对比较宽容mAP50-95会对从0.5到0.95的一系列IoU阈值平均要求极其严格。小目标居多的数据集mAP50-95普遍偏低这不必焦虑——工地安全监控这个场景框的位置大致准就行mAP50才是主要参考指标mAP50-95用来横向对比模型版本。5.2 混淆矩阵的读法重点看哪几个位置confusion_matrix.png是一个8类背景的方阵行代表真实类别列代表预测类别对角线越亮越好。拿到图先不急着看整体准确率而是盯着三块位置一是Hardhat行里和Person列交叉的地方亮则代表安全帽被误检成人员二是No-Hardhat行里和背景列交叉的地方亮则代表未戴帽违规行为被漏检三是背景行里如果有大块亮区说明模型在没有任何目标的地方画了框这类误检在巡检场景会直接触发误报。读混淆矩阵还有一个技巧不要只看亮不亮要看同行的其他列是否出现“结构性偏斜”。比如Person行里Hardhat列也很亮说明模型本质上把“人”和“帽子”耦合了这就是4.2说的语义重叠问题在图上会表现为戴帽和没戴帽的检测结果互相打架。解决方向在前面已经说了合并类别或者加后处理规则而不是单纯堆训练轮次。5.3 badcase可视化按置信度排序找最难样本指标是汇总数据badcase才是具体问题。用训练好的模型跑一遍测试集把预测结果可视化输出然后人工翻图。注意不要随机翻按置信度排序来看。from ultralytics import YOLO model YOLO(runs/site_safety/yolov8n_600img/weights/best.pt) results model.predict( sourcedatasets/site_safety/images/test, conf0.25, saveTrue, # 把标注了框的图片存下来 projectruns/badcase, nametest_pred, save_txtTrue, # 同时输出预测的txt标注方便后续对比 )跑完之后runs/badcase/test_pred里每张图都画了预测框。我一般先从置信度最高的误检看起——高置信度还检错说明模型学到了一个错误模式这是最要命的然后看漏检特别是No-Hardhat的漏检因为这是工地安全监控的核心报警项。corresponding的txt文件可以用来和真实标注做IoU对比IoU低的那批图就是你需要针对性补数据的样本或者需要调整后处理逻辑的样本。6. 进阶部署到工地实时监控前先做这两个动作训练好的模型要真正放到工地监控里光有best.pt是不够的。工地现场跑的一般是边缘计算盒子或者带GPU的NVR设备PyTorch直接推理在性能和部署友好度上都不过关。第一步先把模型导成ONNX格式。yolo export modelruns/site_safety/yolov8n_600img/weights/best.pt \ formatonnx \ opset12 \ imgsz640导出后得到一个best.onnx用ONNX Runtime或者OpenVINO都能直接跑。opset12是兼容性比较好的版本老设备也能识别。导出前可以先跑一遍val对比ONNX和PyTorch的mAP因为量化或opset转换偶尔会带来精度损失如果掉了超过1个点就要检查哪层出了问题。第二个动作是设计报警后处理规则这是工地场景区别于通用目标检测的地方。监控视频每秒25帧不可能每帧都报警否则误报会淹没真实违规。常见做法是帧采样加持续确认每5秒取一帧做检测检测结果不直接触发报警而是送入一个计数器连续N帧确认存在违规才推送告警。# 伪代码安全帽违规报警逻辑 frame_count 0 warn_count 0 while True: frame capture_next_frame() # 每5秒抽一帧 dets model(frame) # 目标检测 hardhat_off [d for d in dets if d.cls 3] # No-Hardhat persons [d for d in dets if d.cls 6] # Person # 核心规则违规框和人员框位置匹配才算数 for h in hardhat_off: if has_overlap(h, persons, iou_thresh0.3): warn_count 1 break if warn_count 3: # 连续3次抽查都发现违规 send_alert(工人未佩戴安全帽) warn_count 0 if frame_count 10: # 一段时间后重置计数避免重复报警 warn_count 0这段伪代码里最值得注意是has_overlap这一步。前面花了很长的篇幅说Hardhat和Person标签语义高度重叠那么在推理阶段No-Hardhat框如果没有和Person框重叠大概率是误检不应该进入报警计数。另外No-Hardhat和Hardhat同时出现在同一位置时按置信度取高者这个规则能过滤掉相当一部分模型自身的不稳定输出。工地安全监控这个场景模型的mAP只要够用就行真正决定产品体验的是后处理规则能不能把误报率压下去。从那以后我每次拿到一个新的目标检测数据集都会强制先跑一遍标签体检脚本把越界坐标、缺失标签、类别分布打印出来贴到项目文档里。这个习惯救过我很多次希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑