Система обнаружения пожаров по видео: снижение ложных тревог

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

Направления AI-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1302
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    998
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1267
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    714
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1006

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

Традиционные дымовые датчики реагируют на задымление в радиусе 5–7 метров. На открытых территориях — складах без потолочных сенсоров, лесных массивах, промышленных площадках — они бесполезны. Видеоаналитика обнаруживает дым и пламя на расстоянии до 300+ метров, часто раньше, чем концентрация достигает порога срабатывания ионизационного датчика. Ложные срабатывания — главная боль: без temporal-фильтрации FAR достигает 15–30%, что дискредитирует систему. Мы разрабатываем такие системы более 5 лет и решили эту проблему.

Почему temporal-анализ критически важен?

Дым — аморфный объект без чётких границ, меняет форму каждые 2–3 кадра. Артефакты вроде пара, тумана, пыли или бликов от фар похожи на дым/огонь для покадрового классификатора. Temporal-анализ обрабатывает последовательность кадров и отличает дым от тумана по характеру движения. Это снижает FAR в 10–15 раз по сравнению с покадровым детектором.

Как устроена архитектура с temporal-фильтрацией?

Используем YOLOv8m/l с дообучением на смешанном датасете (общедоступные + наши собственные с объекта). Temporal-окно 8 кадров + optical flow проверка для дыма. Код инференса:

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 

Метод optical flow описано в документации OpenCV.

Метрики и пороги

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

Наши тесты показывают: temporal-фильтрация с окном 8 кадров повышает Recall на 8–10% и снижает FAR в 10–15 раз по сравнению с покадровым детектором.

Model card (пример содержания)Архитектура: YOLOv8m, temporal window 8, подтверждение 5/8 кадров. Датасет: FireNet, MIVIA Fire, VisiFire, D-Fire + собственные 1200 изображений. Конфигурация аугментации: HSV, геометрия. Метрики на валидации: Recall 96%, FAR 0.8/смену. Ограничения: при сильном тумане возможно снижение дистанции.

Как дообучение на объекте улучшает детекцию?

Публичные датасеты (FireNet, MIVIA Fire, VisiFire, D-Fire) содержат 11k+ изображений, но в продакшене всегда нужно дообучение на локальных данных. Типичная процедура: собрать 500–800 изображений с объекта (200 smoke/fire + 300–600 hard negatives — пар, туман, закат), дообучить YOLO v8m с 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 ложная тревога (закат + парение котла)

До внедрения нашей системы на объекте было 10–15 ложных вызовов пожарной охраны в месяц, каждый обходился предприятию в среднем в $5 000–10 000. После внедрения FAR снизился до 1 в смену, что сэкономило заказчику более $300 000 в год. Инфраструктура: сервер с RTX 3090, 18 потоков @ 10fps, latency 180ms. Интеграция с пожарной панелью Notifier через Modbus TCP.

Интеграция с пожарными системами

  • Протоколы: Modbus TCP/RTU, BACnet, OPC-UA — для прямой интеграции с пожарными панелями
  • VMS: запись видеодоказательства за 60 сек до и после события
  • Геолокация события: привязка bbox к карте объекта через калибровку камеры

Получите консультацию по интеграции с вашим оборудованием.

Что входит в разработку под ключ?

Мы предоставляем:

  • Обученную модель с model card (архитектура, метрики на валидации, ограничения)
  • Исходный код инференса (Python, документация)
  • REST API для интеграции с вашими системами
  • Готовый модуль для VMS (Milestone, Genetec, или любая с RTSP)
  • Инструкцию для операторов и обучение персонала
  • Гарантию 6 месяцев на адаптацию модели к изменениям сцены (сезонные колебания, новые источники дыма)

Сроки разработки

Масштаб Срок
1–6 камер, закрытое помещение 3–5 недель
10–30 камер, открытая площадка 6–10 недель
30+ камер, enterprise 12–18 недель

Стоимость рассчитывается индивидуально по объёму данных и сложности интеграции. Чтобы оценить ваш проект, напишите нам — мы проанализируем ваши камеры и условия за 1 рабочий день.