AI Smoke and Fire Detection System by Video

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1 servicesAll 1566 services
AI Smoke and Fire Detection System by Video
Medium
~1-2 weeks
FAQ
AI Development Areas
AI Solution Development Stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823
  • image_logo-aider_0.jpg
    AIDER company logo development
    762
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    848

Система детекции дыма и огня по видео на основе AI

Традиционные дымовые датчики реагируют на задымление в радиусе 5–7 метров. На открытых территориях — складах без потолочных сенсоров, лесных массивах, промышленных площадках — они бесполезны. Видеоаналитика обнаруживает дым и пламя на расстоянии до 300+ метров, часто раньше, чем концентрация достигает порога срабатывания ионизационного датчика.

Почему задача нетривиальна

Дым — аморфный объект без чётких границ. Он меняет форму каждые 2–3 кадра. «Дымоподобные» артефакты на видео: паровые выхлопы, туман, пыль от строительства, блики от фар в тумане. Огонь: блики от стекла, светоотражающие поверхности, закаты.

Классические CNN-классификаторы на одиночных кадрах дают FAR 15–30% в реальных условиях. Нужна temporal-aware архитектура.

Architecture детектора

import torch
import torch.nn as nn
from ultralytics import YOLO
import numpy as np
from collections import deque

class SmokeFireDetector:
    def __init__(self, model_path: str, temporal_window: int = 8):
        self.detector = YOLO(model_path)  # дообученный на smoke/fire
        self.temporal_window = temporal_window

        # Буфер кадров для temporal анализа
        self.frame_buffer: deque = deque(maxlen=temporal_window)
        self.detection_history: dict = {}  # track_id -> history

        # Минимальное кол-во кадров с детекцией для тревоги
        self.confirm_frames = 5  # из 8 кадров окна

    def _optical_flow_check(self, prev_frame, curr_frame,
                             bbox: list) -> float:
        """Дым движется хаотично — проверяем нерегулярность потока"""
        x1, y1, x2, y2 = bbox
        prev_roi = cv2.cvtColor(prev_frame[y1:y2, x1:x2], cv2.COLOR_BGR2GRAY)
        curr_roi = cv2.cvtColor(curr_frame[y1:y2, x1:x2], cv2.COLOR_BGR2GRAY)

        flow = cv2.calcOpticalFlowFarneback(
            prev_roi, curr_roi, None,
            pyr_scale=0.5, levels=3, winsize=15,
            iterations=3, poly_n=5, poly_sigma=1.1, flags=0
        )
        magnitude = np.sqrt(flow[..., 0]**2 + flow[..., 1]**2)
        # Дым: неравномерный поток, высокая std
        return float(magnitude.std())

    def detect(self, frame: np.ndarray) -> list[dict]:
        self.frame_buffer.append(frame.copy())
        results = self.detector(frame, conf=0.35, iou=0.4)
        confirmed_events = []

        for box in results[0].boxes:
            cls_id = int(box.cls)
            cls_name = self.detector.model.names[cls_id]
            if cls_name not in ['smoke', 'fire']:
                continue

            bbox = list(map(int, box.xyxy[0]))
            conf = float(box.conf)

            # Temporal подтверждение
            det_key = f"{cls_name}_{bbox[0]//50}_{bbox[1]//50}"  # grid cell
            if det_key not in self.detection_history:
                self.detection_history[det_key] = deque(maxlen=self.temporal_window)
            self.detection_history[det_key].append(conf)

            confirmed_count = sum(1 for c in self.detection_history[det_key]
                                   if c > 0.3)

            if confirmed_count >= self.confirm_frames:
                # Дополнительная проверка optical flow для дыма
                flow_score = 0.0
                if cls_name == 'smoke' and len(self.frame_buffer) >= 2:
                    flow_score = self._optical_flow_check(
                        self.frame_buffer[-2], frame, bbox
                    )

                confirmed_events.append({
                    'class': cls_name,
                    'confidence': conf,
                    'temporal_score': confirmed_count / self.temporal_window,
                    'flow_irregularity': flow_score,
                    'bbox': bbox,
                    'alert': True
                })

        return confirmed_events

Metrics и пороги

Показатель Целевое значение Типичный baseline (без temporal)
Recall (реальные возгорания) > 95% 87–91%
FAR на открытых площадках < 1 в смену 8–15 в смену
Время до тревоги < 10 сек < 5 сек (выше FAR)
Дистанция обнаружения (дым) 50–300м

Датасеты и дообучение

Публичные датасеты: FireNet, MIVIA Fire, VisiFire, D-Fire (11k+ изображений, дым + огонь). Но в продакшене всегда нужно дообучение на локальных данных: камеры конкретного объекта, типичные ложные срабатывания.

Типичная процедура: собрать 500–800 изображений с объекта (200 smoke/fire + 300–600 hard negatives — пар, туман, закат), дообучить YOLOv8m с learning_rate=0.001, 50 эпох, аугментация HSV + геометрия. Даёт снижение FAR в 3–5 раз на конкретном объекте.

Кейс: нефтехимический завод

Объект — открытая площадка 4 га, 18 PTZ-камер с ИК. Задача: ранее обнаружение возгорания резервуаров.

  • Базовая модель: YOLOv8l, дообученная на 1200 изображениях объекта
  • Temporal window: 10 кадров @ 10fps = 1 секунда
  • Confirm threshold: 6 из 10 кадров

Результаты тестирования (15 инсценированных возгораний):

  • Recall: 100% (все 15 обнаружены)
  • Среднее время обнаружения: 4.2 секунды от начала горения
  • FAR за 2 недели работы: 1 ложная тревога (закат + парение котла)

Инфраструктура: сервер с RTX 3090, 18 потоков @ 10fps, latency 180ms. Integration с пожарной панелью Notifier через Modbus TCP.

Integration с пожарными системами

  • Протоколы: Modbus TCP/RTU, BACnet, OPC-UA — для прямой интеграции с пожарными панелями
  • VMS: запись видеодоказательства за 60 сек до и после события
  • Геолокация события: привязка bbox к карте объекта через калибровку камеры
Масштаб Срок
1–6 камер, закрытое помещение 3–5 недель
10–30 камер, открытая площадка 6–10 недель
30+ камер, enterprise 12–18 недель