简介:面向目标检测与深度学习实战人群,这份安全背心识别数据集提供YOLO与VOC格式的标注数据,覆盖 vest、no-vest 两个类别,共4185张图片,适用于工地安全监控、人员防护穿戴检测等场景。图片与txt标签已划分为训练集、验证集和测试集,并附带指定类别信息的yaml配置文件,可直接用于YOLOv5至YOLOv10、Faster RCNN、SSD等主流模型训练,省去自行采集、清洗和标注的时间成本。资源包共2000个文件,以txt标注文件为主,另有1个yaml配置文件,整体约254.18MB;txt中保存YOLO格式的类别与坐标信息,yaml声明类别名称及数据集路径,结构清晰,拿到后替换数据路径即可开展训练与验证。该数据集两类样本覆盖穿戴与未穿戴背心状态,可用于训练二分类检测器、评估模型精度,也适合初学者对比不同YOLO系列模型的效果。已有242人学习下载,对于需要安全背心专用数据来快速验证算法的开发者和研究人员,是一份即拿即用的高质量资源。
1. 安全背心识别数据集为什么值得自己跑一遍
施工现场的 PPE(个人防护装备)检测是目标检测落地最密集的场景之一,但公开数据集里专门针对安全背心的并不多。这个数据集一共 4185 张图片,标注了 vest 和 no-vest 两个类别,同时提供 YOLO 和 VOC 两种格式的标签,并已经按训练集、验证集、测试集划分好,拿过来就能直接喂给 YOLOv5 到 YOLOv10 系列做训练。对于做施工安全、智慧工地、行为合规检测的团队来说,省去了自己采集视频抽帧、人工标注、格式转换这几步最耗时的工作。
数据集的文件命名保留了 Roboflow 导出的特征,每个 txt 文件名后缀附带一段哈希值,这是标注平台导出时的正常现象,不影响训练。图片对应的人物姿态覆盖了站立、弯腰、走动、多人同框、不同光照和遮挡情况,用于评估模型在真实工地环境下的泛化能力是够用的。下面按使用顺序拆解数据集的完整流程:从格式转换到目录组织,再到 YOLO 系列的训练和验证。
2. 标签格式解析:YOLO 与 VOC 的结构差异和数据校验
2.1 解压后的目录结构
拿到压缩包后先解压,正常情况下会看到 images 和 labels 两个目录。labels 下同时存有 txt 和 xml 两种格式的标注文件,txt 对应 YOLO 格式,xml 对应 VOC 格式。一个典型的目录结构如下:
safety_vest_dataset/ ├── images/ │ ├── train/ │ ├── validation/ │ └── test/ ├── labels/ │ ├── train/ │ ├── validation/ │ └── test/ ├── data.yaml └── README.txt其中 images 里放的是 jpg 图片,labels 里每个图片名对应一个.txt(YOLO 格式)和一个.xml(VOC 格式)。这种双格式的组织方式是为了适配不同训练框架:YOLO 系列直接用 txt,Faster R-CNN 和 SSD 通过脚本读取 xml 后转成 COCO 或 PASCAL VOC 格式。
2.2 YOLO 标签的字段含义
随便打开一个 txt 文件,每一行代表一个目标框:
0 0.451562 0.502685 0.084375 0.158570 1 0.683203 0.548513 0.062891 0.110987每行由五个字段组成,依次含义为:
class_id:类别编号。0 代表 vest,1 代表 no-vest,对应 data.yaml 中定义的类别顺序x_center:目标框中心点的 x 坐标,已归一化到 0~1,值为绝对像素坐标除以图片宽度y_center:目标框中心点的 y 坐标,已归一化到 0~1,值为绝对像素坐标除以图片高度width:目标框宽度,除以图片宽度后的归一化值height:目标框高度,除以图片高度后的归一化值
注意,YOLO 格式存的是相对坐标,不是绝对坐标。如果自己写脚本做数据增强或裁剪,归一化坐标必须同步变换,否则标签会错位。
2.3 校验标签是否有越界和类别错误
拿到数据集第一步不要急着训练,先跑一个检查脚本确认标签质量。常见问题包括:坐标值落在 0~1 之外、类别 id 与 data.yaml 中的类别数量不匹配、txt 中行的数量与图片中实际目标数不符。一个实用的校验脚本如下:
import os label_dir = 'labels/train' class_names = ['vest', 'no-vest'] for filename in os.listdir(label_dir): if not filename.endswith('.txt'): continue filepath = os.path.join(label_dir, filename) with open(filepath, 'r') as f: lines = f.readlines() for idx, line in enumerate(lines): parts = line.strip().split() if len(parts) != 5: print(f'格式错误: {filename} 第{idx+1}行') continue class_id, x_center, y_center, width, height = parts if int(class_id) >= len(class_names): print(f'类别越界: {filename} 第{idx+1}行') for coord in [x_center, y_center, width, height]: if not (0.0 <= float(coord) <= 1.0): print(f'坐标越界: {filename} 第{idx+1}行')这个脚本会逐行读取标签文件,检查字段数量、类别 id 和坐标范围。坐标必须全部在 0~1 这个区间内,width 和 height 出现 0 值说明标注框退化成了点,这类样本建议直接删除,否则训练时会出现 loss 异常波动。
2.4 data.yaml 配置说明
数据集的 yaml 文件是训练入口,内容大致如下:
train: images/train val: images/validation test: images/test nc: 2 names: ['vest', 'no-vest']train/val/test:分别对应图片目录的路径,建议在训练脚本中使用绝对路径,避免相对路径切换工作目录时报 FileNotFoundErrornc:类别数量,这个数据集固定为 2names:类别名称列表,顺序必须与标签文件里的 class_id 一一对应。顺序乱了,训练出来的模型在推理时就会把 vest 当成 no-vest
2.5 下载数据集中常见的问题
这个数据集是从 Roboflow 导出的,经常有人问数据集中的 train 与 validation 分布是否合理,部分数据的验证集与测试集数量偏少。建议在训练前统计一下不同集合的图片数量,如果测试集少于 200 张,可以考虑从训练集中抽样补充,或者直接只用 train 和 validation 做训练,test 留作最终评估。
3. 目录重组与图像尺寸统一:训练前的数据准备工作
3.1 图片格式与尺寸归一化
这个数据集的图片原始尺寸来自工地监控或移动设备,长宽比并不一致。YOLO 系列模型在训练时会将输入缩放到固定尺寸(如 640x640),但这里存在一个细节:标签是按原图尺寸归一化的,缩放后标签是否依然正确,取决于缩放策略。YOLO 默认的 letterbox 填充方式是在保持宽高比的前提下补灰边,因此归一化坐标依然有效。
推荐在训练前统一图片格式为 jpg,并检查是否有损坏的图片文件。一个快速检查方法:
python -c " from PIL import Image import os for root, dirs, files in os.walk('images'): for f in files: if f.endswith('.jpg'): try: Image.open(os.path.join(root, f)).verify() except Exception as e: print(f'损坏文件: {os.path.join(root, f)} - {e}') "该脚本使用 Pillow 的 verify 方法检查图片完整性,不做像素级解码,速度很快。导出过程中如源文件有中断,verify 会直接抛异常,提前发现这类问题比训练中途报错要容易处理得多。
3.2 训练集与验证集的重组策略
原数据集已经划分好了 train / validation / test,但如果想调整数据分布,就需要重新合并再划分。一个稳妥的做法是先把所有图片和标签分别复制到统一目录,然后按比例重新拆成训练集和验证集:
mkdir -p all_images all_labels find images -name '*.jpg' -exec cp {} all_images/ \; find labels -name '*.txt' -exec cp {} all_labels/ \;复制完成后用 Python 脚本做 8:2 划分:
import os import random import shutil random.seed(42) all_images = os.listdir('all_images') random.shuffle(all_images) train_ratio = 0.8 train_count = int(len(all_images) * train_ratio) os.makedirs('images/train', exist_ok=True) os.makedirs('images/val', exist_ok=True) os.makedirs('labels/train', exist_ok=True) os.makedirs('labels/val', exist_ok=True) for i, img_name in enumerate(all_images): src_img = os.path.join('all_images', img_name) src_label = os.path.join('all_labels', img_name.replace('.jpg', '.txt')) if i < train_count: shutil.copy(src_img, 'images/train/') if os.path.exists(src_label): shutil.copy(src_label, 'labels/train/') else: shutil.copy(src_img, 'images/val/') if os.path.exists(src_label): shutil.copy(src_label, 'labels/val/')关键点在于 seed 固定为 42,保证每次划分的结果一致,便于后续实验对比。如果你要对比不同模型在相同数据上的表现,这个固定划分逻辑必须保留。另外,标签文件的命名必须和图片文件名完全一致,YOLO 训练脚本只认同名文件,后缀不同也会忽略对应标签。
3.3 用 Python 统计类别分布
训练前统计一下类别分布很有价值,特别是 vest 和 no-vest 两类目标数量如果差异大,训练出的模型会对多数类过拟合。统计标签中各类别出现的次数:
import os def count_classes(label_dir): counts = {'vest': 0, 'no-vest': 0} for filename in os.listdir(label_dir): if not filename.endswith('.txt'): continue with open(os.path.join(label_dir, filename), 'r') as f: for line in f: class_id = int(line.strip().split()[0]) if class_id == 0: counts['vest'] += 1 elif class_id == 1: counts['no-vest'] += 1 return counts print(count_classes('labels/train')) print(count_classes('labels/val'))如果两个类别数量相差超过 2 倍,建议在训练时给少数类分配更大的 loss 权重,或者使用 mosaic 增强时对少数类做重复采样。YOLOv8 中可以通过配置 cls 参数来调节类别损失的权重。
4. YOLOv8 训练自己的安全背心数据集:参数调优与实践
4.1 YOLOv8 训练命令与参数
YOLOv8 是当前应用最广的 YOLO 系列版本,官方仓库对自定义数据集的支持很完善。安装依赖后,在项目根目录执行:
yolo detect train \ data=/path/to/safety_vest_dataset/data.yaml \ model=yolov8s.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.01 \ augment=True \ project=/path/to/project \ name=safety_vest_exp训练过程中,日志里重点看三个指标:box_loss、cls_loss、dfl_loss,以及每轮输出的 mAP50 和 mAP50-95。如果 20 轮内 mAP50 不涨,优先检查 data.yaml 路径和图片是否能正常加载。可以跑yolo detect train data=... epochs=1快速验证,能正常跑完一轮,基本可以确认数据链路无误。
4.2 针对安全背心场景的关键参数说明
具体到安全背心这个场景:
model=yolov8s.pt:s 版本在精度和速度之间平衡较好。如果追求极致速度部署到边缘设备,可以考虑yolov8n.pt;如果对较小目标(比如远距离的背心)要求高,换成yolov8m.pt或更大的版本imgsz=640:原始图片分辨率如果普遍低于 640,训练时会被放大,性能影响不明显;如果原始图片超过 1280,可以先适当压缩再训练,避免显存溢出batch:这个参数取决于 GPU 显存。12GB 显存建议 16,24GB 显存可以到 32。出现 OutOfMemory 时先调小 batch,而不是降低图片尺寸lr0:初始学习率 0.01 是 YOLOv8 的默认值,如果你用的是 COCO 预训练权重,这个值合适;如果从零开始训练,建议降低到 0.005
4.3 在训练中嵌入数据增强策略
YOLOv8 默认开启了 mosaic、hsv 变换、随机翻转等增强策略。在安全背心场景下,有两个增强方向值得试:
- 关闭 mosaic 后 10 轮微调:mosaic 增强会拼接 4 张图片,对中小目标训练有帮助,但在最后 10 轮关闭 mosaic 可以提升模型在小物体上的稳定性。在
ultralytics/cfg/default.yaml中设置mosaic=0.0,或者分两阶段训练 - 调整 hsv 参数应对光照变化:工地场景有强逆光、黄昏、夜间照明等复杂光照条件。把
hsv_h、hsv_s、hsv_v的默认值适当调大,可以提高模型对颜色偏移的鲁棒性。安全背心的颜色变化是通过 hsv 增强模拟出来的,这是最直接的手段
4.4 Faster R-CNN 与 SSD 的训练兼容性
这些模型需要 VOC 或 COCO 格式的标注,而本数据集每个图片同时提供了 xml 标签。以 Faster R-CNN 为例,需要用脚本将 xml 转成 tfrecord 或 coco 的 json 格式。常见做法是写一个解析函数:
import xml.etree.ElementTree as ET import json def xml_to_coco(xml_path, img_id, ann_id): tree = ET.parse(xml_path) root = tree.getroot() width = int(root.find('size/width').text) height = int(root.find('size/height').text) annotations = [] for obj in root.findall('object'): class_name = obj.find('name').text bbox = obj.find('bndbox') x_min = int(bbox.find('xmin').text) y_min = int(bbox.find('ymin').text) x_max = int(bbox.find('xmax').text) y_max = int(bbox.find('ymax').text) annotations.append({ 'id': ann_id, 'image_id': img_id, 'category_id': 0 if class_name == 'vest' else 1, 'bbox': [x_min, y_min, x_max - x_min, y_max - y_min], 'area': (x_max - x_min) * (y_max - y_min) }) ann_id += 1 return annotations, ann_idVOC 的 bbox 是绝对坐标,转换成 COCO 的 bbox 时需要把 xyxy 转成 xywh,即用 x_min、y_min 和宽高表示。转换后检查一个关键问题:如果 xml 里没有 size 字段,或 size 与图片实际尺寸不一致,需要以图片的 PIL 读取结果为准。本例数据集由 Roboflow 导出,xml 和图片尺寸通常是对应的,但对从其他来源补的数据要特别检查。
4.5 训练中常见错误与排错
训练前前后后最容易遇到两类报错:
RuntimeError: CUDA out of memory显存溢出,优先调batch到 8 或 4。如果显存还是不够,把imgsz=640改成imgsz=416,对性能影响存在但可接受。
AssertionError: Label class exceeds nc=2说明标签文件里出现了class_id大于 1 的值,可能中间有类别没有正确过滤。用 2.3 小节的脚本扫一遍 labels 目录,找到越界文件后删除或修正。不要忽略这个错误直接训练,loss 会出现 NaN。
5. 模型评估指标解读与误检分析
5.1 安全背心场景下更关注 mAP50 还是 mAP50-95
工地安全检测场景更看重 mAP50,主要是因为安全背心作为目标,实际检测时并不要求像素级精确的定位,框略有偏移并不影响判断工人是否穿戴合规。而 mAP50-95 是更严格的标准,对边界框和真实框的重合度要求更高。如果最终只做合规判断,不用迁移学习,模型不算特别复杂,mAP50 在 0.9 以上,mAP50-95 在 0.6 以上,基本就能用于现场预筛选。反之,如果后接的跟踪算法会用到目标中心点做轨迹分析,对 bbox 稳定性有要求,那就要提高 mAP50-95 的标准。
5.2 使用 Ultralytics 的验证命令评估模型
训练完成后对测试集跑评估:
yolo detect val \ model=/path/to/project/safety_vest_exp/weights/best.pt \ data=/path/to/safety_vest_dataset/data.yaml \ split=test \ batch=16这个命令输出每个类别的 precision、recall、mAP50、mAP50-95。重点看 per-class 指标,如果没有按类别拆分,即使整体 mAP 不错,也可能某个类别表现很差。安全背心数据集容易出现的问题是对 no-vest 的误检过高,即把不穿背心的人预测成了穿背心。若 no-vest 的 recall 偏低,模型对没有背心特征的检测会不够敏感,需要增加负样本或对类别损失进行加权。
5.3 错误样本可视化与根因分析
评估结果出来后,用 Ultralytics 提供的混淆矩阵和结果曲线分析错误模式。更直接的方法是导出推理结果的 txt 文件,再用脚本定位所有误检样本:
yolo detect predict \ model=/path/to/best.pt \ source=/path/to/test/images \ save_txt=True \ conf=0.25打开runs/detect/predict/labels/下生成的 txt,对比原标签,找出哪些图被模型漏检或误检。常见原因集中在三点:目标过小(如在 640 分辨率下背心宽度小于 20 像素)、遮挡严重(两人并排时只有半个背心露出)、以及背心颜色与背景接近导致的对比度不足。针对性扩容这些场景的样本,比盲目调参有效得多。
6. 模型导出与部署推理时需要注意的边界情况
训练完成后,直接导出 TorchScript 和 ONNX 格式用于部署:
yolo export \ model=/path/to/best.pt \ format=onnx \ imgsz=640 \ dynamic=Truedynamic=True:允许推理时输入不同尺寸的图片。监控视频流的画面分辨率通常是固定的,设置成动态的好处是中途切换分辨率时不需要重新导出模型- 导出前用验证集跑一遍
yolo detect val,对比导出前后 mAP 是否有明显下降。精度下降超过 1 个点时要检查是否因为某些算子在导出时被替换成了精度较低的版本
推理时要保留 letterbox 的预处理逻辑:
import cv2 import numpy as np from ultralytics import YOLO model = YOLO('/path/to/best.pt') def letterbox(img, new_shape=(640, 640)): shape = img.shape[:2] r = min(new_shape[0] / shape[0], new_shape[1] / shape[1]) new_unpad = (int(round(shape[1] * r)), int(round(shape[0] * r))) img = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR) dw = new_shape[1] - new_unpad[0] dh = new_shape[0] - new_unpad[1] top, bottom = int(round(dh * 0.5 - 0.1)), int(round(dh * 0.5 + 0.1)) left, right = int(round(dw * 0.5 - 0.1)), int(round(dw * 0.5 + 0.1)) img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(114, 114, 114)) return img frame = cv2.imread('test_person.jpg') input_img = letterbox(frame) results = model(input_img)这里的 letterbox 处理要和训练时的参数完全对齐。如果训练时未采用 letterbox 而是直接拉伸,推理时用了 letterbox,坐标映射会有偏差,所有检测框都会整体偏移。判断是否对齐的方法是查看文档中对验证阶段 preprocess 的配置,或者在推理前对少量标注图片做对比测试,确认预测框位置与原标注框的重合度。预处理细节是这类数据集中最容易踩的坑,想快速排查时优先检查这一点。另外,边界框坐标还原到原图时需要减去 padding 的偏移并除以缩放系数,这个逻辑也建议专门写一个函数并配上单测,防止不同模型格式之间相互倒腾时出错。
本文还有配套的精品资源,点击获取