大家好,我是Java1234_小锋老师,分享一套锋哥原创的基于YOLO26的火焰烟雾目标识别(火灾监控预警)系统(FastAPI+Vue3)。

项目介绍
火灾是工业厂房、仓储场所和公共建筑中破坏力很强的一类事故。火焰和烟雾出现得越早,可用于疏散和扑救的时间就越充分。传统烟感、温感探测器依赖烟气浓度或温度升高,在大空间、通风强烈或火灾初期往往响应偏慢。视频监控已经广泛部署,如果能直接从画面中识别火焰和烟雾,就可以把现有摄像机变成预警传感器。
本文设计并实现了基于YOLO26的火焰烟雾目标识别(火灾监控预警)系统。系统以Python为主要开发语言,使用FastAPI提供后端接口,使用Vue3构建管理端页面,使用MySQL保存用户、模型、检测记录、告警和日志。识别能力由Ultralytics接口加载的YOLO26权重提供,支持图片、视频和浏览器实时画面三种输入。检测结果写入数据库后,再按类别和置信度阈值生成告警,并关联火灾处置知识。
论文完成了需求分析、总体架构、功能结构、数据库概念结构与逻辑结构、主要业务时序以及各功能模块的实现。数据库采用以db_为前缀的库名和以t_为前缀的表名,给出了九张业务表的字段名、类型、长度、是否为空和备注。系统实现部分结合登录注册、个人中心、图片识别、视频识别、实时检测、告警、记录查询、模型管理和统计分析,给出了与工程代码一致的核心片段。
在本机训练记录中,以yolo26n为初始权重、输入尺寸640、批大小16、训练5个周期后,验证集精度约为0.599,召回率约为0.483,mAP50约为0.512。该结果说明检测流程已经打通,同时也说明短周期微调还不能当作高可靠的现场报警器。系统把模型文件与业务代码分开管理,后续可以在不改接口的情况下替换更充分训练的权重。
源码下载
链接: https://pan.baidu.com/s/1hRykcLMBDM3VcM7cDLPRFQ?pwd=1234
提取码: 1234
系统展示








核心代码
"""根据告警规则生成告警记录。"""
from datetime import datetime, timedelta
from typing import Optional
from sqlalchemy.orm import Session
from app.models.alarm import Alarm, AlarmRule
from app.models.detect import DetectDetail
def match_and_create_alarms(db: Session, record_id: int, details: list[DetectDetail], dedup_seconds: int = 0) -> list[Alarm]:
"""
将检测明细与告警规则匹配,命中则写入告警表。
Args:
db: 数据库会话
record_id: 检测记录ID
details: 检测明细列表
dedup_seconds: 实时检测去重间隔,0 表示不去重
Returns:
新产生的告警列表
"""
rules = db.query(AlarmRule).filter(AlarmRule.enabled == 1).all()
rule_map = {r.class_id: r for r in rules}
created: list[Alarm] = []
for detail in details:
rule = rule_map.get(detail.class_id)
if rule is None:
continue
conf = float(detail.confidence or 0)
if conf < float(rule.conf_threshold):
continue
if dedup_seconds > 0:
since = datetime.now() - timedelta(seconds=dedup_seconds)
exists = (
db.query(Alarm)
.filter(Alarm.class_name == detail.class_name, Alarm.alarm_time >= since)
.first()
)
if exists:
continue
alarm = Alarm(
record_id=record_id,
detail_id=detail.id,
class_name=detail.class_name,
confidence=conf,
alarm_level=rule.alarm_level,
alarm_time=datetime.now(),
status="未处理",
)
db.add(alarm)
created.append(alarm)
if created:
db.flush()
return created
<template>
<div class="page-card">
<div class="search-bar">
<el-input v-model="keyword" placeholder="火焰/烟雾" clearable style="width: 200px" />
<el-select v-model="status" placeholder="状态" clearable style="width: 140px">
<el-option label="未处理" value="未处理" />
<el-option label="已处理" value="已处理" />
<el-option label="已忽略" value="已忽略" />
</el-select>
<el-select v-model="alarmLevel" placeholder="等级" clearable style="width: 120px">
<el-option label="高" value="高" />
<el-option label="中" value="中" />
<el-option label="低" value="低" />
</el-select>
<el-button type="primary" @click="load">查询</el-button>
<el-button @click="batch('已处理')">批量处理</el-button>
<el-button @click="batch('已忽略')">批量忽略</el-button>
</div>
<el-table :data="list" style="width: 100%" @selection-change="sel = $event">
<el-table-column type="selection" width="48" />
<el-table-column prop="id" label="ID" min-width="70" />
<el-table-column prop="class_name" label="目标类别" min-width="180" show-overflow-tooltip />
<el-table-column prop="confidence" label="置信度" min-width="90" />
<el-table-column prop="alarm_level" label="等级" min-width="80">
<template #default="{ row }">
<el-tag :type="row.alarm_level === '高' ? 'danger' : row.alarm_level === '中' ? 'warning' : 'success'">{{ row.alarm_level }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" min-width="90" />
<el-table-column prop="alarm_time" label="告警时间" min-width="170" />
<el-table-column prop="handler_name" label="处理人" min-width="100" />
<el-table-column prop="handle_remark" label="备注" min-width="140" show-overflow-tooltip />
<el-table-column label="操作" min-width="160" fixed="right">
<template #default="{ row }">
<el-button v-if="row.status === '未处理'" type="primary" link @click="handle(row, '已处理')">处理</el-button>
<el-button v-if="row.status === '未处理'" type="warning" link @click="handle(row, '已忽略')">忽略</el-button>
<el-button v-if="row.record_id" type="success" link @click="$router.push(`/record/${row.record_id}`)">记录</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination style="margin-top: 12px" background layout="total, prev, pager, next" :total="total" v-model:current-page="page" @current-change="load" />
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { alarmPageApi, alarmHandleApi, alarmBatchApi } from '@/api/alarm'
const list = ref([])
const total = ref(0)
const page = ref(1)
const keyword = ref('')
const status = ref('')
const alarmLevel = ref('')
const sel = ref([])
const load = async () => {
const res = await alarmPageApi({ page: page.value, page_size: 10, keyword: keyword.value, status: status.value, alarm_level: alarmLevel.value })
list.value = res.data.list
total.value = res.data.total
}
const handle = async (row, st) => {
const { value } = await ElMessageBox.prompt('请输入处理备注', st, { inputPlaceholder: '可选' }).catch(() => ({ value: '' }))
await alarmHandleApi(row.id, { status: st, handle_remark: value })
ElMessage.success('已更新')
load()
}
const batch = async (st) => {
if (!sel.value.length) return ElMessage.warning('请先选择')
await alarmBatchApi({ ids: sel.value.map(i => i.id), status: st, handle_remark: '批量处理' })
ElMessage.success('批量完成')
load()
}
onMounted(load)
</script>
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/caoli201314/article/details/167701397




