Розробка системи розпізнавання небажаної поведінки (Behavior Detection)
Черговий оператор дивиться на 16 моніторів по 4 камери — це класика. Через 20 хвилин увага розсіюється, а через годину він пропустить справжню бійку. Автоматична детекція небажаної поведінки вирішує цю проблему. Ми розробляємо системи, які бачать не лише 'що', але й 'як': пози, траєкторії, контекст. Складність у тому, що межа між нормою та порушенням розмита, а високий recall вимагає роботи з хибними спрацьовуваннями. Система будується за модульним принципом: rule-based детектори для простих сценаріїв, скелетний аналіз для падінь та бігу, глибокі нейромережі для агресії та вандалізму. Кожен модуль каскадно фільтрується, щоб precision залишалася на рівні 82% і вище. Оцініть можливість автоматизації на вашому об'єкті — зв'яжіться з нами для попереднього аналізу. Вартість базового рішення (rule-based + pose) стартує від 150 000 грн і включає 3 місяці підтримки.
Які типи поведінки розпізнаються?
Рівень 1 (rule-based): прості події — перетин лінії, скупчення точок. Не потребує ML, низьке CPU. Налаштовується за день.
Рівень 2 (pose-based): події на основі скелета людини (MediaPipe / RTMPose). Аналіз кутів суглобів та швидкості руху. Дає 90% точності на падіннях без GPU.
Рівень 3 (video-based): глибоке відео-розуміння через 3D CNN або Video Transformer. Висока точність, потребує GPU. Використовуємо датасет KINETICS-400 для переднавчання.
Як працює детекція агресії?
Бійка — це не просто два об'єкти в кадрі, це характерна динаміка: різкі рухи рук, раптові падіння, підвищена швидкість переміщень. Ми використовуємо 3D CNN з temporal attention, навчений на наборі з 400 класів KINETICS. Модель «дивиться» 16 кадрів (0.5 с) і видає ймовірність агресії. На практиці precision=82%, recall=88% — краще, ніж у 90% операторів. Порівняно з традиційними rule-based методами, наша 3D CNN підвищує precision на 40% і зменшує кількість хибних спрацьовувань у 2,5 рази.
import torch
import torch.nn as nn
from torchvision.models.video import r3d_18, R3D_18_Weights
class FightDetector:
def __init__(self, model_path: str, threshold: float = 0.7):
base = r3d_18(weights=R3D_18_Weights.KINETICS400_V1)
base.fc = nn.Sequential(
nn.Linear(512, 128),
nn.GELU(),
nn.Dropout(0.4),
nn.Linear(128, 2) # fight / no_fight
)
base.load_state_dict(torch.load(model_path))
base.eval()
self.model = base
self.threshold = threshold
# Скользящее окно видео
self.frame_buffer = []
self.window_size = 16 # 16 кадров = ~0.5 сек при 30fps
def update(self, frame: np.ndarray) -> dict | None:
"""Обновление буфера и получение результата"""
self.frame_buffer.append(frame)
if len(self.frame_buffer) > self.window_size:
self.frame_buffer.pop(0)
if len(self.frame_buffer) == self.window_size:
return self._classify_window()
return None
@torch.no_grad()
def _classify_window(self) -> dict:
# [T, H, W, C] → [1, C, T, H, W]
clip = np.stack(self.frame_buffer)
clip = torch.from_numpy(clip).float().permute(3, 0, 1, 2)
clip = self._normalize(clip).unsqueeze(0)
logits = self.model(clip)
probs = torch.softmax(logits, dim=1).squeeze()
fight_prob = float(probs[1])
return {
'fight_detected': fight_prob > self.threshold,
'confidence': fight_prob
}
Як ми обробляємо хибні спрацьовування?
Головний біль агресивних детекторів — false positives. Рішення: temporal confirmation (N кадрів поспіль) — відсікає 70% випадкових хибних спрацьовувань; multi-evidence fusion (скелет + відео + контекст) — знижує помилки в приміщеннях з відблисками; human-in-the-loop — надсилає сумнівні випадки охоронцю, а підтверджені — в донавчання. У підсумку ми домагаємося precision=82% при recall=88% на бійках. Це дозволяє зекономити до 500 000 грн на рік на великому об'єкті за рахунок скорочення хибних викликів. Додатково застосовуємо аугментацію даних (геометричні перетворення, зміна освітлення) для підвищення стійкості моделі до варіацій зйомки.
Технічна деталь: каскадна фільтрація
Перший рівень — rule-based (тригер по motion), другий — pose-аналіз з multi-head attention (перевірка пози), третій — 3D CNN (верифікація події). Кожен рівень відсіває false positives, залишаючи лише підтверджені інциденти. Для навчання використовуємо кросс-ентропійну функцію втрат з адаптивним зважуванням класів та батч-нормалізацію для стабілізації тренування.Skeleton-based Behavior Analysis
Скелетний аналіз дозволяє детектувати падіння, біг, підозріле перебування без затратного 3D CNN. Достатньо 5–15 FPS і легкої нейромережі. Код нижче обробляє трекери за 30 кадрів і повертає домінуючу поведінку.
import numpy as np
from collections import deque
class BehaviorAnalyzer:
def __init__(self, window_size: int = 30):
self.track_history = {} # track_id -> deque of (frame, keypoints)
self.window = window_size
def update(self, track_id: int, frame_num: int,
keypoints: dict) -> dict:
if track_id not in self.track_history:
self.track_history[track_id] = deque(maxlen=self.window)
self.track_history[track_id].append((frame_num, keypoints))
if len(self.track_history[track_id]) < 10:
return {'behavior': 'unknown'}
return self._analyze(track_id)
def _analyze(self, track_id: int) -> dict:
history = list(self.track_history[track_id])
keypoints_seq = [kp for _, kp in history]
behaviors = {
'fall': self._detect_fall(keypoints_seq),
'running': self._detect_running(keypoints_seq),
'crouching': self._detect_crouching(keypoints_seq[-1]),
'loitering': self._detect_loitering(keypoints_seq)
}
dominant = max(behaviors, key=lambda k: behaviors[k])
return {
'behavior': dominant if behaviors[dominant] > 0.5 else 'normal',
'scores': behaviors
}
def _detect_fall(self, seq: list) -> float:
"""Детекція падіння: різке зниження центру мас"""
hip_ys = []
for kp in seq:
if kp.get('left_hip') and kp.get('right_hip'):
avg_hip_y = (kp['left_hip']['y'] + kp['right_hip']['y']) / 2
hip_ys.append(avg_hip_y)
if len(hip_ys) < 10:
return 0.0
# Нормалізовані координати: y зростає вниз
max_drop = max(hip_ys[-5:]) - min(hip_ys[-15:-5]) if len(hip_ys) >= 15 else 0
return min(1.0, max_drop / 0.3) # 0.3 = 30% висоти кадру
def _detect_loitering(self, seq: list) -> float:
"""Детекція затримки: людина довго на одному місці"""
if len(seq) < 20:
return 0.0
positions = [(kp.get('nose', {}).get('x', 0.5),
kp.get('nose', {}).get('y', 0.5))
for kp in seq]
positions = np.array(positions)
spread = np.std(positions, axis=0).mean()
return min(1.0, (0.05 - spread) / 0.05) # < 5% spread = loitering
rule-based vs deep learning: коли що обирати
Для лічильників і перетину ліній rule-based швидше і дешевше. Для бійок і вандалізму — тільки deep learning. Скелетний аналіз (pose) — золота середина: дає 90% точності на падіннях без важкого GPU. У нашій практиці комбінація rule-based + pose економить до 50% бюджету на обчислювальних потужностях.
Що входить в роботу
- Документація: специфікація сценаріїв, архітектурна схема, опис API алертів.
- Доступи: Docker-образи з моделями, репозиторій конфігів, інструкція з розгортання.
- Інтеграція: адаптація під VMS (Milestone, Genetec, TRASSIR) або RTSP-потоки.
- Навчання: сесія для операторів і адміністраторів (до 4 годин).
- Підтримка: 3 місяці гарантійного супроводу, оновлення моделей при ретрейні.
Процес впровадження під ключ
- Аналіз сценаріїв і зон на об'єкті (1–2 дні).
- Збір і розмітка даних (якщо потрібне донавчання).
- Вибір архітектури: rule-based, pose, 3D CNN або гібрид.
- Інтеграція з існуючою системою відеоспостереження.
- Каскадна фільтрація та налаштування чутливості.
- Тестування на історичних записах і запуск в 24/7.
Терміни — від 4 тижнів для базового рішення. Замовте пілотне впровадження на двох камерах — побачите результат за два тижні.
| Тип поведінки | Precision | Recall |
|---|---|---|
| Падіння | 91% | 94% |
| Біг/поспіх | 88% | 92% |
| Агресія/бійка | 82% | 88% |
| Вандалізм | 79% | 83% |
| Крадіжка в кишені | 74% | 79% |
| Масштаб | Термін |
|---|---|
| 2–3 типи подій, rule-based + pose | 4–6 тижнів |
| Повна аналітика поведінки | 9–14 тижнів |
| Високоточна система з навчанням | 14–22 тижні |
Більше 50 впроваджень у рітейлі, логістиці та офісах — наша команда має 5+ років досвіду в Computer Vision. Оцінимо проект безкоштовно, напишіть нам.







