Всем привет, я Иван, продакт-менеджер. В этой статье разберу практический опыт построения системы видеоаналитики на базе open source-инструментов: от выбора библиотек и архитектуры до проблем с производительностью и масштабированием под десятки видеопотоков.

Материал будет полезен инженерам, тимлидам и продакт-менеджерам и всем тем, кто рассматривает open source как основу для production-ready CV-систем.

Почему мы решили не писать всё с нуля

Начнём с базового вопроса: почему вообще open source?

На практике в компьютерном зрении уже закрыты почти все фундаментальные задачи:

  • детекция объектов,

  • трекинг,

  • базовая обработка изображений,

  • инференс моделей.

Писать собственную реализацию этих вещей с нуля — дорого, долго и бессмысленно. Мы решили использовать open source как фундамент, а свою экспертизу вложить туда, где он заканчивается:

  • в архитектуру,

  • в масштабирование,

  • в устойчивую обработку видеопотоков,

  • в интеграцию с бизнес-системами.

Мы также рассматривали альтернативные подходы — закрытые коммерческие платформы и managed-сервисы. На практике они быстро упирались в ограничения: сложность кастомизации под конкретные сценарии, vendor lock-in и непрозрачную модель масштабирования по стоимости.

Базовый стек

На старте мы выбрали максимально «приземлённый» и проверенный набор инструментов:

  • YOLO (Ultralytics) — детекция объектов в кадре и видеопотоке

  • OpenCV — декодирование видео, пред- и постобработка изображений

  • PyTorch — обучение и инференс моделей

  • NumPy — работа с массивами на всех этапах пайплайна

Важно: open source закрывает именно алгоритмическую часть. Всё, что связано с жизненным циклом данных, отказоустойчивостью и масштабированием, пришлось проектировать отдельно.

Например, в качестве базовой модели детекции мы остановились на YOLO из-за хорошего баланса между точностью и задержками. Для наших сценариев latency была важнее максимального mAP: система должна реагировать почти в реальном времени, а не «догонять» события.

PyTorch выбрали из-за удобства дообучения и отладки. В процессе разработки модели часто менялись, и возможность быстро экспериментировать с архитектурой и параметрами оказалась важнее потенциального выигрыша в производительности, который могли бы дать более жёсткие фреймворки.

OpenCV использовали не только для декодирования, но и для ряда оптимизаций на этапе предобработки — это позволило снизить нагрузку на GPU в пиковые моменты.

Архитектура: почему всё разнесено по сервисам

С самого начала мы отказались от монолитного подхода. Причина простая: видеопотоки — это неравномерная нагрузка. Камеры могут «сыпаться», пропадать, возвращаться, давать пики.

В итоге архитектура выглядит так:

  • Frontend — веб-интерфейс для подключения камер, настройки зон и просмотра событий

  • Backend — API и хранилище событий

  • Detection-сервисы — обработка видеопотоков и детекция объектов

  • Recognize-сервисы — специализированное распознавание (номера, лица и т.д.)

Отдельное внимание пришлось уделить отказоустойчивости. В реальности камеры могут пропадать, отдавать битый поток или резко менять битрейт. Поэтому каждый Detection-сервис работает независимо и не блокирует остальные при сбоях.

Очередь сообщений используется не только для масштабирования, но и как буфер: если сервис распознавания временно недоступен, события не теряются, а обрабатываются позже. Для таких случаев мы используем retry-механику и отдельные очереди для проблемных сообщений.

Связь между компонентами идёт через API и очередь сообщений (RabbitMQ).

Kafka рассматривали, но в нашем масштабе она давала больше операционной работы, чем пользы: отдельная эксплуатация, настройки, наблюдаемость, плюс необходимость аккуратно держать latency, отказались.

Как работает пайплайн:

  1. Камера отдает поток H.264 по RTSP.

  2. Detection находит объекты и формирует кропы.

  3. Backend сохраняет их и ставит задачу на распознавание.

  4. Recognize возвращает результат.

  5. Пользователь видит событие в интерфейсе или получает уведомление.

На практике самые затратные по времени этапы — это декодирование видеопотока и инференс модели. Именно они определяют верхнюю границу по количеству камер на сервер.

Мы сознательно разделили эти этапы и минимизировали синхронные операции, так мы сгладили пики нагрузки и избежали накопления задержек при росте числа потоков.

Зачем нужна модульность

  • Можно быстро подключить новый сценарий (например, контроль СИЗ), дообучив модель.

  • Detection и Recognize масштабируются параллельно — под разные камеры и задачи.

  • Разделение ответственности: интерфейс, хранилище и модули развиваются независимо.

Производительность

На одном сервере (Threadripper PRO + 2× RTX 4090) система держит около 30 RTSP-потоков. Средняя задержка от появления объекта в кадре до события в интерфейсе — меньше секунды. Это ключевой показатель, ради которого мы оптимизировали пайплайн.

При дальнейшем увеличении числа камер система начинает упираться в CPU-часть, связанную с декодированием видео и подготовкой данных. На практике узким местом оказывается не инференс, а подготовка видеопотока и работа с I/O.

Мы рассматривали варианты горизонтального масштабирования, но для текущих сценариев сделали ставку на вертикальное — с более мощными CPU и несколькими GPU на сервер.

