ARTICLE DETAIL

资讯详情

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

智慧工地数据集实战:从YOLOv8训练到安全帽反光衣检测

智慧工地数据集实战:从YOLOv8训练到安全帽反光衣检测 简介面向智慧工地监控场景的视觉检测数据集适用于反光衣穿戴、安全帽佩戴与行人检测等任务可直接用于主流目标检测算法的训练与验证。资源包共2000个文件压缩包约585.74MB主要包含YOLO格式标签、VOC格式标签、工地实拍图像等并附完整图片下载链接所有标签均由LabelImg工具手工标注背景覆盖多视角、多场景光照与遮挡情况贴近真实环境。数据集覆盖3065张真实工地监控样本已经实际项目验证算法拟合效果良好可显著减少数据清洗与标注成本双格式标签也便于在不同训练框架间迁移使用。目前已有1436人学习下载适合需要高质量安全帽佩戴与反光衣穿戴检测数据的工程师与研究人员直接使用无论是快速验证算法还是落地部署均有实用价值。1. 智慧工地数据集到手先看这两样标签格式和拍摄场景做智慧工地项目最难受的不是算法选型而是数据。你部署到工地现场的摄像头视角是斜的、逆光的、扬尘的跟网上下载的公开数据集完全是两个世界。这套“智慧工地数据集3065张反光衣安全帽行人检测数据集”我拆过一遍先说结论它是真实工地监控抓拍不是摆拍场景包含多视角和多背景对落地项目很有参考性。它同时给出 VOC 和 YOLO 两种标签这意味着你不用为格式转换折腾太久YOLO 系列、SSD、CenterNet、PP-YOLO、YOLOX、PP-PicoDet 都能直接拿来训练。适合谁准备做安全帽佩戴检测、反光衣穿戴检测、人员入侵告警的工程师也适合刚入门想拿真实数据练手的学生。接下来我会把它怎么组织、怎么用于训练、有哪些坑一条条讲清楚。2. 把数据集拆开看VOC和YOLO标签的目录结构、格式差异与一致性校验2.1 数据集目录长什么样images、xml、txt 怎么对应拿到压缩包后解压出来的目录不是千篇一律的images和labels两个文件夹而是像safety_vest1754.txt、safety_vest1793.txt这样的文件直接散落在某个目录下。这是很多标注工具导出时的习惯图片在JPEGImages或images目录与图片同名的.xml在Annotations.txt在labels。但是这套数据集的压缩包里因为上传限制只带了部分图片你需要先看清目录结构再把图片和标签文件建立对应的映射关系。常见做法是先把所有.jpg文件放进images目录把对应的.xml放进Annotations把.txt放进labels。需要注意的是图片文件名和标签文件名必须完全一致不含扩展名否则后续训练时 YOLO 会直接跳过所有找不齐配对的文件。我一般写一个 Python 脚本跑一遍把缺失对应关系的文件揪出来。import os from pathlib import Path img_dir Path(images) # 图片目录 xml_dir Path(Annotations) # VOC xml 目录 txt_dir Path(labels) # YOLO txt 目录 img_files {p.stem: p for p in img_dir.glob(*.jpg)} xml_files {p.stem: p for p in xml_dir.glob(*.xml)} txt_files {p.stem: p for p in txt_dir.glob(*.txt)} # 校验图片和标签是否一一对应 missing_xml [k for k in img_files if k not in xml_files] missing_txt [k for k in img_files if k not in txt_files] print(缺 xml:, missing_xml) print(缺 txt:, missing_txt)先跑一遍这个脚本再开始训练。缺标签的文件要么删除要么单独挑出来手工补标否则训练时类别数看起来齐全实际参与训练的样本少了一大截。2.2 VOC 的 xml 到底记了什么从object到bndboxVOC 格式的 xml 是手动标注工具 LabelImg 输出的标准结构。每个 xml 文件描述一张图片的宽度、高度、通道数以及图片里出现的每个目标。核心在object节点annotation folderimages/folder filenamesafety_vest1754.jpg/filename size width1920/width height1080/height depth3/depth /size object namesafety_vest/name bndbox xmin734/xmin ymin286/ymin xmax929/xmax ymax612/ymax /bndbox /object /annotationname是类别名从摘要信息来看这套数据集包含反光衣safety_vest、安全帽helmet、行人person这几个类别但具体类别名需要打开一个 xml 确认。bndbox是边界框的左上角和右下角像素坐标。这里要注意VOC 的坐标是绝对值、从 0 开始YOLO 的格式是归一化后的相对值两者转换时经常会有人把xmax当成宽度直接算结果框全部偏移。2.3 YOLO 的 txt 边界框归一化坐标转换与一致性校验脚本YOLO 格式每一行代表一个目标结构是class_id x_center y_center width height前四个值都除以图片宽高归一化到 01。比如上面那个框转成 YOLO 格式后大概是class_id 0.433 0.416 0.102 0.302。手工写转换脚本容易出错我习惯直接对每一张图片做反向校验读 txt 里的坐标乘回图片宽高再算 IoU 或直接对比是否落在 xml 的框内。import cv2 import numpy as np def voc_xml_to_yolo_txt(xml_path, img_path, txt_path, class_map): with open(xml_path, r, encodingutf-8) as f: xml_content f.read() import xml.etree.ElementTree as ET root ET.fromstring(xml_content) img cv2.imread(img_path) h, w img.shape[:2] lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_map: print(f未知类别 {name} in {xml_path}) continue class_id class_map[name] bnd obj.find(bndbox) xmin float(bnd.find(xmin).text) ymin float(bnd.find(ymin).text) xmax float(bnd.find(xmax).text) ymax float(bnd.find(ymax).text) x_center (xmin xmax) / 2 / w y_center (ymin ymax) / 2 / h width (xmax - xmin) / w height (ymax - ymin) / h lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) with open(txt_path, w) as f: f.write(\n.join(lines))这段脚本会读取 xml用 OpenCV 拿到真实图片宽高再算归一化坐标。注意class_map里类别顺序YOLO 训练时的类别顺序必须和这个 map 完全一致否则训练时类别就乱了。这也是很多人用现成 VOC 转 YOLO 工具后训练 Loss 不下降的原因之一——类别 id 对不上。3. 用这个数据集跑通 YOLOv8从数据集配置文件到训练命令3.1 先按 YOLO 标准把数据集目录重新组织一遍虽然压缩包里已经给了 YOLO 格式的 txt但直接用散落的文件训练还是容易出问题。Ultralytics YOLOv8 默认的目录结构是images/train、images/val、labels/train、labels/val。我一般把 3065 张图按 8:2 划分先创建目录再用shutil拷贝文件。注意这里不推荐直接把原图移动走因为压缩包里可能还有部分图片在别处拷贝出来训练原始文件留着备用。mkdir -p dataset/images/train dataset/images/val dataset/labels/train dataset/labels/val然后用脚本按随机种子划分。为了让每次实验可复现我固定random.seed(42)。划分完成后检查一下每个类别的样本数量是否均匀。智慧工地场景里未戴安全帽的样本通常远少于戴了安全帽的如果验证集里全是戴帽子的训练结果会虚高。3.2 修改数据集 yaml类别、路径、train/val 划分YOLOv8 通过 yaml 文件告诉模型数据在哪、类别有几个。这个文件必须放到一个固定的位置我会把绝对路径写进去避免训练时工作目录切换导致路径失效。# smart_construction.yaml path: /home/yourname/smart_construction_dataset # 数据集根目录 train: images/train val: images/val nc: 3 names: [helmet, safety_vest, person]注意names的顺序决定了训练输出的类别 id。如果你拿到的 txt 里类别 id 顺序不是这个比如反光衣是 0安全帽是 1一定要先打开几个 txt 看一下再按实际顺序改。不要迷信摘要里写的“类别齐全”以代码跑出来的类别分布为准。有一种情况是 txt 里存在class_id超出nc-1这类标签会直接报错需要提前过滤。3.3 训练命令与关键参数imgsz、batch、epochs 的现场调法数据集准备好后直接运行 YOLOv8 训练命令。这套数据集是 1080P 工地监控画面我建议先以 640 输入尺寸跑通流程后面再试 1280 看小目标收益。yolo detect train \ modelyolov8n.pt \ datasmart_construction.yaml \ imgsz640 \ epochs100 \ batch16 \ device0 \ workers4 \ projectruns/smart_construction \ nameyolov8n_640这里modelyolov8n.pt是预训练权重不是随意选的。第一次跑用 n 模型最快目的是确认数据链路没问题、Loss 能正常下降。batch16在 1080Ti 或 V100 上跑得动显存不够就降到 8。workers4是 CPU 读图线程数工地监控图片分辨率高CPU 瓶颈明显跑满后可以再调高。训练时盯着终端里的box_loss、cls_loss和mAP50前几轮如果cls_loss一直横着不降多半是标签类别映射错了停掉改 yaml。4. 踩坑记录反光衣数据集在训练和部署中的五个典型翻车现场4.1 训练 Loss 正常但 mAP 上不去检查标签类别是否对错现象训练完 mAP50 只有 0.2 左右但 Loss 曲线看起来正常损失值一直在降。原因txt 里的 class_id 跟实际类别不一致比如反光衣 id 是 0但 yaml 里配的 0 代表安全帽。模型一直在学错误的映射Loss 能降但验证时类别错位mAP 崩盘。解决训练前随机抽 20 个 txt写脚本把归一化坐标换算回像素画框在原图上人眼看一遍框和标签是否匹配。不要信任任何转换工具的输出必须可视化验证。4.2 白天漏掉反光衣强光下的白平衡与增广策略现象反光衣在白天强光下反光严重穿在身上变成一片亮斑检测框要么框小了要么根本检不出来。原因工地摄像头逆光或阳光直射时反光衣的高光区域过曝纹理完全丢失。用默认马赛克增强时颜色被随机扭曲反光衣的荧光色特征被削弱。解决训练时降低hsv_h、hsv_s的增强幅度尤其不要对颜色做大幅随机。反光衣的荧光黄绿是区分背景的关键颜色抖动过大会让模型去学错误特征。另外可以在数据集里补充一些过曝样本或者对图片做 gamma 校正后再训练一轮。4.3 数据集只有 3065 张却要求多视角别省验证集现象训练集和验证集随机划分但验证集 mAP 高一到现场新摄像头就露馅漏检大量人员。原因3065 张图来自多个场景但随机划分后同一场景的图片可能同时出现在训练集和验证集模型记住了场景背景而不是目标本身。现场换了个视角背景不同模型就失效。解决按摄像头视角或场景粒度划分。理想做法是确认每张图片来自哪个摄像头把视角差异最大的作为验证集。如果没办法确认至少先按时间间隔采样每隔 10 张取 2 张做验证保证同场景时序相近的图片不会同时出现在两端。4.4 百度云下载的文件包和本地文件对不上先算哈希再解压现象压缩包里只带部分图片完整图片要从百度云下。下载回来后训练时发现很多 txt 没有对应图片报错一堆。原因压缩包里的部分图片和解压后的散装文件混在一起文件名重复覆盖或者云盘下载断点续传导致文件损坏打开图片时cv2.imread返回空对象。解决解压后立即用哈希校验。对每个文件计算 MD5再跟包里的清单文件比对。如果包里没有清单就把所有 JPG 的尺寸读一遍凡是imread失败或尺寸为 0 的图片一律删掉对应的 txt 和 xml 也要删掉否则训练时会导致 batch 报错。4.5 安全帽是小目标在 1080P 下直接缩图训练会丢精度现象摄像头 1920×1080人站在 20 米外安全帽在图像里只有 20×20 像素。640 输入尺寸训练完成后小目标基本检不到。原因YOLOv8 的默认下采样倍数是 32640 输入时特征图 20×20对应原图一个格子约 96×96 像素安全帽 20 像素无法激活足够的特征。解决先尝试imgsz1280训练。如果显存不够就采用切图策略把原图切成 4 个 960×960 的区域分别检测最后合并框。还有一种思路是单独训练一个专门检测安全帽的模型输入尺寸设 640但 anchor-free 的模型对绝对尺寸敏感改输入尺寸后要重新调imgsz。5. 模型评估和告警逻辑把 mAP 转成工地现场能用的报警5.1 用混淆矩阵看安全帽和反光衣到底谁在漏检训练结束后不要只看 mAP50 一个数。YOLOv8 会输出confusion_matrix.png和results.csv。混淆矩阵里能清楚看到每个类别之间的混淆情况helmet被预测成person、safety_vest被预测成背景这些都是现场报警误报、漏报的根源。import pandas as pd results pd.read_csv(runs/smart_construction/yolov8n_640/results.csv) print(results.columns) # 看最后一轮的 mAP50 和 mAP50-95 print(results.iloc[-1][metrics/mAP50(B)])一般工地场景只要精确率和召回率平衡不用追求 mAP50-95 很高因为部署时通常会设一个较高的 confidence 阈值0.50.6来减少误报。我在实际项目里习惯看 F1 曲线找一个合适的 confidence 阈值让误报和漏报达到现场可接受的程度。5.2 从检测框到区域入侵设置指定的作业区域智慧工地里检测到人只是第一步更常见的是划一个临时作业区人员进入该区域但没有穿反光衣才报警。这个逻辑不能只靠检测框坐标需要把图像坐标映射到真实地面坐标。简单做法是在监控画面里用多边形划定危险区判断检测框底边中点是否落在多边形内即可。import cv2 import numpy as np def point_in_polygon(x, y, pts): n len(pts) inside False p1x, p1y pts[0] for i in range(1, n 1): p2x, p2y pts[i % n] if (y p1y) ! (y p2y) and (x (p2x - p1x) * (y - p1y) / (p2y - p1y 1e-6) p1x): inside not inside p1x, p1y p2x, p2y return inside # 假设检测框为 (x1, y1, x2, y2)取底边中点 foot_x (x1 x2) / 2 foot_y y2 region [(100, 300), (500, 320), (480, 700), (80, 650)] # 多边形顶点 if point_in_polygon(foot_x, foot_y, region): print(人员进入危险区域)注意1e-6是为了防止除零。实际工地监控画面有透视变形多边形标定时不要只在截图里画最好用现场测量点标定。另一条重要规则报警要去抖动连续 N 帧比如 5 帧都满足条件再触发否则一个行人走过去就会产生十几次误报。5.3 穿戴合规判断先检测人再匹配安全帽框安全帽检测比反光衣检测更难因为安全帽戴在头顶框非常小。现场合规判断需要结合人的检测框安全性匹配先找到person框再找helmet框只有当头盔框的底边中心点落在人框的顶部区域比如人框最上面 20% 高度内才认为戴了。直接用全局匹配极易把远处另一个人的安全帽匹配到这个人身上。def helmet_matched(person, helmet): px1, py1, px2, py2 person hx1, hy1, hx2, hy2 helmet person_top py1 0.2 * (py2 - py1) # 人的头顶区域上限 # 头盔底边中心 hx_c (hx1 hx2) / 2 hy_b hy2 if (px1 hx_c px2) and (py1 hy_b person_top): return True return False这段代码的逻辑是安全帽的底边应位于人体检测框的最上部 20% 区域。如果安全帽框在人框之外或太靠下判定为未戴帽。现场摄像头角度倾斜时这个阈值要适当放宽否则戴着帽子的工人在画面边缘会被误判成未戴。多跟几个角度做迭代最终固定参数。6. 进阶技巧用这 3065 张图做预标注再扩成自己的数据集6.1 用训练好的模型给新视频做批量预标注既然这个数据集质量可靠在它上面训练出来的模型可以直接部署到现场同时也可以用来给新摄像头录制的视频做预标注。具体做法是用yolo predict跑视频帧把输出结果转成 VOC 或 YOLO 格式再导入 LabelImg 手工校正。这样你想扩样本到 10000 张时只需要检查修改不需要从头画框。yolo detect predict \ modelruns/smart_construction/yolov8n_640/weights/best.pt \ sourcenew_video.mp4 \ save_txtTrue \ save_confTrue \ imgsz640save_txtTrue会生成与视频帧同名的 txt里面是检测到的类别和归一化坐标。把这些 txt 和抽取的原图扔回第 3 章的目录结构里用脚本把带重叠框的样本剔除剩下来的就是可用的预标注数据。注意预标注的 confidence 阈值要设低一点比如 0.3宁可多标一些假目标也不要漏掉真实目标手工删除比手工补框省时间。6.2 数据增强别盲目反光衣的颜色是特征颜色抖动要克制很多人训练时开了 YOLO 默认的增强包括hsv_h0.015、hsv_s0.7、hsv_v0.4。对常规物体这没问题但反光衣的荧光色是区分于背景的重要特征。如果色相随机偏移过大荧光绿变成灰色模型就会开始依赖纹路和形状鲁棒性反而下降。我的做法是保留空间增强平移、缩放、翻转把色相增强降到接近 0饱和度增强可以保留但要压制幅度。如果你发现模型对白色反光衣和黄色反光衣判断不稳优先调这里。6.3 导出到 ONNX 部署到 Jetson 这类边缘设备训练完成后导出成 ONNX 格式再转 TensorRT可以在不损失太多精度的前提下大幅提速。yolo export modelruns/smart_construction/yolov8n_640/weights/best.pt formatonnx imgsz640导出后先用onnxruntime在本地跑一遍确认和 PyTorch 输出一致再上 Jetson 设备做trtexec转 engine。这里有个细节导出时imgsz必须和训练时一致否则模型输出的特征图尺寸和锚框比例会变检测框全偏。另外工地现场摄像头常用 H.264 码流拉流解码时偶发丢帧输入到模型的图片如果出现黑边或撕裂会直接导致漏检。我遇到过类似问题后来在部署时强制检查每帧图像素均值低于某个阈值就丢帧不推理从那以后每次部署边缘设备都把这个边界条件写进检查清单。希望这些拆解和踩坑记录能帮你在智慧工地项目里少走弯路。本文还有配套的精品资源点击获取
返回列表