恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
小场景烟火识别数据集实战指南:从采集标注到YOLO训练
首页
资讯中心
/
小场景烟火识别数据集实战指南:从采集标注到YOLO训练
小场景烟火识别数据集实战指南:从采集标注到YOLO训练
发布时间:2026/9/26 2:31:40
简介这是面向计算机视觉与深度学习入门及进阶人群的烟火识别训练数据集聚焦公园、街道、室内等小范围场景中的烟火检测任务。包内共1204个文件压缩包约69.68MB包含600张jpg原始图像、600个配套XML标注文件及4个txt说明文件。XML标注提供烟火目标的边界框、类别与关键特征可直接用于YOLO、SSD、Faster R-CNN等常见检测模型的训练与验证txt文件可能包含数据集划分或类别清单便于整理训练流程。目前已有951人学习使用适合需要快速获得标注数据以开展烟火检测实验、完成课程设计或进行迁移学习实践的研究者。借助该数据集可帮读者省去手动采集与标注的繁琐环节专注于模型搭建、调参与效果评估。1. 小场景的烟火识别数据集通用数据集为什么在小监控里翻车同一个检测模型在森林火灾、厂房大空间这类公开数据集上 mAP 能跑到 0.9一装到厨房、配电箱、楼道小监控画面上烟是半透明的火只有十几像素漏检率立刻飙升。这个标题要做的就是把小场景烟火识别数据集这件事拆开从采集方案、标注规范、格式转换到训练验证最后落到避坑和持续扩充形成一条能重新跑通的链路。它适合做安防摄像头联动、机房告警、工地消防监测的算法工程师和学生前提是你手头已经有真实场景的图像或视频抽帧并且愿意在数据质量上花时间。这里不解决大场景遥感火情不讲怎么从零搭模型只讲怎么把数据集做扎实。2. 数据长什么样来源、类别与小场景采集方案烟火识别数据集听起来简单真正动手才发现难点全在样本形态。小场景的“烟火”和通用火灾检测里的“烟火”不是一回事。这里先立住这个概念后面的采集、标注和训练才不容易跑偏。2.1 小场景与通用场景数据集的主要差异通用场景数据集绝大多数拍的是大场面森林火灾的烟墙、工厂仓库的大火、远处直升机洒水。这些画面里火焰和烟雾占画面比例高识别目标大纹理信息丰富。小场景不一样的地方有三点。第一是目标尺度小。一个安装在厨房吊顶的摄像头视野大概两三米见方灶台上的火苗框起来可能只有 30×40 像素在 1920×1080 原图里占比不到百分之一。第二是烟雾半透明。烟雾没有清晰的边缘透出背后的橱柜和墙砖标注和模型都在跟“似有似无”的纹理搏斗。第三是干扰源密集。厨房水蒸气、炒菜油烟、窗外阳光、红色调料瓶、手机屏幕亮光都会让模型把普通画面当成烟火。还有一个常被忽略的差异拍摄视角。通用数据集多为平视或俯视的大广角小场景监控往往是斜下角或正下角目标有遮挡、形变、明暗突变。所以做这个数据集的时候不能直接下载一个公开火灾数据集就开训必须先从视角、尺度和干扰源三个维度确认它是否匹配你的场景。2.2 数据来源公开数据集、实拍与合成增强常见的做法是三条腿走路。公开数据集方面网上能下到的火灾识别数据集绝大多数偏向大场景少数包含室内近景的样本但数量少且标签风格不一致。有人会直接套用 coco2017 数据集结构去凑烟火类别但 COCO 本身没有 smoke/fire 类只能算作预训练特征来源不能当烟火数据用。更实际的做法是把公开数据集当作补充样本库只挑其中火焰占比小、视角贴近监控画面的图片抽出来手动复核标签后再并入自己的训练集。实拍是数据集质量的主心骨。不要真的在室内点火拍合规和安全隐患都太大。我一般会去采集三类素材厨房日常炒菜时的油烟和灶火、工地/工厂电焊火花、蜡烛和燃烧盘等可控小火焰。拍摄时分别用手机和低分辨率监控头各拍一段让模型见过两种成像质量。如果项目里已经有客户提供的现场监控视频抽帧前记得确认数据权限。合成增强可以作为补充。用带透明通道的烟雾贴图叠加到真实背景上能快速扩出大量烟雾样本代价是真实感有限。下面是个最小叠加脚本import cv2 import numpy as np bg cv2.imread(kitchen.jpg) # 真实背景小场景优先 smoke cv2.imread(smoke.png, cv2.IMREAD_UNCHANGED) # RGBA透明烟雾贴图 h, w bg.shape[:2] smoke cv2.resize(smoke, (w, h), interpolationcv2.INTER_LINEAR) alpha smoke[:, :, 3:4].astype(np.float32) / 255.0 # 取出alpha通道并归一化 alpha cv2.GaussianBlur(alpha, (0, 0), sigmaX1.5) # 让边缘更柔和 bg_f bg.astype(np.float32) smoke_rgb smoke[:, :, :3].astype(np.float32) blend (bg_f * (1 - alpha) smoke_rgb * alpha).astype(np.uint8) cv2.imwrite(kitchen_smoke_syn.jpg, blend)这段代码的逻辑是把烟雾贴图的 alpha 通道作为前景权重背景按 1-alpha 保留两张图加权求和。注意对 alpha 做高斯模糊因为真实烟雾边缘是逐渐消散的硬边贴图一眼假。参数里 sigmaX 建议 1.02.5太小边缘生硬太大烟雾会散成一片看不清。合成样本只建议占总样本的 20% 以内并且要人工筛选掉严重失真的图否则模型会把“模糊”学成烟雾特征。2.3 采集方案与场景清单采集前先列一份场景清单避免拍来拍去都是同一类画面。表格是实际项目中会用到的底稿场景类型建议角度主要干扰源建议样本量厨房灶台斜上45°、顶部吊装水蒸气、油烟、红椒500配电箱/机柜正面、侧上方指示灯、红色线缆300楼道走廊两端对角灯箱、安全出口红光300垃圾桶/废纸篓俯视塑料袋反光200工地小角落平视、斜视焊光、红色安全帽400每类场景要覆盖白天、夜晚、开灯、关灯、逆光五个光照条件。别只挑“看得清”的画面故意多拍一些模糊、过曝、偏暗的样本这些才是部署时真正会遇到的画面。视频抽帧时不要每秒都抽否则连续帧几乎一样浪费存储还造成数据泄漏建议每秒抽 1~2 帧并且保留抽帧时间戳后面划分数据集时按时间戳分组。3. 标注与格式转换把图像变成 YOLO 能吃的数据集采集完的原始图像还是半成品。烟火识别的难点不只是“目标在哪里”而是“烟到哪里为止、火算不算红外光晕”。这一步标注规范定不好之后的训练、评估全部受影响。3.1 标注目标烟、火分开标还是合成一个我的建议是分开标成两类class 0 为 smokeclass 1 为 fire。虽然最终部署时可以合并成一个告警但训练阶段分开有两个好处一是火焰和烟雾在形状、纹理、运动特征上差异明显让 loss 分别学习两类特征比强行合成一个类别更稳定二是推理时如果经常出现“烟很多但火不识别”看混淆矩阵就能立刻定位是哪一类出了问题。标注框的范围要写进规范。对火焰框住亮芯加橙色外焰不要框进烟雾对烟雾框住肉眼可见的半透明核心区淡到几乎看不清的透明边缘一律不框。可能有人觉得“边缘也是烟”但标注边缘会导致标签框大幅抖动同一帧不同人标出的框 IoU 只有 0.4模型训练等于在跟噪声作对。小目标也要设一个下限。单边像素小于 4 的框直接丢弃因为 resize 到 640 之后这些目标只剩 12 像素模型不可能学出有效特征。保留它们只是让 loss 被随机噪声污染。3.2 标注工具与标注规范标注工具我一般用 X-AnyLabeling支持输出 YOLO 格式也支持半自动预标注。先把类别写进 classes.txtsmoke fire然后设置自动保存间隔为 5 分钟标注快捷键保持默认。多人协作时一定要先定“核心烟团”的定义拿 10 张图让每个标注员独立标一遍计算两两之间的 IoU低于 0.6 就说明规范没对齐宁可停下来重新讨论。3.3 把 VOC 转成 YOLO 格式转换脚本与无效框过滤很多公开数据下载下来是 VOC 的 XML 格式训练自己的数据集时通常要转成 YOLO 的 txt。这里给出一个带过滤逻辑的转换脚本处理小场景烟火数据时比通用脚本多两个关键判断。import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, out_path, class_map, min_side4): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_map: continue # 跳过未定义类别或负样本标记 box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) w xmax - xmin h ymax - ymin if w min_side or h min_side: continue # 过滤掉小于4像素的框小目标不能小到丢失全部特征 xmin max(0, min(xmin, img_w - 1)) xmax max(0, min(xmax, img_w - 1)) ymin max(0, min(ymin, img_h - 1)) ymax max(0, min(ymax, img_h - 1)) if xmax xmin or ymax ymin: continue # 过滤掉越界后被压成0宽度的框 x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h cls_id class_map[name] lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) if len(lines) 0: return with open(out_path, w, encodingutf-8) as f: f.write(\n.join(lines))参数说明min_side 是保留框的最小边长设 4 是对应 imgsz640 的常见选择如果你后面训练用 1280可以适当放松到 2。归一化坐标全部保留 6 位小数太短会引入量化误差。转换完成后要随机抽 20 张图把 txt 坐标画回原图人工看一眼最常见的问题是 XML 标注把宽高写反。3.4 按场景划分 train/val/test 并统计类别分布烟火视频抽帧得到的图片时间相关性强直接随机划分会把同一段视频的相邻帧分到训练集和验证集验证指标虚高。正确做法是先按视频片段或采集时间戳分组再把整组数据划入同一集合。import os import random import shutil from collections import Counter # 假设 images 目录下文件名格式为 scene001_frame0001.jpg # 每组按场景ID划分而不是按单张图 files [f for f in os.listdir(images) if f.endswith(.jpg)] scene_groups {} for f in files: scene_id _.join(f.split(_)[:1]) # 取文件名前缀如 scene001 scene_groups.setdefault(scene_id, []).append(f) scene_ids list(scene_groups.keys()) random.seed(42) random.shuffle(scene_ids) train_scenes scene_ids[:int(len(scene_ids) * 0.8)] val_scenes scene_ids[int(len(scene_ids) * 0.8):int(len(scene_ids) * 0.9)] test_scenes scene_ids[int(len(scene_ids) * 0.9):] # 统计类别数量作为训练权重参考 label_counter Counter() for scene in train_scenes: for img in scene_groups[scene]: label_file os.path.splitext(img)[0] .txt label_path os.path.join(labels, label_file) if not os.path.exists(label_path): continue for line in open(label_path, r, encodingutf-8): label_counter[int(line.strip().split()[0])] 1 print(label_counter)这段代码先按场景分组再按组划分保证同一个监控点位拍出来的画面不会在训练集和验证集里同时出现。random.seed(42) 固定随机种子别人复现你的结果时拿到一致的划分。类别统计会告诉我们 smoke 和 fire 的比例如果 fire 只有 smoke 的十分之一后面训练就要做过采样或样本加权。4. 训练自己的烟火识别模型YOLOv8 与关键参数数据集就位以后接下来是用它去训练一个能用的检测模型。这里不推冷门框架选 YOLOv8 和 YOLOv5 之一它们的问题不是“哪个更强”而是“哪个更适合你的部署环境”。4.1 选型YOLOv8n 还是 YOLOv5s我的经验是需要跑在 Jetson、RK3588 这类边缘盒子上优先考虑 YOLOv8n导出 ONNX 和瑞芯微转换工具的支持度更好如果团队已有 YOLOv5 的部署代码和量化流程就继续用 YOLOv5s不折腾。两者在这个任务上的精度差距远小于数据质量带来的差距把时间花在补数据上更划算。注意一点预训练权重用的是 COCO 预训练模型但 COCO 缺少烟火类别所以加载预训练权重只取 backbone 特征Head 层要按 nc2 重新初始化。YOLO 训练命令会自动处理这一步你不要手动改权重文件否则容易踩维度不对的坑。4.2 数据集 YAML 与训练命令处理数据集用于 YOLOv8 训练时最常犯的错是 YAML 里路径写绝对路径换一台机器就废。推荐用相对路径加path字段指定数据根目录。新建smoke_fire.yamlpath: /data/smoke_fire train: images/train val: images/val test: images/test nc: 2 names: 0: smoke 1: fire说明train/val 下面直接是图片文件标注 txt 放在labels/train和labels/valYOLO 靠找同名文件实现对应无需在 YAML 里写 label 路径。启动训练前先打印配置确认一下yolo cfgsmoke_fire.yaml确认无误后开始训练yolo train modelyolov8n.pt datasmoke_fire.yaml imgsz640 batch16 epochs300 projectruns/smoke_fire命令里没有加devicecpu默认优先 GPU。第一次训练建议先用小 batch 跑 20 轮确认 loss 不发散、不出现 NaN再跑完整训练。4.3 小场景训练参数怎么设小场景烟火识别不适合直接套用公共教程里的默认参数。下面这张表是实测后比较稳的起点参数建议值原因imgsz640兼顾小目标与显存火焰不足 10 像素可试 1280batch168G显存/ 3216G以上显存不足优先降 batch不降 imgszepochs300烟雾纹理弱需要更久才能收敛mosaic1.0 前 250 轮最后 10 轮关闭防止合成烟和真实烟长混hsv_h0.015色相偏移太大会把火焰变成绿色hsv_s0.5保留烟雾的灰白色调close_mosaic10关闭 mosaic 后模型适应单一尺度hsv 增强是烟火识别的双刃剑。火焰颜色是有强先验的色相偏移 0.1 就会生成大量橙红色物体当火焰干扰反而更大。所以这里把 hsv_h 压到很小保留亮度变化不改变颜色的基本分类依据。4.4 评估指标不要被 mAP 骗了训练完先看results.csv里的 mAP0.5 和 mAP0.5:0.95。小场景烟火更关键的是 F1 和混淆矩阵。烟雾因为半透明视觉特征弱漏检往往比误检多所以重点看 Recall 而不是 Precision。如果 F1 不理想先去val_batch_pred.png里翻漏检图确认是烟太淡还是目标太小再决定是补数据还是调阈值。还有个小技巧把验证集的置信度阈值从默认的 0.25 降到 0.1导出更多预测框专挑那些“低置信度但实际有火”的样本。这些样本就是数据集缺口的直接证据应该回填到训练集而不是简单地靠调阈值硬扛。5. 烟火识别数据集避坑5 条踩坑记录数据集的坑比模型结构多得多而且每一坑都会直接反映到最终效果上。下面这五条是我做同类项目时反复踩过的问题每条都按“现象 → 原因 → 解决”展开。5.1 验证集虚高连续帧泄漏现象训练时 mAP0.5 到 0.98部署到新场景基本不能用。原因视频抽帧后随机划分同一段 10 秒视频的 20 帧分到了训练集和验证集模型等于做过“开卷考试”。小场景监控画面背景固定只需要记住背景就足够过验证真实场景一换角度就失效。解决按视频场景分组划分而不是按帧划分。前面 3.4 的脚本已经打了样务必把同一个时间段、同一机位的帧归到同一个组。5.2 烟雾框边缘抖动现象同一张图两次标注的框相差 30% 以上训练 loss 一直降不下来。原因标注规范没有定义“烟到哪里为止”。半透明烟雾边缘扩散有人框到浓烟核有人框到整个烟团标签噪声直接放大。解决把标注规范写死只框不透明度超过 50% 的核心区域做一次双人标注一致性测试IoU 低于 0.6 就重新培训再开工。这个成本远低于后期清洗标签。5.3 红色干扰物体误报现象红色灯笼、厨房红椒、晚霞、红色安全帽都被识别成 fire。原因小场景里火焰颜色成了最强特征模型学到的是“橙色红色块”而不是火焰的形状和闪烁纹理。解决专门建一个负样本集包含上述干扰场景但不标注训练时放进 images 目录且 labels 目录留空让模型学会“有红色但没有火”的背景。这批负样本同样需要按场景划分不能全都放训练集。5.4 小火焰在 resize 中丢失现象火焰在 1920×1080 里是 20×20 像素送到 640×640 后只剩 7×7特征完全被压缩成色块。原因统一 resize 对大图小目标不友好缩放过程中纹理和边缘细节被抹掉。解决优先用 imgsz1280 训练显存不够就切成瓦片把大图按 640×640 重叠裁剪火焰完整落在某一块再训练。推理时也用瓦片拼接不要图省事整图缩放。5.5 烟多火少类别失衡现象模型对烟识别很好对火的召回率特别低但总 Precision 看起来还不错。原因标注数据中 smoke 样本远多于 fire尤其厨房场景几乎不断烟火焰只在爆炒或起火时出现。loss 被多数类别主导。解决训练时让 fire 类在采样器里过采样或在 loss 权重中给 fire 更高权重。注意不要把权重调太大否则模型会把一切橙色物体都当火。我一般先统计 3.4 里的类别数量按比例从 1.0 到 3.0 之间试。6. 让数据集越用越强难例回捞与版本迭代数据集做完不是终点上线后保持迭代效果才会越用越稳。我最后的习惯是用训练好的模型反哺数据拿一批没有标注的新场景视频跑推理置信度低于 0.35 的框特别值得看尤其那些“模型认为像烟但我们知道没烟”的干净场景以及漏掉的淡烟雾都是难例。把这些难例帧抽出来人工标注合入下一版训练集。验证方法可以简单固定下来每次迭代后跑同一组留存的测试集比较 mAP 和漏检数不要用用户反馈当评估指标太滞后。迭代记录记在数据集目录的 CHANGELOG 里写清楚新增了多少场景、标签规范改了没有、有没有换过划分方式不然三个月后你都不知道上一版为什么效果更好。做烟火识别数据集最大的教训就是模型改结构只能涨两个点数据质量能涨十个点。与其反复调参不如先回看标注规范有没有把半透明烟雾处理干净。希望我的这些经验能帮你少走点弯路把数据集一步做到位让模型真正在小场景里扛住实战。希望帮到你。本文还有配套的精品资源点击获取