车间安全帽与背心检测数据集:YOLO/VOC标注到模型训练实战

发布时间:2026/9/28 22:26:00
车间安全帽与背心检测数据集:YOLO/VOC标注到模型训练实战
简介一份面向车间安全生产场景的目标检测数据集聚焦于识别工人、安全帽和安全背心三类目标适合使用YOLO系列、Faster RCNN、SSD等主流检测模型进行训练。数据集内含3465张图片的标注信息压缩包共2000个文件其中1999个为txt格式的YOLO标签文件另附1个yaml类别配置文件整体约357.09MB同时提供VOC格式的xml标签可在不同框架间灵活使用。标签已预先划分训练集、验证集和测试集可直接用于YOLOv5至YOLOv10等算法的训练省去手动整理标注的步骤。特别适用于工厂车间安防监控、作业规范检查、安全生产管理等场景能帮助开发者快速搭建安全帽佩戴与安全背心穿着检测系统也适合目标检测入门与项目实战。压缩包结构清晰标注规范目前已有438人学习下载是相关课题落地的实用数据基础从数据准备到模型验证均提供了高效支持。1. 车间安全穿戴检测为什么这套数据能直接上手训练做工业安全巡检的人应该都遇到过同一个问题自己从监控视频里抽帧、标注、整理数据集一套流程走下来至少一两周而且标注质量参差不齐。这次拆的这套车间工人、安全帽、安全背心识别目标检测数据集直接给了 YOLO 和 VOC 双格式标注3465 张图片、3 个类别已经划分好训练集、验证集和测试集拿到就能直接喂给 YOLOv5 到 YOLOv10 训练。对做安全生产管理系统、智慧工地、工厂视频监控报警的开发者来说省掉的不只是标注时间还有数据清洗的功夫——毕竟从文件名就能看出这些图是从真实的车间监控视频里抽帧来的背景、光照、遮挡情况都比较接近实际部署场景。适合刚接触目标检测想练手的人也适合项目工期紧、需要尽快出 baseline 的团队。2. 数据集结构与标注格式从文件命名到标签内容一次看清拿到压缩包后先别急着训练花十分钟把文件结构搞清楚后面能少踩很多坑。这套数据集是典型的 Roboflow 导出结构每个样本对应一张 JPG 图片和同名的 txt 标注文件另外还有一份 yaml 配置文件和多份 xml 标注文件。文件名看起来很长但其实信息量很大拆开看就明白了。2.1 文件命名规则与 sample 级结构先看一个典型的文件名MUELLE-4_20210720205959_20210720210300_20210721130838_mp4-167_jpg.rf.ec32a2dce38ed051eeb82eef8835f02e.txt拆解规则MUELLE-4采集点位标识说明这是 4 号车间/机位20210720205959_20210720210300视频片段的起止时间戳精确到秒20210721130838导出时间戳mp4-167源视频文件名与帧序号jpg图片格式标识rf.ec32a2dce38ed051eeb82eef8835f02eRoboflow 平台生成的样本唯一 ID这套命名规则的价值在于你能直接从文件名回溯到源视频和时间点。如果训练完发现某个类别效果特别差可以通过文件名找到对应的原始视频片段检查是不是该时段光照异常或人员密度过高导致的。目录结构通常长这样dataset/ ├── train/ │ ├── images/ │ └── labels/ ├── valid/ │ ├── images/ │ └── labels/ ├── test/ │ ├── images/ │ └── labels/ ├── data.yaml └── annotations/ └── xml/2.2 三种标注格式txt、yaml、xml 各自扮演什么角色这套数据集同时提供三种格式的标注信息看起来冗余但实际各有各的用处。**txt 文件YOLO 格式**是训练时直接读取的。每行表示一个目标格式为class_id x_center y_center width height比如0 0.521484 0.423958 0.073438 0.215625 1 0.558594 0.399306 0.056250 0.168750 2 0.715625 0.773958 0.189063 0.216146参数说明第一个数字是类别 ID0 代表 person1 代表 helmet2 代表 vest后面四个数字是归一化后的坐标值范围 0~1用像素坐标除以图片宽高得到如果想在训练前做数据检查可以写个小脚本把这些框画回图片上确认标注是否贴边yaml 文件是训练时的配置文件内容大致是train: ../train/images val: ../valid/images test: ../test/images nc: 3 names: [person, helmet, vest]这里有一个容易翻车的地方train、val、test路径如果是相对路径是基于你执行训练命令时的当前目录来解析的。如果你把数据集挪了位置或者在不同目录下启动训练路径就会失效。我一般会改成绝对路径或者用一个符号链接固定数据集位置。**xml 文件VOC 格式**是给 Faster R-CNN、SSD 这类传统两阶段/单阶段检测框架用的。每个 xml 对应一张图片包含图片尺寸、通道数和每个目标的 bounding box 坐标左上角和右下角的绝对像素值。如果主用 YOLO 路线xml 可以先放一边如果之后想对比不同框架的效果xml 能省去格式转换的时间。2.3 三个类别与数据分布特点类别只有 3 个但都是工业安全场景里最核心的检测目标类别名含义检测难点person车间工人远距离小目标、遮挡helmet安全帽与背景颜色相近、头部遮挡vest安全背心与货架/设备颜色相近、反光从标注文件的规模来看数据集的图片量3465 张不算大但胜在来源单一——同一个车间机位的多时段视频抽帧背景一致性高。这对于模型训练来说是双刃剑在相似场景下泛化效果好换一个完全不同装修风格的车间掉点可能比较明显。如果项目场景比较固定比如就是这一个车间这套数据的性价比非常高。在开始训练前建议先用脚本统计一下三个类别的目标数量分布确认没有严重的类别不平衡。如果 helmet 的目标数明显少于 person后面训练时就要考虑给 helmet 加权重或做过采样。3. YOLOv8 训练实战从数据检查到训练参数调优这套数据集在明面上就是奔着 YOLO 系列来的所以这一章直接用 YOLOv8 走一遍完整流程。选 YOLOv8 而不是 v5 或 v9 的理由很简单v8 的 API 最稳定文档全遇到问题好搜v10 虽然更新但在某些依赖环境下兼容性还有坑。3.1 训练前的数据完整性检查在正式训练前先跑一段数据完整性检查避免训练中途因为图片损坏或标签越界而中断import os from PIL import Image img_dir dataset/train/images label_dir dataset/train/labels class_names [person, helmet, vest] for img_name in os.listdir(img_dir): img_path os.path.join(img_dir, img_name) label_path os.path.join(label_dir, img_name.replace(.jpg, .txt)) # 检查图片是否完整 try: img Image.open(img_path) img.verify() except Exception as e: print(fCorrupt image: {img_path}, error: {e}) continue # 检查标签文件是否存在 if not os.path.exists(label_path): print(fMissing label: {label_path}) continue # 检查标签坐标是否越界 w, h img.size with open(label_path, r) as f: for line in f: parts line.strip().split() if len(parts) ! 5: print(fInvalid label line: {label_path}: {line}) continue cls_id int(parts[0]) x_center, y_center, box_w, box_h map(float, parts[1:]) if x_center 0 or x_center 1 or y_center 0 or y_center 1: print(fCenter out of bounds: {label_path}: {line}) if cls_id 0 or cls_id len(class_names): print(fInvalid class id: {label_path}: {cls_id}) print(Data check finished.)这段脚本做的事情是逐张检查图片能否正常打开、标签文件是否齐全、坐标是否落在 0~1 范围内。Roboflow 导出的数据集通常不会有大问题但如果有人手动改过标签这类检查能尽早发现问题。3.2 安装与训练启动创建虚拟环境并安装 YOLOv8python -m venv yolov8_env source yolov8_env/bin/activate pip install ultralytics torch torchvision安装完成后先做一次最小化训练验证流程是否通畅yolo train detect modelyolov8n.pt datadataset/data.yaml epochs5 imgsz640 batch8参数说明modelyolov8n.pt使用 yolov8n 的预训练权重初始化n 是 nano 版本参数量最小适合先验证流程epochs5先跑 5 轮确认数据路径、模型结构和损失函数都没问题imgsz640输入分辨率YOLOv8 默认就是 640如果图片本身是 720p 或 1080p直接缩到 640 会丢失一部分小目标信息后面可以试试 1280batch8批量大小根据自己的显存调整显存不够就降到 4 或 2确认流程没问题后再上正式配置yolo train detect modelyolov8s.pt datadataset/data.yaml epochs100 imgsz640 batch16 patience20 optimizerAdamW lr00.001参数逻辑从yolov8n换成yolov8s模型容量更大对这个规模的 dataset 更合适patience20验证集 mAP 连续 20 轮不提升就早停避免无效训练时间AdamW比默认的 SGD 收敛更稳尤其当数据集规模不大时AdamW 不容易震荡3.3 训练结果评估mAP 与 PR 曲线的读法训练完成后在runs/detect/train/目录下会生成results.png、confusion_matrix.png和val_batch0_pred.jpg等文件。重点关注三个指标mAP0.5IOU 阈值取 0.5 时的平均精度对框的位置要求较宽松看整体检测能力mAP0.5:0.95从 0.5 到 0.95 每隔 0.05 取一次 IOU 再求平均更严格反映框的位置精度Precision/Recall安全帽检测的应用场景更看重 recall因为漏检安全帽比误报更严重在 3465 张图片的数据量下正常训练 100 轮后 mAP0.5 应该能达到 85 以上。如果只有 70 左右先别急着调模型结构检查是不是学习率设置异常或数据划分偏差导致的。4. 从 YOLO 切到 Faster R-CNN / SSDVOC 格式数据的迁移用法之所以特别强调这套数据同时带了 xml 标注是因为很多实际项目里YOLO 不是唯一选型。比如厂区里已有的老系统是基于 Faster R-CNN 搭建的或者出于部署硬件的考虑比如某些嵌入式设备上两阶段模型跑得更稳你需要把数据切成 VOC 格式训练其他框架。这个数据集同时提供两边格式省了一道转换的工序。4.1 目录结构调整为 VOC 风格VOC 格式的标准目录长这样VOCdevkit/ ├── VOC2007/ │ ├── Annotations/ # xml 文件 │ ├── JPEGImages/ # 图片 │ ├── ImageSets/ │ │ └── Main/ │ │ ├── train.txt │ │ ├── val.txt │ │ └── test.txt对应的准备脚本import os import shutil import random src_root dataset dest_root VOCdevkit/VOC2007 os.makedirs(f{dest_root}/Annotations, exist_okTrue) os.makedirs(f{dest_root}/JPEGImages, exist_okTrue) os.makedirs(f{dest_root}/ImageSets/Main, exist_okTrue) for split in [train, valid, test]: img_dir f{src_root}/{split}/images for img_name in os.listdir(img_dir): shutil.copy(os.path.join(img_dir, img_name), f{dest_root}/JPEGImages/{img_name}) base img_name.replace(.jpg, ) xml_path f{src_root}/annotations/xml/{base}.xml if os.path.exists(xml_path): shutil.copy(xml_path, f{dest_root}/Annotations/{base}.xml) # 生成 train/val/text 的 txt 索引 for split, prefix in [(train, train), (valid, val), (test, test)]: img_dir f{src_root}/{split}/images names [f.replace(.jpg, ) for f in os.listdir(img_dir)] with open(f{dest_root}/ImageSets/Main/{prefix}.txt, w) as f: f.write(\n.join(names))这段脚本的逻辑是先把图片和 xml 分别拷入JPEGImages和Annotations再生成 ImageSets 下的索引文件。Faster R-CNN 和 SSD 的实现比如 mmdetection、detectron2、torchvision 自带的 Faster R-CNN都会读取这几个索引文件来划分训练集和测试集。4.2 torchvision Faster R-CNN 微调示例import torch import torchvision from torchvision.models.detection import fasterrcnn_resnet50_fpn from torchvision.models.detection.faster_rcnn import FastRCNNPredictor model fasterrcnn_resnet50_fpn(pretrainedTrue) num_classes 4 # 3 classes background in_features model.roi_heads.box_predictor.cls_score.in_features model.roi_heads.box_predictor FastRCNNPredictor(in_features, num_classes) # 修改预训练模型输入以适配 3 通道彩色图片 model.transform.min_size 640 model.transform.max_size 640 device torch.device(cuda if torch.cuda.is_available() else cpu) model model.to(device) # 加载数据省略 DataLoader 定义 # dataset VOCDataset(rootVOCdevkit, ...) # dataloader torch.utils.data.DataLoader(dataset, batch_size4, num_workers4) # 训练循环省略标准 PyTorch 训练流程这里需要重点注意的是num_classes 4因为 Faster R-CNN 的 3 个类别之外还要加一个背景类。这是从 YOLO 切过来最容易犯的错误——YOLO 的类别数直接就是nc而 Faster R-CNN 的num_classes永远要加 1。4.3 两种格式混用时的注意事项往下传之前先把这三点记下来xml 文件里如果出现了difficult1的标签训练时默认会被忽略掉YOLO 格式的类别顺序是按names列表排列的转换到 VOC 时 class ID 也会按这个顺序映射最好先确认两边一致如果只用 xml 做迁移训练图片分辨率差异不能太大Faster R-CNN 内部会做 resize但异质分辨率太多依旧影响收敛5. 常见坑与排查训练掉点、标注错位和显存翻车的真实记录数据跑通只是开始真正让人头疼的是那些半路杀出来的问题。这一章写几类我在类似数据集上调参时实打实踩过的坑每条都是现象、原因、解决串起来照着排查能省不少时间。5.1 训练集 loss 下降但验证集 mAP 不动现象训练集 loss 正常下降但每轮验证集 mAP 波动很大甚至个别轮次回退到 60 以下。原因最常见的是学习率设置偏高导致验证阶段权重在震荡。还有一个可能性是数据划分不均匀——如果训练集中某个类别的目标数量占绝对优势验证集里另外两个类别目标很少mAP 的统计方差就会变大。解决先降学习率比如把lr0从 0.01 调到 0.001同时给三个类别分别统计目标数量占比。如果 helmet 占比小于 10%建议在 loss 里给这个类别加权重或者用mosaic增强多补充小目标样本。最直接的办法是打开results.png看 loss 曲线的收敛形态如果 loss 曲线锯齿严重基本就是学习率的问题如果 loss 平稳但 mAP 不动再回头查数据划分。5.2 标注框偏大导致边框位置精度不达标现象mAP0.5 能达到 90 以上但 mAP0.5:0.95 只有 60 出头。说明框虽然能框到目标但位置贴合不够。原因标注框绘制得偏大比如画安全帽的框时把头发或帽檐外的区域也包进来了。暗光环境下标注员容易把反光边当成目标的一部分。解决用可视化脚本把 ground truth 框画回图片上import cv2 img_path dataset/train/images/xxx.jpg label_path dataset/train/labels/xxx.txt img cv2.imread(img_path) h, w img.shape[:2] with open(label_path, r) as f: for line in f: parts line.strip().split() cls_id, x_center, y_center, box_w, box_h int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) x1 int((x_center - box_w / 2) * w) y1 int((y_center - box_h / 2) * h) x2 int((x_center box_w / 2) * w) y2 int((y_center box_h / 2) * h) color (0, 255, 0) if cls_id 0 else ((0, 0, 255) if cls_id 1 else (255, 0, 0)) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.imwrite(check_visual.jpg, img)抽 20~30 张不同光照条件的图片做叠加检查如果光晕边缘被包进框里就说明标注需要修正。这类问题最有效的处理方式是从源头解决回到视频抽帧环节重新制作标签或者直接用 Roboflow 的注释工具做批量微调。盲目加大迭代轮数治标不治本。5.3 显存溢出batch 参数反复翻车现象训练启动时报 CUDA out of memory或者跑了几轮之后训练进程被杀掉。这种情况在 batch 参数设置过高、老显卡上特别常见。原因把 batch 设成 16 或 32在 1080Ti11GB 显存上训练yolov8s就很容易卡死。尤其开了mosaic1.0增强后每张 mosaic 图等于把 4 张图拼接起来内存占用直接乘 4。解决显存不够时优先调小 batch 而不是降低imgsz。我常用这个递减法先试 batch16OOM 则减到 8再减到 4。同时可以打开cacheTrue参数把预处理后的数据缓存到内存避免反复做数据增强占用显存。另外一种做法是减小模型规模——用yolov8n替代yolov8s代价是 mAP 可能降 2~3 个点但能跑总比崩掉好。之后再考虑梯度累积。5.4 yaml 路径失效导致训练启动即失败现象训练初始化时报AssertionError: train: 不存在该路径或者FileNotFoundError但数据集文件都在。原因data.yaml里用的是相对路径而当前执行 train 命令的工作目录已经不在数据集根目录下了。这个数据集的 yaml 默认写的是../train/images风格路径如果把数据集解压在某个深层目录相对路径解析到别处。解决强烈建议改成绝对路径。在 Python 环境中运行一行命令即可import yaml with open(dataset/data.yaml) as f: cfg yaml.safe_load(f) cfg[train] /absolute/path/to/dataset/train/images cfg[val] /absolute/path/to/dataset/valid/images cfg[test] /absolute/path/to/dataset/test/images with open(dataset/data.yaml, w) as f: yaml.dump(cfg, f)或者直接在命令行中覆盖参数yolo命令支持后接train/path/to/train/images这样就不会受 yaml 里的路径影响。5.5 小目标检测效果差安全帽在远距离时经常漏检现象在监控画面中距离摄像头较远的工人安全帽在图片上可能只有 15×15 像素这类目标漏检率高。原因在 640×640 分辨率下训练小目标的特征图占比太小此外如果训练时开了mosaic增强小目标在拼接后尺寸会被进一步缩小。解决训练时把imgsz调到 1280再开启augmentTrue中的scale0.5做多尺度训练。代价是显存占用翻倍或更多所以通常需要把 batch 减半。再配合降低置信度阈值让模型在推理时保留更多低分框再用 NMS 去重效果能好很多。6. 进阶技巧验证集可视化与安全帽/背心场景的部署调优模型训练完只盯着 mAP 数字是不够的。尤其在工业安全场景真正有效的是把预测结果叠加回真实画面里看模型在什么距离、什么光照条件下开始丢目标然后针对性地去调整。我自己的习惯是训练完立刻对验证集做一次批量推理把预测结果连同 confidence 分数一起可视化每张图上标注出预测框、类别和置信度然后快速扫一遍确认模型在多数画面中能框住三个类别再检查有没有误检比如把货架上的黄色标签当作安全帽以及置信度普遍偏低的时间段集中在哪。接下来要做的验证是不同光照时段下的表现。车间监控视频里通常存在明显的自然光变化上午、下午、夜间的光照条件差异很大而普通的训练集如果主要以白天为主夜间检测的效果往往不够理想。在验证集上按时间段分批统计 mAP就能直观看出哪些时段明显掉点再决定是否需要补充夜间样本或做亮度增强。另外一个重要验证是确认最小可检测目标尺寸。用一段包含不同距离行人的测试视频跑一次推理观察模型在哪个距离开始漏检安全帽如果 20 米处就开始丢目标就需要调高imgsz或者给测试信号加上agnostic_nmsTrue更好地滤除重叠框。关于部署推理的稳定输出除了显存和硬件适配最有用的一个技巧就是给不同类别设置不同置信度阈值。比如 person 的阈值可以设高一点0.5helmet 和 vest 设低一点0.3因为安全类的目标宁可把不确定的框也报出来让后端人工二次判断也不能漏报。生产环境中使用 OpenCV 的DNN或 ONNX Runtime 做推理都比直接跑 PyTorch 更节省显存尤其是同时接多路监控流的时候。说了这么多这套数据集真正能派上用场的地方还是在安全生产管理系统里把违规行为变成自动告警有人没戴安全帽或没穿安全背心系统能以帧为单位推送提醒不用人工盯监控。从那以后我每次做类似数据集训练都会强制自己先跑一遍可视化验证再谈调参模型看起来得分高和真正能在现场用是两码事。希望帮到你。本文还有配套的精品资源点击获取