AI-Powered Video Smoke and Fire Detection System
Traditional smoke detectors respond to smoke within a radius of 5–7 meters. In open areas—warehouses without overhead sensors, forests, industrial sites—they are useless. Video analytics detects smoke and flames at distances up to 300+ meters, often before the concentration reaches the trigger threshold of an ionization detector. False alarms are the main pain point: without temporal filtering, FAR can reach 15–30%, discrediting the system. We have been developing such systems for over 5 years and have solved this problem.
Why Temporal Analysis Is Critical for AI Smoke Detection
Smoke is an amorphous object without clear boundaries, changing shape every 2–3 frames. Artifacts such as steam, fog, dust, or headlight glare resemble smoke/fire for a frame-by-frame classifier. Temporal analysis processes a sequence of frames and distinguishes smoke from fog based on motion patterns. This reduces FAR by 10–15 times compared to frame-by-frame detection—a significant improvement over baseline approaches.
How Temporal Filtering Works for Video Fire Detection
We use YOLOv8m/l fine-tuned on a mixed dataset (public + our own from the site). Temporal window: 8 frames + optical flow check for smoke. Steps to deploy:
- Collect 500–800 site images (including hard negatives).
- Fine-tune YOLO model on your data.
- Set temporal window (8–12 frames) and confirm threshold.
- Integrate with fire panel via API or relay.
Inference code:
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) # fine-tuned on smoke/fire
self.temporal_window = temporal_window
# Frame buffer for temporal analysis
self.frame_buffer: deque = deque(maxlen=temporal_window)
self.detection_history: dict = {} # track_id -> history
# Minimum frames with detection for alarm
self.confirm_frames = 5 # out of 8 frame window
def _optical_flow_check(self, prev_frame, curr_frame,
bbox: list) -> float:
"""Smoke moves chaotically—check flow irregularity"""
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)
# Smoke: uneven flow, high 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 confirmation
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:
# Additional optical flow check for smoke
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
The optical flow method is described in OpenCV documentation.
Metrics and Thresholds
| Metric | Target Value | Typical Baseline (without temporal) |
|---|---|---|
| Recall (real fires) | > 95% | 87–91% |
| FAR in open areas | < 1 per shift | 8–15 per shift |
| Time to alarm | < 10 sec | < 5 sec (higher FAR) |
| Detection distance (smoke) | 50–300 m | — |
Our tests show: temporal filtering with an 8-frame window improves Recall by 8–10% and reduces FAR by 10–15 times compared to frame-by-frame detection. This means our method is up to 15 times better than standard approaches in false alarm reduction.
Model card (example content)
Architecture: YOLOv8m, temporal window 8, confirmation 5/8 frames. Dataset: FireNet, MIVIA Fire, VisiFire, D-Fire + proprietary 1200 images. Augmentation config: HSV, geometry. Validation metrics: Recall 96%, FAR 0.8/shift. Limitations: distance may decrease in heavy fog.How On-Site Fine-Tuning Improves AI Smoke and Fire Detection
Public datasets (FireNet, MIVIA Fire, VisiFire, D-Fire) contain 11k+ images, but in production, fine-tuning on local data is always needed. Typical procedure: collect 500–800 images from the site (200 smoke/fire + 300–600 hard negatives — steam, fog, sunset), fine-tune YOLO v8m with learning_rate=0.001, 50 epochs, augmentation HSV + geometry. This reduces FAR by 3–5 times on the specific site.
Case Study: Petrochemical Plant (Our Client)
The site is an open area of 4 hectares, 18 PTZ cameras with IR. Task: early detection of tank fire.
- Base model: YOLOv8l, fine-tuned on 1200 site images
- Temporal window: 10 frames @ 10fps = 1 second
- Confirm threshold: 6 out of 10 frames
Test results (15 staged fires):
- Recall: 100% (all 15 detected)
- Average detection time: 4.2 seconds from ignition
- FAR over 2 weeks: 1 false alarm (sunset + boiler steam)
Before our system, the site experienced 10–15 false fire brigade calls per month, each costing the enterprise an average of $5,000–10,000. After implementation, FAR dropped to 1 per shift, saving the client over $300,000 per year. Infrastructure: server with RTX 3090, 18 streams @ 10fps, latency 180ms. Integration with Notifier fire panel via Modbus TCP.
With over 5 years of experience and 20+ deployed projects, we deliver robust solutions for industrial safety.
Integration with Fire Systems
- Protocols: Modbus TCP/RTU, BACnet, OPC-UA — for direct integration with fire panels
- VMS: record video evidence 60 seconds before and after the event
- Event geolocation: bind bbox to site map via camera calibration
Get a consultation on integration with your equipment.
What Is Included in Turnkey Development? (Deliverables)
Our deliverables include:
- Trained model with model card (architecture, validation metrics, limitations)
- Inference source code (Python, documentation)
- REST API for integration with your systems
- Ready-made module for VMS (Milestone, Genetec, or any with RTSP)
- Operator manual and staff training
- 6-month warranty on model adaptation to scene changes (seasonal variations, new smoke sources)
Typical project costs range from $15,000 for small setups to $100,000 for enterprise solutions. We provide a fixed-price quote after initial assessment.
Development Timelines
| Scale | Timeline | Cost Range |
|---|---|---|
| 1–6 cameras, indoor | 3–5 weeks | $15,000–$30,000 |
| 10–30 cameras, open area | 6–10 weeks | $30,000–$60,000 |
| 30+ cameras, enterprise | 12–18 weeks | $60,000–$100,000 |
Cost is calculated individually based on data volume and integration complexity. To evaluate your project, write to us — we will analyze your cameras and conditions within 1 business day.







