资讯动态

烟雾检测数据集全攻略:10000张图+三格式标签+划分脚本+训练教程

发布时间:2026/9/26 8:58:31 来源:尧图企业网站定制
简介本资源为面向目标检测初学者与算法工程师的YOLO烟雾目标检测数据集聚焦真实场景下的烟雾识别任务可用于安防监控、工业巡检、火灾预警等方向的模型训练与课程实践。数据经labelimg精细标注标注框质量高场景覆盖丰富并同步提供voc、coco和yolo三种格式标签分别存放于独立文件夹可直接接入YOLO系列检测框架。压缩包共约2000个文件以1986个xml标注文件为主另含少量html说明文档、txt列表与py脚本整体约574MB目录结构清晰便于按格式取用。随包附赠数据集划分脚本可按需生成训练集、验证集与测试集并配有Windows与Linux环境搭建及训练案例教程帮助读者快速跑通从环境配置到模型训练的全流程。目前已有492人学习下载适合希望快速上手烟雾检测实战的读者参考使用。1. 烟雾目标检测数据集怎么选10000 张图 三格式标签到底解决了什么做烟雾检测的团队十有八九卡在同一个地方模型结构抄得飞快数据集却迟迟凑不齐。烟雾这东西不像行人车辆有固定轮廓早期是半透明的薄雾中期是翻滚的灰团后期又和天空、水汽、粉尘混在一起标注边界极其主观。更麻烦的是公开数据里真正带 VOC、COCO、YOLO 三套标签的烟雾集很少多数人拿到一批图还得自己写转换脚本转完发现类别对不上、坐标越界、空标签一堆。这个标题里的「10000 张图片 voc、coco 和 yolo 三种格式标签 划分脚本 训练教程」本质是把数据准备这条最脏最累的链路一次性打包图片够量、标签三种主流格式齐全、划分脚本负责切分 train/val、训练教程负责把 YOLO 跑起来。它适合三类人——刚入门想跑通第一个烟雾检测 demo 的新手、要快速验证改进模块是否有效的研究者、以及需要给实际项目做烟雾预警原型的工程师。下面我按「数据长什么样 → 怎么转怎么切 → 怎么训 → 坑在哪 → 怎么验证」的顺序把这条链路讲透。2. 三格式标签的差异与转换VOC、COCO、YOLO 到底谁在用什么2.1 三种格式的字段结构对比同一张烟雾图三种格式描述的是同一件事但组织方式完全不同。VOC 是每张图一个 XML坐标是左上角加右下角的绝对像素值COCO 是一个大 JSON所有图片、标注、类别集中管理坐标是[x, y, width, height]的绝对像素YOLO 是每张图一个 txt每行class cx cy w h全部归一化到 0~1。理解这个差异是后面所有转换和排错的基础。维度VOCCOCOYOLO文件形态每图一个 XML单个 JSON每图一个 txt坐标形式xmin,ymin,xmax,ymaxx,y,w,hcx,cy,w,h坐标单位绝对像素绝对像素归一化 0~1类别位置XML 内 name 字段categories 数组行首 class id典型用途老框架、评测脚本通用评测、分割YOLO 系列训练选型上我的建议很直接训练 YOLO 就用 YOLO 格式别在训练时临时转做跨模型对比或投稿评测保留 COCOVOC 更多是历史兼容很多老工具链还认它。数据集同时给三套好处是你不用在格式上反复折腾坏处是必须搞清楚三者类别 id 的映射否则训出来的模型会把「烟」和「雾」搞反。2.2 VOC 转 YOLO 的脚本与四个边界坑最常见的操作是把 VOC 转成 YOLO。下面这段脚本我用了很多次核心是把绝对坐标归一化同时处理越界和空标注。import os import xml.etree.ElementTree as ET # 类别到 id 的映射必须和 data.yaml 里的 names 顺序一致 CLASS_MAP {smoke: 0} IMG_W, IMG_H 1920, 1080 # 若图片尺寸不统一需逐图读取真实尺寸 def voc_to_yolo(xml_path, out_dir): tree ET.parse(xml_path) root tree.getroot() # 优先从 XML 里读真实尺寸避免硬编码导致归一化错误 size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text.strip() if name not in CLASS_MAP: continue # 未登记类别直接跳过防止 id 错位 bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 裁剪越界坐标烟雾标注经常手抖超出图像边界 xmin, xmax max(0, xmin), min(w, xmax) ymin, ymax max(0, ymin), min(h, ymax) if xmax xmin or ymax ymin: continue # 宽高非法丢弃 cx (xmin xmax) / 2 / w cy (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{CLASS_MAP[name]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) if not lines: return # 空标签图不生成 txt避免训练时全背景样本干扰 os.makedirs(out_dir, exist_okTrue) stem os.path.splitext(os.path.basename(xml_path))[0] with open(os.path.join(out_dir, stem .txt), w) as f: f.write(\n.join(lines))逻辑说明先读 XML 里的真实宽高而不是硬编码这是最容易翻车的地方——很多脚本图省事写死 1920×1080遇到手机拍摄的竖图坐标全错。参数上CLASS_MAP必须和训练配置里的names顺序严格一致id 从 0 开始。四个边界坑分别是坐标越界要裁剪、宽高非法要丢弃、未登记类别要跳过、空标签图不要生成空 txt。最后一条尤其重要YOLO 训练时空 txt 会被当成纯背景负样本比例过高会让模型学不到烟雾特征。2.3 COCO 与 YOLO 互转时最容易错的两件事COCO 转 YOLO 时第一件容易错的事是bbox的格式。COCO 的[x, y, width, height]里 x、y 是左上角而 YOLO 要的是中心点转换时cx (x w/2) / img_w少加半个宽就整体偏移。第二件是category_id不连续。COCO 的 id 可能从 1 开始甚至跳号直接拿来当 YOLO 的 class id 会越界必须先建一张category_id → 连续 id的映射表。反过来 YOLO 转 COCO 时images、annotations、categories三个数组的 id 要自洽annotation里的image_id必须能在images里找到否则评测脚本直接报错。我一般会写个校验函数转完统计每个类别的框数量和原格式对不上就说明映射错了。3. 划分脚本怎么写train/val 切分比例与烟雾场景的类别均衡3.1 为什么烟雾数据集不能简单随机切分通用做法是 8:1:1 随机切分但烟雾数据集有个特殊问题同一段视频抽帧出来的图片高度相似。如果随机切训练集和验证集里会出现几乎一样的图验证指标虚高实际部署一塌糊涂。我一般按「源视频/源场景」分组切分同一组的图要么全进训练要么全进验证。下面这个脚本按文件名前缀分组保证同源不跨集。import os import random import shutil from collections import defaultdict def split_dataset(img_dir, out_root, ratios(0.8, 0.1, 0.1), group_keylambda n: n.split(_)[0]): # group_key 按文件名前缀分组同源图片不会被拆散 groups defaultdict(list) for name in os.listdir(img_dir): if name.lower().endswith((.jpg, .png, .jpeg)): groups[group_key(name)].append(name) keys list(groups.keys()) random.seed(42) # 固定种子保证可复现 random.shuffle(keys) n len(keys) n_train int(n * ratios[0]) n_val int(n * ratios[1]) splits { train: keys[:n_train], val: keys[n_train:n_train n_val], test: keys[n_train n_val:], } for split, gkeys in splits.items(): img_out os.path.join(out_root, images, split) lbl_out os.path.join(out_root, labels, split) os.makedirs(img_out, exist_okTrue) os.makedirs(lbl_out, exist_okTrue) for g in gkeys: for name in groups[g]: shutil.copy(os.path.join(img_dir, name), os.path.join(img_out, name)) lbl os.path.splitext(name)[0] .txt src_lbl os.path.join(img_dir, lbl) if os.path.exists(src_lbl): shutil.copy(src_lbl, os.path.join(lbl_out, lbl))逻辑说明group_key默认取文件名第一个下划线前的部分作为分组依据实际用的时候按你的命名规则改。random.seed(42)固定种子保证每次切分结果一致方便复现实验。参数ratios是 train/val/test 比例烟雾数据量 10000 张的话 8:1:1 比较稳如果某类烟雾样本特别少可以调到 7:2:1 给验证集更多样本。3.2 切分后必须做的三项校验切分完别急着训先跑三项校验。第一统计每个 split 的图片数和标签数是否一致图片有标签没生成说明转换漏了。第二统计每个类别的框数量分布训练集里某类为 0 就是灾难。第三抽查几张图把 YOLO 框画回去肉眼看框是否贴合烟雾区域。我见过太多人跳过第三步训了半天发现标签整体偏移血泪经验。校验脚本核心就是遍历 labels 目录累加每行首列和预期对比。4. 用这套数据训 YOLO环境、配置与三个必调参数4.1 环境搭建与 data.yaml 配置环境这块Anaconda 建个独立环境最省心Python 3.8~3.10 都行PyTorch 按显卡驱动选对应 CUDA 版本。装完 ultralytics 就能开训。关键是data.yaml要写对路径、类别数、类别名三者必须自洽。# data.yaml path: /data/smoke_dataset # 数据集根目录 train: images/train # 相对 path 的训练图目录 val: images/val test: images/test nc: 1 # 类别数烟雾通常就 1 类 names: [smoke] # 顺序必须和转换脚本的 CLASS_MAP 一致nc和names长度必须相等names的顺序决定 class id和前面 VOC 转换脚本里的CLASS_MAP对不上模型学到的就是错的类别。path用绝对路径最稳相对路径在不同工作目录下启动训练容易找不到文件。4.2 训练命令与三个必调参数yolo detect train \ datadata.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ conf0.25 \ iou0.5 \ projectruns/smoke \ nameexp1参数说明imgsz640是输入分辨率烟雾目标通常较大640 够用小烟雾多的话提到 960。batch16按显存调显存不够就降别硬撑导致 BN 崩溃。lr00.01是初始学习率烟雾数据集如果只有 1 类且样本均衡这个值稳如果 loss 震荡就降到 0.001。conf和iou在训练阶段主要影响验证时的 mAP 计算真正调检测门限是推理阶段的事。modelyolov8s.pt是预训练权重小数据集上迁移学习比从头训收敛快得多。4.3 训练过程看什么指标训练时重点盯三个box_loss是否稳定下降、mAP50是否上升、cls_loss有没有突然飙高。box_loss不降说明标签坐标有问题回去查转换。mAP50卡在低位可能是学习率太大或数据太少。cls_loss飙高常见于类别映射错乱。另外 YOLO 的混淆矩阵在单类别时看着「总合不唯一」是正常的因为只有一类别被这个吓到。5. 避坑与排查烟雾数据集训练中最常见的五个翻车现场5.1 现象训练 loss 正常但验证 mAP 接近 0原因验证集和训练集图片高度相似被分到同一侧或者验证集标签路径写错导致读到空标签。解决用分组切分脚本重新切检查data.yaml里 val 路径下 labels 是否真实存在抽查几张验证图把框画出来看。5.2 现象BN 层崩溃报错含 NaN原因batch 太小或学习率太大烟雾数据集如果某批全是相似背景BN 统计量方差趋近 0。解决把 batch 提到 16 以上学习率降到 0.001或者改用modelyolov8s.pt这类带预训练的权重稳定初期训练。5.3 现象推理时烟雾框大量漏检原因训练时conf设太高或者数据集中小烟雾样本太少。解决推理时把conf从 0.25 降到 0.1 试同时检查训练集里小目标占比必要时提高imgsz到 960 并开启多尺度训练。5.4 现象同一张图重复检测出多个重叠框原因NMS 的iou阈值设太高烟雾边界模糊导致模型输出多个相近框。解决推理时把iou从 0.5 降到 0.3~0.4让 NMS 更激进地合并重叠框。5.5 现象COCO 格式评测脚本报 image_id 找不到原因YOLO 转 COCO 时annotations里的image_id和images里的id没对齐或者类别 id 跳号。解决转换后写个校验遍历所有 annotation 确认 image_id 在 images 集合里category_id 从 1 连续编号。6. 验证与进阶把烟雾检测从能跑推到能用训完模型别只看 mAP 数字真正决定能不能用的是推理阶段的调参和场景验证。我一般会做三件事。第一拿一段真实烟雾视频抽帧跑推理观察框的时序稳定性烟雾是动态目标单帧准不代表连续帧稳。第二画 PR 曲线找最佳置信度门限不同场景门限不一样室内烟雾可以设 0.3室外远距离烟雾得降到 0.15。第三做误报分析把背景里的云、水汽、粉尘单独抽出来跑一遍看误报率烟雾检测最大的敌人从来不是漏检而是误报。进阶方向上如果这套 10000 张数据训出来的基线还不够可以考虑几个思路换更大的输入分辨率专门抓早期薄雾在数据层面做烟雾合成增强把烟雾前景贴到不同背景上扩充样本或者把 YOLO 和时序模块结合用连续帧的时序信息压制单帧误报。验证方法上我习惯留一个完全独立的测试集不参与任何调参最后只跑一次这个数字才是能拿出去说的。我自己踩过最深的坑是早期图省事用随机切分验证 mAP 0.9 沾沾自喜部署到实际场景漏检一半回头查才发现训练验证集里全是同段视频的相邻帧。从那以后我切分必按源分组验证必画框肉眼过一遍。数据准备这步偷的懒训练和部署阶段会加倍还回来。希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