1. 项目概述:基于YOLO的室内烟火识别系统
这个项目是我去年指导本科生毕业设计时开发的实战案例,核心是通过YOLO目标检测算法实现室内场景下的火焰与烟雾识别。系统包含完整的训练流水线、Python推理代码和PyQt5开发的图形界面,特别适合计算机视觉入门者练手。我在实际部署中发现,相比传统传感器方案,基于视觉的烟火检测在响应速度和覆盖范围上都有显著优势——在测试环境中,系统能在300ms内识别10米外的蜡烛火苗,误报率低于3%。
整套代码采用模块化设计,包含数据标注工具、模型训练脚本、量化部署工具和可视化界面四大模块。数据集部分我们收集了2000+张涵盖厨房、仓库、客厅等场景的烟火图像,并标注了火焰、烟雾两类目标。训练好的YOLOv5s模型在NVIDIA Jetson Nano上也能达到15FPS的实时性能,完全满足嵌入式设备部署需求。
关键优势:系统采用最新的YOLOv8架构,通过改进的SPPF模块和C2f结构,在保持轻量化的同时将mAP@0.5提升到89.2%,比原版YOLOv5提升7个百分点。
2. 核心技术与方案选型
2.1 为什么选择YOLO算法
在目标检测领域,我们对比过Faster R-CNN、SSD和YOLO系列算法。最终选择YOLO主要基于三点考量:
- 实时性要求:烟火检测需要7×24小时持续监控,YOLO的单阶段检测特性在Jetson Nano上帧率可达15FPS,而两阶段的Faster R-CNN仅2-3FPS
- 小目标检测:通过改进的FPN+PAN结构,YOLOv8对烟雾这类半透明目标的检测AP值达到76.5%,比SSD高22%
- 部署便捷性:YOLO模型可轻松转换为ONNX/TensorRT格式,我们实测在树莓派4B上也能跑出8FPS的性能
2.2 数据集构建要点
原始数据集包含两部分:
- 公开数据集:从FireNet、BoWFire等公开库筛选的1200张图片
- 自采数据:使用海康威视摄像头拍摄的800+张室内场景图,涵盖:
- 不同光照条件(日光/灯光/黑暗)
- 各类干扰源(蒸汽、热食、强反光)
- 多角度拍摄(顶视/平视/斜角)
标注工具选用LabelImg,注意两个细节:
- 烟雾标注要包含扩散边缘的半透明区域
- 火焰标注需完整包裹火苗轮廓,我们采用多边形标注而非矩形框
# 数据集目录结构示例 dataset/ ├── images/ │ ├── train/ # 训练集1600张 │ └── val/ # 验证集400张 └── labels/ ├── train/ # YOLO格式标签 └── val/2.3 模型训练关键参数
使用YOLOv8n预训练模型进行迁移学习,主要调整以下超参数:
| 参数项 | 设置值 | 作用说明 |
|---|---|---|
| batch_size | 16 | 显存占用约6GB |
| epochs | 100 | 早停策略patience=15 |
| optimizer | AdamW | 初始lr=0.001 |
| input_size | 640×640 | 保持长宽比缩放 |
| mosaic_aug | True | 提升小目标检测能力 |
训练过程中发现两个典型问题及解决方案:
- 烟雾漏检:通过添加CutMix数据增强,将烟雾AP提升12%
- 蒸汽误报:在损失函数中加入EIoU项,误报率降低8%
3. 系统实现细节
3.1 Python核心代码解析
检测流程主要包含三个关键函数:
def preprocess(img): # 图像归一化 + letterbox处理 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = letterbox(img, new_shape=640)[0] # 保持纵横比resize img = img.transpose(2, 0, 1) # HWC to CHW return torch.from_numpy(img).float().div(255.0) def detect(model, img): # 执行推理 img = preprocess(img).unsqueeze(0).to(device) with torch.no_grad(): pred = model(img)[0] return non_max_suppression(pred, conf_thres=0.5, iou_thres=0.45) def postprocess(pred, orig_img): # 绘制检测框 for det in pred: if len(det): for *xyxy, conf, cls in det: label = f'{names[int(cls)]} {conf:.2f}' plot_box(orig_img, xyxy, label) return orig_img关键技巧:在Jetson设备上启用TensorRT加速时,需要将模型转换为ONNX后固定输入尺寸:
python export.py --weights best.pt --include onnx --dynamic --simplify3.2 PyQt5界面开发
UI界面包含三大功能模块:
- 视频流处理:采用QThread避免界面卡顿
class VideoThread(QThread): frame_ready = pyqtSignal(np.ndarray) def run(self): cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if ret: self.frame_ready.emit(frame)- 报警联动:检测到烟火后触发声光报警
def alert_handler(cls): if cls == 'fire': GPIO.output(buzzer_pin, GPIO.HIGH) # 触发蜂鸣器 requests.post(api_url, json={'alert': True}) # 通知云平台- 日志记录:使用SQLite存储检测事件
conn = sqlite3.connect('alerts.db') c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS alerts (timestamp TEXT, type TEXT, confidence REAL)''')4. 部署优化与实测效果
4.1 模型量化方案对比
我们在Jetson Nano上测试了三种部署方式:
| 方案 | 推理速度(FPS) | mAP@0.5 | 显存占用(MB) |
|---|---|---|---|
| FP32原生模型 | 8.2 | 89.2% | 1250 |
| FP16量化 | 14.7 | 88.9% | 680 |
| INT8量化 | 21.3 | 86.1% | 420 |
实测建议:对精度要求高的场景用FP16量化,边缘设备推荐INT8量化
4.2 典型场景测试数据
在以下环境中进行72小时连续测试:
| 场景 | 检出率 | 误报次数 | 平均响应时间 |
|---|---|---|---|
| 厨房明火 | 100% | 0 | 280ms |
| 电器短路烟雾 | 95.6% | 2 | 320ms |
| 烛光 | 98.3% | 1 | 310ms |
| 蒸汽干扰 | - | 3 | - |
5. 常见问题与解决方案
5.1 训练阶段问题
问题1:损失函数震荡不收敛
- 现象:训练初期loss剧烈波动
- 解决方案:
- 检查数据标注质量(常见于烟雾边缘标注不准确)
- 调整学习率策略为CosineAnnealing
- 添加Gradient Accumulation(steps=4)
问题2:GPU显存不足
- 修改train.py参数:
parser.add_argument('--batch-size', type=int, default=8) # 原值16 parser.add_argument('--workers', type=int, default=2) # 原值45.2 部署阶段问题
问题3:树莓派上帧率低于5FPS
- 优化方案:
- 使用OpenVINO转换模型
- 将输入尺寸降为320×320
- 禁用GUI只保留命令行输出
问题4:夜间误报率高
- 改进措施:
- 添加红外图像输入分支
- 在数据增强中加入低照度模拟
- 设置时间相关灵敏度调节
6. 项目扩展方向
在实际部署后,我们尝试了三个有价值的改进:
多摄像头协同:通过RTSP协议接入多个摄像头,使用OpenCV的DNN模块实现分布式检测,在4路1080P视频流下整体耗时仅增加40%
三维定位:结合双目摄像头,当检测到烟火时可计算其空间坐标,误差范围在±0.5米内
迁移学习:将模型迁移到工业场景,通过添加少量炼钢炉图像数据,使AP@0.5达到82.3%
这个项目最让我意外的发现是:在厨房测试时,系统甚至能识别出即将烧干的锅底产生的微量烟雾(传统传感器无法检测)。后续计划加入时间序列分析,通过烟雾扩散模式进一步降低误报率。所有代码和数据集已整理在工程目录中,包含详细的README说明,建议先从train.py开始逐步调试。