尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

YOLOv8火焰烟雾检测与RK3588边缘部署实战指南

YOLOv8火焰烟雾检测与RK3588边缘部署实战指南 YOLOv8做火焰和烟雾检测这个方向我断断续续折腾了大半年从刚开始用官方权重跑DEMO到后面自己标注数据、调参、在RK3588上部署中间踩过的坑比想象中的多得多。说实话火焰和烟雾检测这件事看着简单实际做起来比常规的目标检测要麻烦不少因为火焰的形态变化大、颜色不稳定烟雾又是半透明且边缘模糊的很多在COCO数据集上表现很好的模型到这种场景里直接翻车。这篇文章我打算把所有关键环节都串一遍从环境配置、数据集标注到训练参数、Loss曲线分析再到模型导出和RK3588边缘部署全部按实际操作的顺序来写。不管你是准备用GTX1660Ti这种老旧显卡跑YOLOv8还是想在自己的设备上做实时烟火识别这篇文章应该都能给你一些参考。1. 为什么火焰和烟雾检测偏偏要选YOLOv81.1 烟火识别的场景需求和难点在哪先理清楚应用场景。火焰和烟雾检测最常见的落地场景大概有这么几类森林防火预警、仓库和工厂的安防监控、加油站和化工厂等危化区域监测还有一些是小区楼道、电动车棚的消防预警。这些场景的共同特点是摄像头角度固定、背景相对稳定但检测目标的形态变化非常大。难点主要有三个。第一火焰的纹理是高度非刚性的没有什么稳定的几何特征形状随时在变颜色也从橙红到亮黄不定单纯靠传统图像处理里的颜色阈值或者帧差法误检率极高。第二烟雾没有明确的轮廓是半透明的边缘非常模糊而且颜色和很多背景接近比如灰白色的墙壁、雾霾天、蒸汽都很容易让模型产生误判。第三昼夜光线差异大火光在夜间的特征和白天完全不同烟雾在逆光、背光场景下的可辨识度也很低。这些都意味着如果用传统方法或者很浅的网络去做几乎不可能达到实用级。YOLOv8在速度和精度的平衡上做得不错加上它直接把训练、验证、导出、部署的流程压缩成了一套命令这种工程上的便利性对于做安防项目的人来说其实是最大的吸引力。1.2 对比之前常用的检测方案YOLOv8的赢面在哪早几年大家都习惯用Faster R-CNN或者SSD做烟火检测Faster R-CNN精度是还行但部署到边缘设备上帧率根本上不去SSD速度快小目标又特别容易漏检而火焰和烟雾的初始形态往往就是小目标。后来YOLOv5出来一阵子解决了不少问题但到了YOLOv8变化其实更彻底。一个很直观的变化是YOLOv8把模型的Head部分从原来的耦合检测头改成了Decoupled-Head也就是分类和回归各自走一个分支这让训练的收敛更稳定对火焰烟雾这种分类边界模糊的目标更友好。另一个是Anchor-Free的检测方式不再需要预设锚框尺寸因为火焰的宽高比实在不固定用固定锚框有时候会很难受。C2f模块替换了原来的C3等于把特征复用做得更深对小目标的信息保留也更好。我自己的体会是YOLOv8对于中低端显卡的利用率也比YOLOv5好一点同样训练一个火焰烟雾模型在数据量不多的情况下YOLOv8更容易收敛。另外Ultralytics官方把导出ONNX、TensorRT、RKNN的配套流程做得非常顺这对后面要接RK3588这种设备的项目来说省了非常多时间。不是因为YOLOv8是最新的就选它而是烟火检测这个任务本身恰好需要它这种特性组合。2. 环境准备和YOLOv8工程初始化2.1 GTX1660Ti到底能不能训练烟火模型训练火焰和烟雾模型大部分人手里的显卡都不会太好尤其是学生或者中小型项目团队GTX1660Ti算是非常常见的了。先给个结论GTX1660Ti有6GB显存跑YOLOv8n和YOLOv8s没问题跑YOLOv8m需要非常小心地控制batch size和图片尺寸YOLOv8l基本别想好好训练。我自己那台机器就是GTX1660Ti 6GB显存刚开始还很担心训练不了后来实测下来用YOLOv8s加上640x640输入分辨率batch size设成8显存占用大概在4.5GB左右可以正常训练。如果换成batch size16大概率会爆显存除非你开梯度累积。火焰和烟雾检测的数据集一般不会特别大两三千张图训练一轮也就几分钟到十几分钟完全可以接受。所以如果你也是1660Ti别慌YOLOv8s就是最合适的选择。有一点必须提醒显卡驱动和CUDA版本要提前搭配好。GTX1660Ti虽然是老卡但支持很全建议直接上CUDA 11.8加PyTorch 2.0以上的版本不要用太老的PyTorch因为Ultralytics新版本的很多算子需要新版PyTorch支持。我装的时候就是先装的CUDA再装对应版本的PyTorch顺序反了容易出现装了也用不了GPU的情况。2.2 conda环境配置和YOLOv8官方库的安装细节环境配置这块网上的教程很多版本混乱我把自己验证过的一套流程写在这里。我用的是Anaconda管理环境Python版本3.9CUDA 11.8PyTorch 2.1.0Ultralytics 8.2.x。具体操作步骤大概是这样的conda create -n yolofire python3.9 conda activate yolofire pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics装完以后可以运行一下yolo命令如果能正常显示版本信息就说明基础环境没问题。官方库其实是建议直接从Git仓库拉最新的release版本但我更建议用pip装稳定版一个原因是稳定版经过验证另一个原因是后续如果要跑RKNN转换某些第三方工具对最新代码的兼容性反而不好。第一次跑YOLOv8训练之前最好先下载官方预训练权重。别一上来就用随机权重训练火焰烟雾检测你的数据集可能就几千张从零训练很容易欠拟合而且训练时间会拉长很多。直接在训练命令里加上pretrainedTrue程序会自动下载YOLOv8s.pt或者你指定的预训练模型。国内网络情况大家心里有数如果下载一直失败就去把权重手动下载好放进项目目录路径设为weights/yolov8s.pt这样省心很多。2.3 拉通官方验证流程先跑一次老数据集环境配好以后我强烈建议先别急着训练自己的数据先用官方模型和COCO验证集或者随手拍的照片跑一次推理确认整个流程是通的。命令很简单比如yolo predict modelyolov8s.pt sourcetest.jpg这一步要确认的事情有三个GPU有没有被跑起来、模型推理是否正常、输出的图片标注效果是否符合预期。如果这一步正常说明你的环境、显存、驱动都没有问题。接着再跑一次官方数据集的验证流程yolo detect val modelyolov8s.pt datacoco8.yaml这个可以快速验证你是不是正常调用了CUDA。很多新手在训练自己的数据前没做过这一步结果一训练就报各种奇怪的错最后才发现是环境没配对。3. 火焰和烟雾数据集准备与标注策略3.1 数据从哪里来收集多少张才够用火焰和烟雾检测这种垂直领域不可能指望像COCO那样有现成的通用数据集市面上有一些公开的烟火数据集比如Bilkent University的火灾数据集、一些Kaggle上的fire and smoke数据集但数量参差不齐而且很多图像分辨率很低直接用来训练效果有限。最靠谱的做法是公开数据集打底再加自己采集的数据。公开数据集一般能提供一千到三千张图作为基础素材。但真正的训练效果提升往往来自自己采集的截图和网络视频抽帧。我自己会从一些火灾新闻视频、消防演练视频里抽帧再把监控摄像头拍的夜晚场景、烟雾报警测试场景都纳入进来。火焰和烟雾检测对数据多样性要求很高至少要把白天、夜晚、逆光、远距离小目标、近距离大目标、不同背景材质这几类都覆盖到。具体数量的话我的建议是不要少于1500到2000张每张图里目标数量可以是多个这样比相同数量但单目标的图要好很多。我最终训练用的数据集是4200多张图火焰目标大约8000个烟雾目标大约7000个实际效果已经比较稳定了。数据贵在精不在多如果样本都是同一个角度同一个场景那10000张也不如人家2000张多样性强。3.2 标注盒子的边界怎么画烟火标注的独有技巧标注工作我用的LabelImg简单直接。但是火焰和烟雾的标注规则和普通目标有很大区别这也是最容易让新手走弯路的地方。火焰的标注很多人喜欢把整个火焰外沿包进去结果标注框里一半是被照亮的背景。我的经验是火焰的标注框应该尽量贴合“高温发光区”也就是颜色最亮、最浓的部分。因为火焰的外部其实是很淡淡的红色边缘如果框太大了模型学到的特征是“亮区域大片的橙色”一旦灯光、夕阳场景出现就容易误检。烟雾的标注更烦因为烟雾没有边界人眼都很难判断到哪里算烟、哪里不算。我的标注原则是抱住“肉眼可辨识的烟雾核心区域”那些稀薄的、半透明的边缘一律不纳入这样模型学到的特征会更聚焦在有辨识度的纹理和形状上。另外一张图里如果同时有大片烟雾和火焰核心我通常把烟雾框画得保守一点避免和火焰框严重重叠。标注的时候还要注意一点不要框出“假阳性”区域。比如一个黑色的烟囱在冒白烟如果烟和云的边界很模糊就别硬标宁可漏标也不要错标因为错标会直接教模型把云当烟。3.3 数据清洗和增强策略宁可少不可乱数据清洗这块容易被忽略但极其重要。公开数据集里经常会混入相似任务的数据集有的图片标注的是森林背景但没有火有的烟雾图其实是雾霾这些脏数据如果不清理训练出来的模型就会出现很奇怪的误检。我的做法是数据收集回来后先用一个简单的分类逻辑筛一遍凡是肉眼都分不清的图直接删掉。增强策略上我推荐优先使用mosaic和mixup尤其是mosaic对火焰烟雾检测很有帮助。因为mosaic会把四张图拼起来等于强制让模型去学习小目标和多目标场景正好补齐了烟火初始阶段往往是小目标这个短板。我自己训练时开了mosaic概率0.8scale augmentation开到0.5效果比关掉增强高了好几个点的mAP。需要提醒的是火焰和烟雾检测不需要太多的色彩类增强比如色调变化、亮度变化可以开一点但饱和度不要乱调。因为火焰有个很强的特征是它的颜色如果把颜色随变增强开得太大模型就学不到“橙红色偏亮”这个关键特征了夜间火焰的颜色特征也会被削弱。对比度和亮度增强适度开一些就够了。4. 模型选型、训练参数调优与Loss曲线解读4.1 YOLOv8n/s/m烟火场景到底选哪个版本YOLOv8官方提供了n、s、m、l、x五个主力版本区别主要体现在网络宽度和深度上也就是参数量和计算量。它们的体积和速度差异很直观参数从n的300多万到x的6800多万模型文件从6MB到130MB不等推理速度也相差好几倍。火焰和烟雾检测的目标不像行人检测那样需要区分出极其细微的类别但它难在特征不够刚性。所以我建议如果你的部署设备算力够至少要用YOLOv8s起不要用n。YOLOv8n在复杂场景下对烟雾这种弱纹理目标会明显漏检特别是距离远、目标小的时候。如果是GTX1660Ti训练YOLOv8s是最折中的选择训练速度能接受精度也够用。如果设备算力很富余可以尝试YOLOv8m但我自己比较过在烟火这个任务上s和m的精度差距没有想象中那么大有时候s调好参数反超m。4.2 训练命令参数详解手把手教你怎么设先给一个我在GTX1660Ti上实际用过的训练命令模板数据集结构在后面会讲到yolo detect train \ modelyolov8s.pt \ datafire_smoke.yaml \ imgsz640 \ batch8 \ epochs200 \ lr00.01 \ lrf0.01 \ momentum0.937 \ weight_decay0.0005 \ optimizerSGD \ augmenttrue \ seed42这里面的参数我逐个说下我的实际经验。imgsz640是默认值也是精度和显存消耗的平衡点1660Ti完全能跑。如果只用单目标检测可以考虑调到800多火焰烟雾场景建议保持640太小了细节不够太大了训练时间翻倍且收益有限。batch8是6GB显存的极限值如果你跑的时候爆显存调低到4同时可以开amptrue用混合精度训练来省显存。epochs200看着多其实火焰烟雾数据集如果只有两三千张模型到大概120轮左右就基本稳定了。不过建议还是设200早停机制本来就能帮你判断什么时候不用再训。如果没有设定早停策略就用看Loss曲线的方式判断。lr00.01是官方默认值一般来说不用动如果你的数据集比较小调到0.005会更稳定防止前几个epoch损失爆炸。数据集配置文件fire_smoke.yaml的格式是这样的很简单但是关键train: /path/to/fire_smoke/images/train val: /path/to/fire_smoke/images/val names: 0: fire 1: smoke nc: 2注意路径最好用绝对路径。训练过程中程序不会帮你检查路径对不对如果路径错了它会直接报错找不到数据集。另外nc必须和names里的类别数一致这个没问题但如果你是从别人的项目里改的一定要确认标签文件里的class id没有超过类别数。4.3 Loss曲线怎么看网络结构图到底有什么用YOLOv8训练过程中我一般会同时盯着三个东西box_loss、cls_loss、dfl_loss。很多教程一上来就是贴一张训练日志说你看损失降下来了其实光看这几个数字不够我更推荐在训练过程中把plotsTrue打开它会自动生成一堆曲线图包括loss曲线、PR曲线、F1曲线以及验证集上的预测样例图。Loss曲线的正常形态是前10个epoch快速下降之后进入缓慢下降阶段最终趋于平稳。如果你的曲线是断崖式上升然后再降下来那大概率是学习率设置太大或者标签出了问题。如果前50个epoch还在高位震荡不下降先检查数据集是不是打错了或者增强策略是不是太激进。网络结构图这个东西很多人觉得是锦上添花其实不是。YOLOv8的结构图你用官方模型权重配合工具就能画出来大概能看到Backbone、Neck、Head三部分的堆叠方式。看网络结构图的目的不是背网络而是知道你的目标特征在哪个层级被提取。比如火焰烟雾检测里小目标多你就可以重点关注Neck部分的特征融合层确认模型在P3、P4、P5三个尺度上的输出在配置里是否正常。用yolo export modelyolov8s.pt formattorchscript导出的模型再配合netron工具能直接看到各层的输入输出尺寸排查预处理尺寸是否对得上的时候相当有用。5. 模型评估与实景测试5.1 mAP、Precision、Recall这些指标怎么用于烟火模型训练完以后很多人只看一个mAP数字其实在烟火场景里Precision和Recall的平衡比mAP更重要。你要想清楚一个根本性的问题你的系统宁可误报还是宁可漏报如果是消防预警系统大概率宁可误报也不能漏报因为漏一次火的代价太大了。所以我在评估烟火模型时重点看Recall是否足够高尤其是小目标类别的Recall。YOLOv8训练结束时会在验证集上直接输出各类别的mAP50、mAP50-95、Precision、Recall。我的一般标准是mAP50要大于0.85Recall要大于0.8Precision大于0.9。如果你的Recall很低说明模型有很多烟火目标没检测到这对安防场景很不友好。还有一个容易被忽略的点烟雾类比的Recall通常比火焰低。这是很正常的因为烟雾本身就模糊但你要特意关注这个值。如果烟雾的Recall比火焰低很多往往是数据集中烟雾标注不一致导致的而不是模型结构问题。5.2 视频流测试时你一定会遇到的几个真问题模型训练完以后拿去测试视频流或者监控画面才会暴露真正的工程问题。第一个问题是“闪烁”也就是某个目标前几帧有框后几帧没框再隔几帧又出现。这种情况说明模型的置信度刚好在阈值附近波动。解决方法不是继续提高阈值而是引入时序过滤逻辑比如连续三帧都检测到才输出结果或者对检测结果做简单的卡尔曼滤波平滑。第二个问题是目标检测框的大小不连续上一帧框住整个火焰下一帧只框住中间的高亮部分。这个除了调置信度阈值以外还可以考虑用更强的NMS参数或者把分类置信度和IoU阈值配合起来调整让框更稳定。第三个问题特别隐蔽就是“同步时间的错位”。如果你用OpenCV读视频流再配合YOLO推理摄像头本身的缓冲会让画面延迟越来越大。不要小看这个延迟做实时烟火预警延迟两三秒可能没什么延迟十秒问题就大了。建议用队列加丢帧策略只处理关键帧保证延迟可控。我在实际项目中是抽帧检测比如每秒处理5帧既保证响应速度也控制边缘设备的负载。5.3 导出ONNX模型和TensorRT加速的取舍验证完效果后如果只是本地跑一跑PyTorch模型就够了。但如果要部署到服务器上做高并发检测或者跑在边缘设备上就必须要做模型导出。最常用的两种格式是ONNX和TensorRTONNX是中间格式TensorRT是英伟达GPU上的专用推理优化格式。导出ONNX很简单yolo export modelbest.pt formatonnx opset12导出来的model.onnx可以用onnxruntime直接跑CPU推理或者GPU推理。我在服务器上测试时用ONNX Runtime加上GPU推理速度比PyTorch原生快30%以上。TensorRT则更快但配置过程麻烦尤其是在低版本显卡驱动的机器上坑特别多。如果是GTX1660Ti也能用TensorRT但提升没有新款显卡明显我建议先把ONNX流程跑通再考虑TensorRT。还有一个在导出时必须注意的问题就是输入尺寸和动态维度的选择。如果部署场景的输入尺寸固定导出时直接把尺寸固定比如imgsz640这样模型尺子固定后TensorRT的优化空间更大。如果需要适配不同分辨率就要开启动态轴但这样TensorRT优化会打折扣推理速度变慢。6. 在RK3588上部署YOLOv8火焰烟雾模型的完整流程6.1 为什么选择RK3588作为边缘算力平台好了训练和服务器端推理都验证过了真正的项目落地往往要求你上边缘设备。很多客户只愿意在内网部署不能离开他们的机房环境所以你不能指望每个现场配一块昂贵的GPU相比之下RK3588这类国产边缘设备才是主流方案。RK3588是瑞芯微推出的高性能SoC集成了6 TOPS算力的NPU可以同时跑多路视频流的目标检测任务而整板功耗比一张独立显卡低太多。正点原子有块基于RK3588的开发板网上相关资料比较全Python推理流程跑起来也方便。我这边选的也是RK3588最终用YOLOv8s量化后模型在NPU上跑单路1080p视频推理延迟大概在30到50毫秒之间完全满足实时性要求。6.2 模型转换全流程从PyTorch到ONNX再到RKNNRK3588的NPU不认识PyTorch模型也不直接运行ONNX它需要通过瑞芯微的rknn-toolkit2工具链把模型转换成RKNN格式。整个转换链路是PyTorch模型转ONNXONNX转RKNN最后在板子上加载RKNN模型进行推理。转换前需要先在PC上安装rknn-toolkit2注意它的Python版本和依赖和Ultralytics版本不一定兼容所以我干脆用虚拟环境分开一个是训练环境一个是RKNN转换环境。转换过程的核心代码如下from rknn.api import RKNN rknn RKNN() rknn.config( mean_values[[0, 0, 0]], std_values[[255, 255, 255]], target_platformrk3588 ) rknn.load_onnx(modelfire_smoke.onnx) rknn.build(do_quantizationTrue, datasetdataset.txt) rknn.export_rknn(fire_smoke.rknn)这段代码里面的几个参数我要重点解释一下。mean_values和std_values必须和YOLOv8训练时的数据预处理保持一致。YOLOv8默认的预处理就是把像素值除以255所以mean0std255这个对应关系如果错了模型输出会全部乱掉框全飘到天上。do_quantizationTrue是把模型从FP16量化为INT8这个能大幅提高NPU推理速度和降低内存占用但代价是精度略微下降烟火检测这种目标仍然可以接受。6.3 RK3588上的推理代码骨架和性能实测在板子上加载RKNN模型推理跟PyTorch的推理逻辑差异很大需要自己处理缩放、坐标映射、NMS这些逻辑。RKNN官方自带YOLO系列的后处理示例但版本和API变化比较快我自己的经验是不要完全照抄至少要把坐标还原部分重新写一遍。核心的推理代码骨架是这样import numpy as np from rknnlite.api import RKNNLite rknn RKNNLite() rknn.load_rknn(fire_smoke.rknn) rknn.init_runtime() img cv2.imread(test.jpg) img_resized cv2.resize(img, (640, 640)) img_input img_resized[:, :, ::-1].transpose(2, 0, 1) # BGR转RGB并转CHW img_input np.expand_dims(img_input, axis0).astype(np.float32) img_input img_input / 255.0 outputs rknn.inference(inputs[img_input])推理完成后得到的outputs还需要按照YOLOv8的head输出格式解码做置信度过滤和NMS。这块我也会踩坑主要是YOLOv8的输出布局在不同版本的导出中略有差异有的会直接输出decoded结果有的输出原始feature map。最好的方式是拿一张已知结果的图片先跑一遍拿输出尺寸去对照模型结构不要靠猜。RK3588部署完成后我测试的结论是YOLOv8s-int8单路视频推理大约30ms左右双路同时跑也能控制在60ms以内CPU占用率在20%上下。这个水平用于烟火预警相当够了如果再叠加多路视频流只要拉开处理间隔不追求每帧都检测稳定跑四路以上没有太大问题。7. 常见问题与排查技巧实录7.1 Loss不降、显存爆掉、权重下载失败这些问题怎么解经常有朋友在群里问我训练的时候Loss一直不降怎么回事。我一般先问三个问题第一个是标签是否正确如果标签文件全空或者class id越界Loss曲线绝对不正常第二个是学习率是否过大尤其在小数据集上默认0.01可能偏大降到0.005试试第三个是数据增强是否太极端mosaic打开时如果图片尺寸太小有时会把目标裁没了。显存爆掉的解法相对直接先调小batch size到4再开ampTrue还不够就把imgsz从640降到512再不行就换小模型。GTX1660Ti上如果batch8就爆排除显存占用被其他程序吃掉的情况基本是显卡问题认命用batch4就行。权重下载失败这个事网上很多教程让你去镜像站下载。我自己的经验是先从官方releases页面直接下载对应.pt文件放到项目目录下然后在训练时指定绝对路径一劳永逸。比反复自动下载要靠谱得多。7.2 火焰烟雾误检和漏检的针对性调优思路很多人在模型部署以后发现模型把红色的汽车尾灯、夕阳下的红色云彩、甚至红色衣服当成了火焰把雾霾和蒸汽当成了烟雾。这种误检很烦但也不能全怪模型因为烟火特征本身就和这些场景相似。针对火焰误检我用的方法是收集一批典型的强干扰负样本比如红色灯光、红色旗帜、夕阳、晚霞、红色车身的车辆放进一个单独的负样本文件夹然后通过训练配置把它们一并纳入训练集。YOLOv8的标签里没有负样本这一说但你可以建一个没有标签的图片文件夹与有标签的图片混合训练模型就会学到这些背景不是目标。针对烟雾误检重点调整验证集和训练集的背景多样性。烟雾误检往往集中在特定背景上比如雾天的远山、蒸汽管道、厨房水汽。把这些背景图加进去再配合增加烟雾本身的数据模型会逐步学会区分。另外还可以调整类别置信度阈值比如对烟雾单独用一个高一点的阈值比如0.35火焰用0.25。YOLOv8支持按类别设置阈值的话就尽量用上不支持的话可以在后处理阶段手工实现。7.3 部署后的一些工程避坑建议最后讲几个部署后容易忽视的小坑。第一个是摄像头图像流的分辨率不要直接喂给模型如果摄像头是2592x1944你直接把整帧缩到640x640会导致远处的小火焰完全丢失。更好的做法是在原图上做Region of Interest截取对关键区域单独放大检测或者把输入尺寸提升到960的同时开启多尺度训练。我实际项目中就是先做人形区域ROI再检测误检和漏检都下降不少。第二个是模型的启动加载时间。RKNN模型在板上第一次初始化runtime时需要加载一些设备配置有时候第一次推理特别慢甚至要好几秒。这个不是故障是NPU初始化的正常现象项目上线时要在代码里做预热检测也就是启动时跑一张空白图后面的延迟才会稳定下来。第三个是日志和告警的输出机制。火焰和烟雾系统不像物体检测Demo检测到框就完了它必须要有告警联动。我的做法是把检测结果同时写入消息队列和本地数据库满足连续多帧条件后再触发告警避免误报被频繁上报。按照这套流程做下来从环境配置到RK3588部署整个链路基本能跑通。我个人实操后的体会是模型训练其实只占整个项目工作量的三成数据和部署的细节才是最磨人的尤其是RK3588转换和后处理部分多花点时间把每个环节测透后面维护起来会省心很多。
返回列表