Модель данных

Ядро системы — это события (Event) и кропы (EventPhoto). Каждое событие связано с камерой (Camera), функцией (CameraFunction) и временем. Кроп хранит изображение и результат обработки.

Отдельно ведутся пользователи (User), сотрудники (Employee), регионы (Region), а также настройки функций камеры и пакеты подписок. Такая модель позволяет хранить как «сырые» данные (кропы), так и бизнес-контекст (какой сотрудник, на какой территории, какое событие).

Мы сознательно не делаем видео основной сущностью системы. Хранение и обработка видеозаписей сильно усложняет аналитику и увеличивает требования к инфраструктуре.

Событийная модель позволяет работать с уже интерпретированными данными: временем, типом события, объектом и контекстом. Видео при этом остаётся источником, но не центром системы.

Модули и кейсы применения

Мы строили систему по принципу конструктора: модули можно подключать под разные задачи, они работают на общей архитектуре и обмениваются данными через единый пайплайн.

Автомобили. Система отмечает въезды и выезды: сохраняет время, фото и номер машины. Это дает статистику по парковкам и контроль тран��порта на промплощадках.

Люди и рабочее время. Камера фиксирует вход/выход или считает, сколько сотрудник провел в зоне — например, у станка. Так можно сверять табель с фактическим временем и понимать загрузку персонала.

Средства защиты. Отдельный модуль проверяет, есть ли каска или жилет. Нарушение фиксируется как событие.

Кейсы применения:

  • Завод: контроль транспорта на въезде и проверка касок.

  • Офис: вход сотрудников и интеграция со СКУД.

  • Склад: учет рабочего времени и СИЗ.

  • Парковка: автоматический учет заездов по номерам.

Мы строим модули на YOLO, OpenCV и PyTorch и дообучаем модели под конкретные сценарии. Для этого используем собственные датасеты — более 200 тысяч изображений автомобилей и номерных знаков, а также специализированные выборки для детекции касок и оружия.

Нишевые сценарии

В отдельных сценариях мы сознательно отказались от нейросетевых подходов. Например, при поиске дефектов на металлических поверхностях нейросети требовали большого объёма размеченных данных, которые было сложно и дорого собрать.

В таких случаях мы использовали классические методы компьютерного зрения, в частности признаки Харалика. Они позволяют анализировать текстуру поверхности и хорошо работают там, где дефект проявляется как изменение структуры материала, а не формы объекта.

Этот подход оказался устойчивым и предсказуемым, особенно в условиях ограниченного датасета. При этом он требует более точной настройки и понимания предметной области, чем нейросетевые модели. Прикерпляю пикчу:

 Пример результата, полученного с использованием признаков Харалика
Пример результата, полученного с использованием признаков Харалика

Если тема классических методов CV интересна, могу разобрать этот подход подробнее в отдельной статье.

Инфраструктура и требования

Для стабильной работы используются:

  • Камеры: IP + RTSP (H.264, ≤1 Мбит/с).

  • Сервер: многопоточный CPU (Threadripper PRO), ≥128 ГБ RAM, 2× GPU уровня RTX 4090, быстрый SSD.

Мы тестировали и более легкие конфигурации: сервер с одной GPU держит не больше 8–10 потоков.

Отдельный пласт работы — эксплуатация. Мы мониторим не только технические метрики (загрузка CPU/GPU, задержки очередей), но и качество распознавания: рост ложных срабатываний часто сигнализирует о проблемах с камерой или освещением.

«Ошибка Кабачок»

При первых тестах на слабом сервере мы столкнулись с артефактами и потерей кадров из-за проблем с декодированием видеопотока. Внутри команды эту багу мы в шутку назвали «ошибка Кабачок». Опыт показал: без мощного CPU и двух GPU система нестабильна, поэтому для продакшена мы сразу выбрали Threadripper и RTX 4090.

Минимальная настройка

В config.ini настраиваются:

  • confidence_ratio — баланс между пропусками и ложными срабатываниями;

  • class_list — список объектов для поиска (авто, человек, каска);

  • BoundingBox — расширение рамки, чтобы не обрезать номер.

Интеграции:

  • Telegram — уведомления о событиях.

  • FaceReg — идентификация лиц.

  • Swagger — автодокументация API.

Выводы и уроки

Опыт с zool (так назвали продукт) показал, что ставка на open source оправдана, но не решает всё автоматически.

Где помогло:

  • Быстро собрали прототипы на YOLO, OpenCV и PyTorch.

  • Сократили расходы на лицензии.

  • Получили гибкость — можно дообучать модели под конкретные задачи.

Где пришлось дорабатывать:

  • Обучение на собственных датасетах (например, российские номера машин).

  • Оптимизация под высокую нагрузку и десятки потоков.

  • Настройка пайплайна и параметров, чтобы снизить ложные срабатывания.

Почему гибридный подход лучше. Открытые библиотеки закрывают базовые задачи, а свои сервисы дают управляемость и удобство для бизнеса. Такой баланс позволяет развивать продукт, не завязываясь на одном вендоре и сохраняя контроль над качеством.

Что дальше. Мы планируем расширять модули (например, анализ поведения людей), добавлять новые интеграции и повышать производительность системы при росте числа камер.