ARTICLE DETAIL

资讯详情

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

安全背心识别数据集构建与YOLOv8训练全流程指南

安全背心识别数据集构建与YOLOv8训练全流程指南 简介这是一份面向目标检测与安全作业场景的安全背心识别数据集适合使用YOLO系列、Faster RCNN、SSD等模型的开发者与研究者。数据集包含vest与no-vest两个类别共4185张图片并已按训练集、验证集、测试集划分配套txt标签、xml标签及指定类别信息的yaml文件可直接用于YOLOv5至YOLOv10等主流算法训练。包体共2000个文件以txt标签文件为主1999个另含1个yaml配置文件压缩包大小254.18MB文件命名清晰便于按图片对应检索标签。目前已有244人学习适合需要快速获取合规标注数据、开展安全着装检测或施工区域人员监管项目的研究者。数据集中已包含完整的标签映射与目录划分无需额外预处理即可投入模型训练能有效节省数据清洗与格式转换时间。1. 安全背心识别数据集工地场景里最先被低估的那个坑在工地安全帽、反光背心这类PPE检测需求里最常翻车的不是模型而是数据集。我见过好几个团队直接拿公开的行人数据集来凑“安全背心识别数据集”模型在通用场景跑得挺好一到工地现场就大面积漏检——因为安全背心的视觉特征根本不是“人”而是荧光色块和反光条。这个标题的核心任务是把一套能用于目标检测训练的安全背心识别数据集从采集、标注、格式转换到落地训练的全流程讲清楚。它适合要做工地安全监管、工厂PPE合规检测的算法工程师也适合拿YOLO系列做目标检测项目的学生。顺着这个方向做完你会发现模型效果的上限其实在数据阶段就决定了。2. 安全背心识别数据集的样本构成与采集原则先想清楚再动手2.1 安全背心和普通行人检测的差异类别定义是第一步安全背心识别不能借用行人检测的思路。行人检测的框是“整个人”安全背心检测的框是“躯干区域”。这个差异决定了标注边界你框的是背心覆盖区域而不是整个人。如果直接拿行人框来训练模型学到的特征会偏向头肩比例和人体轮廓而不是荧光色和反光条到了现场自然认不出穿没穿。所以我一般建议把标签定义成两类这是当前做安全背心识别数据集最常见的做法。第一类是“穿了背心”第二类是“没穿背心”。最多再加一个“穿了但被遮挡”的中间类但中间类在模型推理阶段很难跟第一类区分实际工程里两类最不容易翻车。注意正负样本的定义必须统一标注“穿背心”时要求背心覆盖躯干超过50%否则一律按“没穿”算。这个阈值要写进标注规范文档不然两个标注员的标准会完全不同数据质量直接失控。2.2 样本规模与场景覆盖多少张算够用目标检测训练自己的数据集起步建议是每类不少于2000个实例。以安全背心识别数据集为例就是正样本“穿了背心”的矩形框不少于2000个负样本“没穿”的框不少于2000个。这里说的是实例数不是图片数。一张图里可能有三个人其中两个穿了那就贡献两个正例和一个负例。光有数量不够场景覆盖才是决定工地现场是否翻车的关键。常见的坑是只用白天清晰照片训练。真实工地里有夜间、逆光、雨天、扬尘、背心被工具袋遮住、工人蹲着、背对镜头这些情况。我一般按下面的比例做场景预算场景占比说明白天正常光照40%基础场景保证模型下限逆光/阴影20%背光下荧光色会变暗特征衰减明显夜间/低光照15%反光条在暗光下的纹理是核心特征遮挡/姿态异常15%背心被部分遮挡、工人蹲姿或背对镜头远景小目标10%人在画面中占比小于5%的情况按这个比例采集训练出来的模型在实测时不容易突然拉胯。对于目标检测的数据集处理来说场景多样性比图片总量更值钱。2.3 采集与清洗ffmpeg 抽帧和人工筛图最常见的采集来源是工地监控视频。监控视频一天拍下来几万帧不可能全部标注。用ffmpeg按固定间隔抽帧是效率最高的起步方式ffmpeg -i input.mp4 -vf fps2,scale1280:720 -q:v 2 frame_%04d.jpg这个命令把视频按每秒2帧抽出来统一缩放到1280x720jpg质量设成2数值越小质量越高。为什么用fps2而不是直接全部帧保留因为监控里工人走动速度不快每秒2帧能保证同一个人的姿态有变化但不会出现大量重复帧。抽取之后必须人工快速过一遍删掉模糊、过曝、画面遮挡超过一半的图。这一步是玄学现场但值得做——脏样本混进训练集后面调参再久也救不回来。清洗完的图片按场景建目录day、night、backlight、occlusion、far。目录名将来写进数据集的元信息里用于跑完评估后定位模型在哪个场景下短板最明显。安全背心识别数据集的采集阶段到此结束下面是标注环节。3. 用 labelimg 标注一套安全背心数据集边界框规范与质量检查3.1 标注工具选型为什么是 labelimg目标检测常用标注工具里labelimg 适合做矩形框的VOC和YOLO格式标注单机可用不需要部署标注平台。如果你有团队协作需求可以用商用的标注平台但一个人或小团队起步labelimg 是最省事的选择。安装时注意Python版本labelimg 对 PyQt5 的依赖在 Python 3.9 以上有已知兼容问题。稳妥的组合是 Python 3.8 加 PyQt5 5.15或者直接用官方打包好的 release 版本。启动后先设置自动保存模式再选择PascalVOC或YOLO格式输出。建议选PascalVOC格式存储中间结果后面再用脚本做格式转换这样留了后悔药万一标注规范要改改xml比改txt方便得多。3.2 标注规范什么算“穿”什么算“没穿”标注界定的细节决定数据质量。我先定义一个写进团队文档的规范供参考正样本反光背心覆盖躯干面积超过50%的工人。框取背心实际覆盖的矩形区域不包含头和腿。负样本画面中的工人躯干清晰可见且没有穿反光背心。框取躯干区域。不标注的情况人物小于40x40像素、背心被完全遮挡且无法推断、多个人紧贴导致边界不清。宁可漏标也不标歪。这个规范的核心是“框背心而不是框人”。很多标注员习惯性框全身这样训练出来的模型框会上下漂移推理时框住脸或者腰带。还有一类难例是工人把背心系在腰间或搭在肩上按规范这两个算“没穿”——因为现场监管要的是“正确穿着”不是“带了背心”。3.3 标注质量检查GT 可视化脚本标注完几百张后不要直接训练先做一次可视化检查。用OpenCV把标签框画回原图人工快速拉一遍import cv2 import os # 标签格式: class_id cx cy w h (归一化坐标) def draw_yolo_boxes(img_path, txt_path, class_names): img cv2.imread(img_path) h, w img.shape[:2] with open(txt_path, r) as f: lines f.readlines() for line in lines: parts line.strip().split() cls int(parts[0]) cx, cy, bw, bh map(float, parts[1:]) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, class_names[cls], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) return img # 用法示例 class_names [visitor_vest, no_vest] img draw_yolo_boxes(frame_0012.jpg, frame_0012.txt, class_names) cv2.imwrite(check_frame_0012.jpg, img)这段逻辑很简单但特别管用把归一化坐标换算回像素坐标画框写类别。看图时确认两件事框是不是包住背心区域而不是整个人以及负样本框是不是标在躯干上。框错了不用改代码直接用labelimg修正后覆盖txt文件。可视化检查是安全背心识别数据集构建里最容易被跳过的步骤但跳过的人后面基本都回来补了一遍。4. 把标注结果转成 YOLO 格式VOC、COCO、YOLO 坐标体系与转换脚本4.1 三种标注格式的坐标差异labelimg 默认可以存成 VOC 的 xml 或 YOLO 的 txt。如果你用其他工具或平台拿到了 COCO 格式的 json 标注到了训练阶段就必须处理格式差异。三种格式的核心区别在坐标表示格式坐标形式说明VOCxmin, ymin, xmax, ymax绝对像素坐标左上角为原点COCOx, y, width, height绝对像素坐标x, y 是左上角YOLOcx, cy, width, height归一化到 0~1中心点加宽高YOLO格式在多尺度训练时最方便因为归一化坐标不依赖具体分辨率。这也是为什么yolov8训练自己的数据集时官方推荐直接使用YOLO txt格式。如果你拿到的是VOC xml需要先转一次这也是很多做目标检测数据集处理的同学第一道坎。4.2 转换脚本xml 转 txt 的可靠实现import os import xml.etree.ElementTree as ET from pathlib import Path def xml_to_yolo(xml_path, class_map, out_dir): tree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) txt_name Path(xml_path).stem .txt lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_map: continue bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) cx (xmin xmax) / 2 / img_w cy (ymin ymax) / 2 / img_h bw (xmax - xmin) / img_w bh (ymax - ymin) / img_h lines.append(f{class_map[name]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) with open(os.path.join(out_dir, txt_name), w) as f: f.write(\n.join(lines)) # 类别映射顺序要和yaml配置保持一致 class_map {visitor_vest: 0, no_vest: 1} xml_to_yolo(annotations/frame_0012.xml, class_map, labels)这个脚本的核心是把左上右下坐标换算成中心点宽高再除以图片宽高做归一化。这里有三个边界坑一是xml里坐标如果本来是整数读取时也要转float否则除出来的结果永远是0。二是size节点读错位置VOC xml里size在annotation节点下不在object节点下新手经常找错层级。三是同一个xml里出现未定义类别脚本用continue跳过保证不因为一个脏标签导致整个文件作废。4.3 训练前的数据划分与配置转完格式后把图片和txt放在同一目录结构下按yolov8训练自己的数据集的惯例组织dataset/ images/ train/ val/ labels/ train/ val/划分时不要把同一个场景的视频帧全放训练集、另一段视频帧全放验证集。正确做法是按场景分层抽样白天、夜间、逆光各按比例抽20%进val。否则验证集和训练集分布不一致训练曲线看着好实测一测就露馅。比例上train和val按8:2或9:1都可以目标检测小数据集推荐8:2留够验证样本。到这一步安全背心识别数据集已经可以扔给模型训练了。5. yolov8 训练安全背心数据集参数设置与避坑记录5.1 必调参数从预训练权重到学习率衰减yolov8 是当前处理自己的目标检测数据集最常用的框架训练命令不长但参数不能照搬默认yolo detect train \ datasafety_vest.yaml \ modelyolov8n.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ mosaic1.0 \ patience30逐个参数说。data指向yaml配置文件里面写train和val路径、类别数、类别名。model用yolov8n.pt起步n是nano图片尺寸640时速度最快先跑通再往yolov8s换。imgsz640是速度和精度的平衡点但安全背心的反光条是细长结构如果小目标多可以试960。batch16在8G显存内能跑如果爆显存改成8。lr00.01是YOLO系列的默认初始学习率loss不降时调到0.001。mosaic1.0是数据增强策略等于开启拼接四张图的策略对小数据集提升很大但最后20个epoch建议关掉让模型在真实分布上收敛。yaml文件示例path: dataset train: images/train val: images/val nc: 2 names: [visitor_vest, no_vest]训练过程盯两个指标train/loss 和 val/box_loss。如果train loss降但val loss不降是过拟合先把epoch从150减到100或者加强mosaic。如果两边都不降先查数据集txt里归一化坐标有没有大于1的异常值。跑一轮下来你对这套安全背心识别数据集的底子如何就有数了。5.2 安全背心识别数据集落地过程中的5条高频踩坑记录记录1验证集mAP很高现场视频里全漏检。 现象模型在测试集上mAP达到0.9但现场夜间画面里背心一个都检不出来。 原因训练集里夜间样本太少模型根本没有见过暗光下的反光条纹理。 解决回到采集阶段补充夜间数据按2.2节说的15%低光照预算执行重训后夜间召回率从0.2提到0.85。记录2背心框上下漂移框到脸和腰带。 现象检测框有时在头部有时在下半身不稳定。 原因标注时有人用“整个人”框有人用“背心区域”框标签不统一。 解决把3.2节的标注规范重新同步给标注员对已有的标注全部按“背心覆盖躯干”标准复查框不准的重新标。记录3工人转身后漏检。 现象正面检测正常背面大面积漏检。 原因安全背心正面荧光面积大背面反光条少数据里背面样本占比太低。 解决采集时专门补拍背面和侧面的工人把正背比例调到接近1比1。记录4误把穿橙色工服的人识别成穿了背心。 现象橙色工服误报为visitor_vest误报率高于预期。 原因背心的荧光黄绿和橙色工服在色相上接近模型学的是颜色而不是反光条结构。 解决增加难负样本把不穿背心的橙色、黄色工服工人单独抽一批图加入训练集必要时把验证集里这类误报图加入训练集当作hard negative。记录5训练中途loss出现NaN。 现象训练到第40轮loss变成nan曲线断掉。 原因学习率设太高或者标签文件里有宽高为0的框归一化时除出0。 解决先跑一段脚本检查所有txt过滤掉bw或bh小于0.001的无效标注行再把lr0调低到0.005重启训练。6. 用混淆矩阵和错误样本反向优化你的安全背心数据集数据集训完工作只算完成一半。真正让安全背心识别数据集越用越好用的是用评估结果反推数据短板。yolov8训练输出目录下有个confusion_matrix.png这张图是优化数据集的第一手资料。重点看两个格子visitor_vest误判为no_vest的比例以及背景被误判为visitor_vest的比例。前者说明正样本的视觉特征不充分后者说明难负样本不够。我习惯的做法是跑一轮验证把val集里所有预测错误的图单独挑出来按错误类型存目录yolo val modelruns/detect/train/weights/best.pt \ datasafety_vest.yaml \ save_jsonTrue \ conf0.25 \ iou0.45val跑完会生成predictions.json里面有每张图的预测框、类别和置信度。拿它和GT比对把“GT有但预测无”和“GT无但预测有”两类图分别复制出来人工看一遍。这一步看的是数据集的抽样盲区如果连续十张错误样本都是远景小目标那就是2.2节比例分配里far类占比不够如果都是背心系在腰间的样本那就是3.2节标注规范没有覆盖“错误穿法”。补数据不需要全部重标。把错误样本按场景归类后直接从原始监控视频里按对应场景补抽500到1000帧只标注错误相关的类别合并进训练集重新训练一轮。通常一轮这样的闭环优化能比盲目加数据提升3到5个点的mAP。这个习惯我保持了很长时间每次训练完先不看测试集分数先看错误图。数据集的质量不是标注越久越高而是越改越高。这比换更大的模型权重来得实在希望帮到你。本文还有配套的精品资源点击获取
返回列表