ARTICLE DETAIL

资讯详情

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

YOLOv8火焰烟雾检测实战:从数据标注到实时部署

YOLOv8火焰烟雾检测实战:从数据标注到实时部署 简介本资源是一套面向计算机视觉初学者与课程实践者的火灾检测系统实现方案聚焦毕业设计、期末大作业等学术场景解决火焰与烟雾目标的实时识别问题。资源包共499个文件含166个Python源码覆盖数据预处理、YOLOv8模型训练与推理、可视化全流程、35个配置用YAML文件、26个PNG/JPG图像样本及26个标注XML文件另有CUDA扩展相关C/cu/h头文件与编译脚本整体压缩包大小为82.75MB。已有87人下载学习适用于人工智能、智能安防方向的学生开展深度学习项目实践。用户可直接运行完整检测流程代码注释详尽关键模块如DCNv3动态卷积适配、环境配置end-back.env、Qt界面集成.ui/.qrc均保留可调试结构便于理解YOLOv8工程化部署细节并快速二次开发。1. 项目概述为什么我选择用YOLOv8做火焰烟雾检测先说结论YOLOv8不是火焰烟雾检测的唯一选择但它是目前“效果、速度、易用性”三者平衡得最好的方案之一。这套系统我做下来从数据准备到训练完成再到部署到本地摄像头实时推理整个链路跑通大概用了两个周末核心代码量不超过500行但背后涉及到的细节坑确实不少。这个项目解决的是什么问题本质上是一个目标检测任务——在视频帧或图片中定位出“火焰区域”和“烟雾区域”并给出边界框和置信度。它的应用场景非常广森林防火监控、化工厂区安全预警、仓库消防报警、甚至家用摄像头火情侦测。和传统的传感器烟雾报警器相比视觉方案的响应速度更快、覆盖范围更广而且能留存现场画面作为证据这是红外传感器和气体传感器做不到的。这篇内容适合谁如果你是刚接触YOLO系列、想跑通一个完整检测项目的人或者是已经在用YOLOv5/YOLOv7、想迁移到v8看看效果差异的开发者这篇文章都能给你一些参考。我会把数据准备、环境配置、训练参数选择、模型评估、常见坑位全部串一遍用的是我实际踩过的坑和调过的参。先放一下最终效果在自建数据集上训练出的模型对室内火焰场景的mAP50能到0.91左右烟雾的mAP50低一些大概0.84原因是烟雾边缘模糊、形状飘忽天生比火焰难学。推理速度在GTX 1660 Ti上640x640输入FP16半精度下大约55ms一帧约合18FPS基本满足实时监控需求。这套系统我拆成了四个模块数据层采集与标注、训练层YOLOv8训练与调参、推理层摄像头/图片实时检测、告警层帧率控制与置信度阈值策略。下面逐个拆开说。2. 整体设计思路YOLOv8凭什么适合这个场景2.1 YOLOv8相比前代的关键改进YOLOv8是Ultralytics在2023年初发布的作品相比v5和v7它的核心变化可以归纳为四点第一C2f模块替换了C3模块。C2f借鉴了ELAN的设计思路在保持轻量化的同时增强了梯度的流传递。我实际训练时感受到的差异是模型收敛速度更快同样的epoch数下v8的loss下降曲线比v5更平滑最终mAP也略高尤其在烟雾这类小目标上表现得比v5好。第二Anchor-Free检测头。v8彻底抛弃了传统的Anchor机制改成了FCOS风格的解耦头。这意味着训练时不需要再用K-means聚类去算anchor尺寸了省掉了一个调参步骤。它的代价是召回率在某些极端尺度场景下会略低于精心设计anchor的v5但对我们火焰烟雾这种目标尺度相对固定的场景来说利大于弊。第三C2f 解耦头的组合带来自适应训练策略。v8内置了Mosaic数据增强、MixUp、Copy-Paste等策略的自动调度前10个epoch自动关闭Mosaic让模型先稳定收敛之后再逐步开启。这个细节很多人没注意到但它确实减少了训练初期因为增强过猛导致的不收敛问题。第四部署生态更友好。Ultralytics官方提供了跨平台导出能力PyTorch模型可以一行命令导出到ONNX、TensorRT、CoreML、TFLite。对需要部署到嵌入式设备或手机端的场景来说这个优势特别实在。2.2 为什么不用其他方案SSD、Faster R-CNN、传统图像处理在做这个项目之前我其实先评估过几条路线。传统图像处理方案帧差法、颜色空间阈值分割、光流法成本最低但脆弱得不堪一击。火焰颜色在RGB空间中的分布并不稳定受光照、白平衡、物体反光影响极大。我用OpenCV做过一版基于HSV颜色范围的火焰检测在室内稳定光源下效果还行一搬到室外阳光下误报率高到没法用——树叶的反光、红色的汽车、行人的橘色衣服全部被当成火焰。Faster R-CNN在精度上确实能打但在我的GTX 1660 Ti上跑一次推理要200ms以上实时性完全不够。而且它的训练链路比YOLO复杂RPN部分的调参经验也不够普及作为一个个人项目来说性价比太低。SSD是个折中方案但它的召回率在小目标上表现不佳。火焰烟雾检测有一个特点远处的火苗在画面里往往只占几十个像素属于典型的小目标场景。SSD的多尺度特征图设计在高层语义信息上确实有优势但在浅层定位细节上不如YOLO系列的处理干净。综合下来YOLOv8是当时最合理的选择。它的官方预训练权重COCO上的80类模型可以作为很好的起始点通过迁移学习能大幅缩短训练时间。2.3 系统架构设计数据流与控制流整个系统我画了一张很简单的架构图不复杂但每一层的接口都提前定义死了数据层图片/视频流 → 抽帧 → 送检测模型 → 输出检测框、类别、置信度控制层置信度过滤 → NMS去重 → 目标计数 → 阈值判定是否触发告警展示层OpenCV画框 帧率监控 告警标记这种分层设计的好处是如果你想换掉后端检测模型比如以后换YOLOv9或者RT-DETR只需要改数据层的输入输出格式控制层和展示层完全可以复用。实际开发中这个解耦帮我省了不少事——我后来确实把ONNX版本替换过TensorRT版本改动量非常小。3. 数据集准备火焰烟雾检测的核心命门3.1 数据来源与采集策略火焰烟雾检测的数据集是最大的坑。公开可用的高质量数据集非常少比COCO这种通用数据集稀缺得多。我综合使用了三个来源第一个是开源数据集Fire Detection from CCTV来自土耳其的Bilge Karakas等人包含大约1900张标注好的火焰图片。这个数据集质量不错但场景单一多为室内火盆、壁炉。第二个是Fire and Smoke Dataset约2000张标注图覆盖了部分室外场景但很多标注框画得比较粗糙我后期做了大量清洗。第三个是我自己补充的从视频网站下载森林火灾新闻画面、消防演练视频用OpenCV每5秒抽一帧然后手动标注。这批自采数据大概补充了300张主要是增加烟雾的多样性——大火产生的浓烟、建筑火灾的黑烟、森林火灾的灰白烟形态差异极大。关于烟雾数据的补充我特别想强调一点烟雾是半透明的边界非常模糊标注的时候很难判断“哪里算烟、哪里不算”。我的做法是标注肉眼可以辨别的密集烟雾核心区域对于稀薄的边缘区域不标注。这样做的原因是模型需要一个明确的学习边界如果标注得含含糊糊训练时loss会震荡得很严重。3.2 标注实操数据标注具体操作标注工具我推荐LabelImg或者Label Studio。LabelImg是老牌工具安装简单格式直接导出YOLO的txt格式。Label Studio功能更强大支持多人协作但配置麻烦一点。我实际用的是LabelImg。标注流程的核心操作打开图片后按W键开始画框拖出矩形框覆盖目标区域弹窗选择类别我预设了fire和smoke两个类别按D切换到下一张按A回退每张图标注完自动保存同名txt文件内容格式是类别id 归一化中心x 归一化中心y 归一化宽度 归一化高度要特别注意的是归一化坐标的计算。YOLO格式不存绝对像素值存的是相对值范围0到1。比如一张1280x720的图火焰框的左上角在(320, 180)右下角在(640, 450)那么中心点就是(480, 315)归一化之后是(480/1280, 315/720) (0.375, 0.4375)宽度是320/12800.25高度是270/7200.375。标注时我做了一个数据增强策略对每张原图同时保存一个水平翻转的副本标注框坐标相应变换。这样不花额外采集成本就能把数据量翻倍。配合训练时的在线Mosaic增强数据多样性足够满足训练需求。3.3 数据清洗与类别平衡拿到数据后不要急着训练。我花了大量时间做清洗因为偷懒省这步后面返工成本更高。清洗规则有三条删除标注框面积小于图片面积0.5%的样本。这种目标太小学习信号太弱反而会干扰模型删除明显标错的图片框住整面墙的、漏掉明显火焰的对纯火焰、纯烟雾、火焰烟雾混合三种情况做了统计确保每种情况都有足够样本最终我的数据集分布是共3700张训练图、420张验证图、180张测试图。其中包含火焰目标的图有3100张包含烟雾目标的图有2100张——注意这里是有重叠的因为很多图片同时含两种目标。火焰的总标注框数约5400个烟雾约4100个。烟雾数据明显偏少这解释了后面烟雾mAP偏低的原因。提示如果你的数据集类别分布极度不均衡不要只是硬训练。建议先试着用在线增强里的增强倍数去调如果还不够再考虑用SMOTE类的过采样方式复制稀缺类别的样本。4. 环境配置与训练从零跑通YOLOv84.1 环境安装避坑指南YOLOv8的环境配置是这份项目里对新手来说最劝退的部分。我用的配置是Windows 11 Python 3.9 CUDA 11.8 cuDNN 8.9 PyTorch 2.0.1 GTX 1660 Ti 6GB显存。安装命令很简单pip install ultralytics但这里有个大坑——ultralytics包会连带安装最新版的torch和torchvision如果你没有提前装好CUDA版本的PyTorchpip默认会给你装CPU版本显存完全用不上。正确操作是先装GPU版PyTorchpip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu118然后再装ultralytics。装完验证一下import torch print(torch.cuda.is_available()) # 必须输出True输出False的话直接查你的CUDA驱动版本和PyTorch版本是否匹配大概率是版本对不上。我遇到过最恶心的情况是驱动显示CUDA 12.x但PyTorch 2.0默认只支持到11.8需要重新装12.x版本对应的torch。另外推荐加一句pip install albumentationsultralytics的数据增强部分会自动调用它增强效果不装也会有默认的torchvision版增强但装了效果确实好一点。4.2 训练参数选择与调优实践在跑正式训练前我强烈建议先做一个“冒烟测试”——用小数据集、小epoch数跑一次确认数据路径、标注格式、类别映射都没问题再上完整训练。这一步能节省你大量等待时间。我最终使用的训练命令yolo train datafire_smoke.yaml modelyolov8s.pt epochs150 batch16 imgsz640 lr00.01 optimizerSGD patience20逐项说明参数选择的原因model选择yolov8s。v8家族有n/s/m/l/x五个版本体积和精度依次递增。我的显存只有6GB用m已经是极限了所以选了s。如果你想追求极限精度且有更大显存直接上l或x——但要注意实际提升幅度可能没有你想象的大。在火焰烟雾这个任务上s到l的mAP提升通常在3-5个点但推理速度会下降一半以上。lr00.01配合SGD。用过Adam的朋友可能觉得SGD是老古董但在YOLO训练任务上SGD配上合适的warmup和cosine衰减收敛效果就是比Adam稳。我在同样数据集上用AdamW跑过一次前30个epoch确实loss下降很快但后期过拟合明显比SGD早。这不是玄学SGD的权重更新更平滑对噪声标注的容忍度更高。patience20。这是早停参数连续20个epoch验证集mAP没有提升就自动停止。我的训练大概在第90个epoch达到最优然后过了20个epoch还在震荡最终在110个epoch时被早停触发。如果不开早停150个epoch硬跑完最终效果可能还不如110个epoch的——训练后期过拟合的风险远大于收益。batch16。在6GB显存上限情况下640x640的输入16是极限了再大就会OOM。显存不够有两个变通方案一是降低imgsz到512二是开启梯度累积。我实测下来imgsz512最终mAP下降大约4个点所以尽量保分辨率。注意如果你是第一次跑强烈建议先用epochs50快速验证数据没问题再开完整训练。我第一次贪快直接跑150个epoch结果发现数据标注文件里多了一个类别ID为2的标注模型训练了一个多小时才暴露问题浪费了大量时间。4.3 训练过程中的观测要点训练启动后我通常关注这几个指标train/loss的下降曲线应该整体平滑下降如果出现锯齿状震荡大概率是学习率太大或数据标注噪音太大。val/box_loss如果下降后回升说明开始过拟合了。metrics/mAP50(B)是目标检测的核心指标我们更关注mAP50而不是mAP50-95因为火焰烟雾检测的核心诉求是“侦测到没有”对定位框的精确度要求没那么高。训练结束后还会自动生成一系列结果文件。最有用的有两个confusion_matrix.png和results.png。混淆矩阵能直观看到哪些类别互相打架——我见过最典型的情况是深色烟雾和背景的混淆严重把远处树林的阴影当成了烟。用自己训练的权重进行推理from ultralytics import YOLO model YOLO(best.pt) results model.predict(sourcetest.jpg, conf0.35, iou0.5, saveTrue)这里conf0.35是我反复调试后的经验值。火焰我敢把阈值放到0.25烟雾必须放到0.4以上因为烟雾误报的概率远大于火焰。后面告警策略里我还会细说。5. 模型评估与优化让系统更贴合真实场景5.1 验证结果解读训练完成后在测试集上我得到了一组关键数据类别精确率(Precision)召回率(Recall)mAP50fire0.9340.8870.913smoke0.8720.7650.841全部0.9030.8260.877数值看起来不错但注意一个细节——烟雾的召回率明显偏低。这意味着有一批真实的烟雾目标约23%被漏检了。在消防场景中漏检的代价比误报高得多所以这个指标不能放过。我做了个错误样本分析发现问题主要集中在三个场景一是背景与烟雾颜色高度接近的情况比如灰白色浓烟在雾天背景下完全融入模型直接躺平。二是远距离的小目标烟雾在640x640的输入下一个20x20像素的烟雾区域确实很难分辨。这种场景可以考虑图像分块检测或SAHI切片推理把大图切成小块分别检测能有效提升小目标召回代价是推理时间倍增。三是透明薄烟肉眼能看到但标注时我自己都难以框选的区域。这种样本在标注阶段就被我处理掉了所以模型根本没学过自然检测不到。说实话这种场景即使人在监控室里也不一定能第一时间发现对模型的要求确实太高了。针对这几点能做的实际优化路径我测试过有效的有两个第一个优化是修改数据增强策略。在ultralytics自带的增强基础上我增加了随机亮度和对比度扰动幅度比默认值大20%。因为烟雾在强光和逆光环境下视觉特征差异很大提高光度扰动可以帮助模型学到更鲁棒的特征。第二个优化是调整类别损失权重。ultralytics支持传入cls参数但对类别的显式加权需要自己改loss.py给smoke类的损失乘一个1.2-1.5的系数。这能让模型更重视烟雾的学习否则模型会自然地偏向样本量更多、更容易学的火焰类。直接用YOLO训练配置改不了这个需要改源码。5.2 可视化推理与主观评估除了数字指标我强烈建议你亲眼看一批推理结果而不仅仅依赖mAP曲线。我设置了一个“主观验证流”选取几段有火焰烟雾的视频用训练好的模型逐帧跑推理然后人工以2倍速观看视频记录明显的漏检和误报。数字指标会骗人但你的眼睛不会。在这个环节里我发现一个很有意思的现象模型对视频中突然入镜的火源打火机火焰响应很及时但对已经有烟雾积累后出现的火焰反而会漏检——因为烟雾把火焰轮廓遮住了模型特征提取被干扰。这个情况在静态图片评估里完全看不出来只有在连续帧上才能发现。5.3 告警策略置信度阈值与连续帧确认系统落地到实际场景时最需要设计的是告警策略。直接用单帧结果告警会导致大量误报——摄像头晃动、灯光变化、飞虫掠过都可能产生一次高置信度误检。我采用的是连续N帧确认机制只有连续10帧约0.5秒中都检测到同一类目标时才触发告警。同时火焰和烟雾使用不同的置信度阈值火焰conf 0.3 即纳入候选因为它形状特征明显、误报率低烟雾conf 0.5 才纳入候选因为烟雾容易误检宁可漏报一些边界情况也要保证告警可信度这个策略实测下来能把误报率降低80%以上而真正的火情因为持续存在基本不会因为连续帧确认而被延迟发现。6. 部署落地把模型应用到实际摄像头6.1 ONNX导出与推理速度对比训练好的PyTorch模型要部署到实际环境最佳实践是导出为ONNX格式这样可以用ONNX Runtime或者TensorRT做加速推理。一行命令导出yolo export modelbest.pt formatonnx imgsz640导出的ONNX模型在Python里用ONNX Runtime推理CPU模式下和PyTorch的GPU推理速度差别不大。我还在Jetson Nano上测过TensorRT的FP16推理速度能跑到250ms左右一帧虽然算不上流畅但作为一个低功耗边缘设备已经可以接受。性能排序大概是TensorRT FP16 PyTorch GPU FP16 ONNX Runtime PyTorch CPU。如果你的部署环境是服务器直接用PyTorch推理就够了如果是边缘盒子TensorRT是首选。6.2 实时摄像头推理示例部署到摄像头的核心代码并不复杂。我Python实时流处理的骨架如下import cv2 from ultralytics import YOLO # 加载模型 model YOLO(best.onnx) # 打开摄像头0代表默认摄像头也可以换成RTSP流地址 cap cv2.VideoCapture(0) # 告警状态管理用于连续帧确认 fire_count 0 smoke_count 0 ALERT_THRESHOLD 10 # 连续10帧确认 while cap.isOpened(): success, frame cap.read() if not success: break # YOLOv8推理输入BGR帧模型内部会做预处理 results model(frame, conf0.3, imgsz640)[0] # 遍历检测结果分类处理 fire_flag False smoke_flag False for box in results.boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) name model.names[cls_id] # 不同类别使用不同置信度门槛 if name fire and conf 0.3: fire_flag True x1, y1, x2, y2 map(int, box.xyxy[0]) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.putText(frame, ffire {conf:.2f}, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) elif name smoke and conf 0.5: smoke_flag True x1, y1, x2, y2 map(int, box.xyxy[0]) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, fsmoke {conf:.2f}, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) # 连续帧确认逻辑 fire_count fire_count 1 if fire_flag else 0 smoke_count smoke_count 1 if smoke_flag else 0 if fire_count ALERT_THRESHOLD or smoke_count ALERT_THRESHOLD: cv2.putText(frame, ALERT!, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 255), 4) cv2.imshow(Fire/Smoke Detection, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这里面有两点我特别想解释为什么用results[0]ultralytics的predict接口返回的是一个Results列表每个元素对应一张输入图片。即使你只传了一张图也要用下标取出来。新手最容易在这上面踩坑。为什么imgsz640而不是更大输入分辨率越大小目标检测效果越好但推理延迟也越大。在实时场景下我宁可保证帧率也不追求极致精度。真需要高精度后期可以用分块检测做后处理。6.3 嵌入式设备部署思路如果你的目标是部署到Jetson Nano、树莓派这类嵌入式设备有两条路线路线一是换成YOLOv8nnano版本参数量只有s版的三分之一在树莓派4上CPU推理能跑到5-10FPS。这个速度做实时监控比较吃力但做定时巡检足够了——每10秒检测一帧发现异常再提高采样频率。路线二是用TensorRT做模型优化。Jetson系列对TensorRT有深度优化FP16推理速度比PyTorch原生快2-3倍。但TensorRT的安装和转换比较折腾需要根据Jetson的JetPack版本选择对应版本转换中常见的报错包括Unsupported layer type和reshape dimension mismatch大多数情况下更新到最新版就能解决。我个人的建议是如果你只是做个演示项目用ONNX Runtime部署就足够了简单稳定不用碰TensorRT这个深坑。7. 常见问题与排查技巧实录7.1 标注与数据相关Q: 标注框应该多大才算合适框要尽量贴紧目标边缘但不需要精确到像素级。尤其烟雾的边界本来就模糊稍微留一点边距可以接受。但注意别把大量背景框进去——如果框里面70%都是背景模型学到的是背景特征而非烟雾特征。Q: 火焰和烟雾同时出现时互相遮挡怎么办这是火焰烟雾检测里最麻烦的情况之一。我的建议是分别标注可见部分火焰被烟雾遮住一半就只标露出来的那一半烟雾层单独标注。模型不需要理解“这团烟下面藏着火”这种语义关系它只需要检测视觉可见的目标即可。7.2 训练相关Q: loss下降但mAP不涨是数据出问题了吗有几种可能过拟合了、学习率太低导致卡在局部最优、正负样本极度不均衡。我的排查方法是先看验证集loss——如果验证集loss在上升确认过拟合追加数据或增强如果验证集loss也在降但mAP不涨大概率是类别不均衡给稀缺类别加权重。Q: 训练时显存OOM怎么办优先降imgsz其次降batch最后再考虑梯度累积。注意YOLO训练时的Mosaic增强会消耗额外显存如果开了Mosaic导致OOM关掉它通常能省下30%的显存。Q: yolov8画损失函数曲线图是自动生成的吗是的训练过程中会自动保存results.png包含loss曲线和mAP曲线。它默认每轮epoch更新一次曲线。如果你想看更细粒度的信息可以开启plotsTrue参数会额外保存批次级别的分析图。7.3 推理部署相关Q: ONNX模型推理结果和PyTorch模型不一致差多少正常会有微小差异因为PyTorch的BatchNorm层在推理时用的是running statsONNX导出时做了常数折叠理论上完全一致。如果有明显差异检查输入图像的预处理方式——ultralytics内部有letterbox缩放逻辑如果你直接喂原始尺寸图给ONNX结果必然不对。Q: 摄像头推理时帧率太低怎么办从三个方向排查降低imgsz开FP16半精度推理启用批处理多个摄像头共用一批推理。如果还不行可能就是设备算力上限了考虑换更大的GPU或边缘推理加速芯片。Q: 检测到火焰时系统响应有多快在我的配置下单帧推理55ms告警确认需要连续10帧所以从火源出现到系统告警的延迟大约0.6秒。加上网络传输和画面渲染的延迟总体在1秒以内。这个响应速度对绝大多数消防应用来说都是足够的。7.4 我踩过的一个隐蔽坑最后分享一个我调试了很久的问题训练好的模型在图片测试上效果很好但在摄像头实时画面上疯狂误报。排查了很久发现是画面尺寸不一致导致的问题——我的训练图片大多是720p或1080p而摄像头的输出是480p分辨率下降后小目标的特征变得完全不同模型产生了大量错误检测。解决办法就是在推理时固定输入尺寸到640x640并且对摄像头做1080p采集。这个经验告诉我的一个道理训练数据和推理数据的分布一致性非常关键任何预处理差异都可能成为压垮模型效果的最后一根稻草。回头再看这个项目的整个链路——从数据标注到训练调参再到部署推理每一环都有独特的坑但核心始终是“把问题定义清楚、把数据准备好、把参数调合适”。YOLOv8提供了强大的模型骨架但真正决定项目成败的永远是你对业务场景的理解深度。这套系统后续还能扩展多摄像头并行检测、接入告警推送、添加视频回传等功能技术上都没有障碍就看你的具体需求了。本文还有配套的精品资源点击获取
返回列表