🧠 Готовая к продакшену система компьютерного зрения для детекции, трекинга и подсчёта объектов в реальном времени
CVCounter - это гибкая и масштабируемая система компьютерного зрения, предназначенная для анализа видеопотока с возможностью подсчёта объектов.
Подходит для задач: подсчёт продукции, людей, транспорта, аналитика и видеонаблюдение.
- 🎯 Детекция объектов в реальном времени
- 🔢 Подсчёт объектов (в зоне)
- 🧠 Трекинг объектов (multi-object tracking)
- 🎥 Поддержка видеопотоков (RTSP, камера, файлы)
- ⚡ Оптимизация под real-time
- 📊 Подготовка данных для аналитики
- 🧩 Модульная архитектура с реестром детекторов
- 🧠 Несколько бэкендов: Ultralytics YOLO, OpenCV DNN, ONNX Runtime
- Подсчёт людей (магазины, ТЦ)
- Подсчёт транспорта
- Системы безопасности
- Smart City
- Ритейл аналитика
- Промышленность
- Получение видеопотока
- Детекция объектов
- Присвоение ID (трекинг)
- Подсчёт при попадании в зону
- Сохранение или вывод результатов
- Клонируйте репозиторий:
git clone https://github.com/BespredeL/CVCounter.git
- Перейдите в директорию проекта:
cd CVCounter - Установите виртуальное окружение:
python3 -m venv venv
- Активируйте виртуальное окружение:
- В Windows:
.\venv\Scripts\activate
- В Linux/Mac:
source venv/bin/activate
- В Windows:
- Установите зависимости:
pip3 install -r requirements.txt
- Переименуйте файл конфигурации:
mv config/config.example.json config/config.json
- Настройте
config/config.json: укажите видеоисточник, модель и тип детектора (model_type). - Запустите приложение:
python app.py
- Клонируйте репозиторий:
git clone https://github.com/BespredeL/CVCounter.git
- Перейдите в директорию проекта:
cd CVCounter - Соберите и запустите с помощью Docker Compose:
docker-compose up --build
В этом решение реализовано 3 вида просмотра:
- Основной вид - страница на которой выводится значение счетчиков и видео с результатом распознавания
- Текстовый вид - страница на которой выводится только значение счетчиков
- Текстовый вид с N счетчиками - страница на которой выводится значение нескольких счетчиков (например на входе и выходе)
После нескольких вариантов, принял решение реализации на Flask, т.е решение в виде мини веб-сайта, так как такое решение позволяет избежать установки какого либо дополнительного софта на клиенты. А так же это решение не требовательно к клиентам в плане потребления ресурсов (за исключением основного вида с видео)
Мне удалось запустить 6 одновременных подсчетов (без вывода видео), и 5 подсчетов с выводом видео.
Характеристики сервера:
- AMD Ryzen 5 3600
- GeForce GTX 1050 Ti (4Гб)
Вы можете запускать браузер в режиме киоска, для предотвращения выхода из него (например для Google Chrome при запуске можно указать " --kiosk --start-fullscreen")
P.S.:
- Друзья, если вас не затруднит, не убирайте, пожалуйста, мой копирайт внизу страницы. Вам это ничего не стоит, а мне приятно.
- Всё это реализовано без какого либо ТЗ и никто не верил в успех, поэтому пока что есть некоторая хаотичность, но постараюсь всё переделать более правильно =)
- Если вам помогло это решение, вы можете проспонсировать меня отправив слово "Спасибо". Ссылки на контакты ниже =)
- Если нужна помощь с внедрением, можем обсудить =).
Детекторы подключаются через реестр (system/object_detection/registry.py). В конфигурации задаётся поле model_type.
model_type |
Бэкенд | Форматы моделей |
|---|---|---|
yolo |
Ultralytics YOLO | .pt |
opencv, opencv_dnn |
OpenCV DNN | .onnx, .pb, Darknet (.weights + .cfg) |
onnx, onnxruntime |
ONNX Runtime | .onnx (экспорт YOLO) |
Ultralytics YOLO (по умолчанию):
"model_type": "yolo",
"weights_path": "config/ultralytics/models/yolov8n.pt",
"device": 0OpenCV DNN + ONNX:
"model_type": "opencv",
"weights_path": "config/opencv/models/yolov8n.onnx",
"input_size": 640,
"backend": "CUDA",
"target": "CUDA"Darknet через OpenCV:
"model_type": "opencv_dnn",
"weights_path": "config/opencv_dnn/models/yolov4.weights",
"model_config_path": "config/opencv_dnn/models/yolov4.cfg",
"input_size": 416ONNX Runtime:
"model_type": "onnx",
"weights_path": "config/onnx/models/yolov8n.onnx",
"input_size": 640,
"providers": [
"CUDAExecutionProvider", "CPUExecutionProvider"
]Экспорт модели YOLO в ONNX:
yolo export model=config/ultralytics/models/yolov8n.pt format=onnx| Параметр | Применимо к | Описание |
|---|---|---|
weights_path |
все | Путь к файлу модели |
model_config_path |
OpenCV Darknet | Путь к .cfg |
input_size |
OpenCV, ONNX | Размер входа: число или [width, height], по умолчанию 640 |
backend |
OpenCV | OPENCV, CUDA, DEFAULT и др. |
target |
OpenCV | CPU, CUDA, CUDA_FP16 и др. |
providers |
ONNX | Список провайдеров ONNX Runtime |
confidence, iou |
все | Пороги детекции |
device |
YOLO, ONNX | Устройство (0, cpu и т.д.) |
vid_stride |
YOLO | Шаг кадров при инференсе |
classes |
все | Фильтр классов { "0": "person" } |
- Создайте класс, наследующий
BaseObjectDetectionService:
from system.object_detection.base_object_detection import BaseObjectDetectionService, DetectionResult
from system.object_detection.registry import register
@register('my_detector')
class ObjectDetectionMy(BaseObjectDetectionService):
def load_model(self, weights: str, **kwargs) -> None:
...
def detect(self, image, **kwargs) -> DetectionResult:
# return boxes_xyxy, confidences, classes
...- Импортируйте модуль в
system/object_detection/__init__.py. - Укажите
"model_type": "my_detector"в конфигурации.
{
general: {
// включить режим отладки
debug: true,
// путь к файлу журнала
log_path: "storage/logs/cvcounter.log",
// минимальный уровень журнала: DEBUG, INFO, WARNING, ERROR, CRITICAL
log_level: "INFO",
// включить вывод журнала в консоль (рекомендуется false в рабочей среде)
log_console: false,
// язык по умолчанию
default_language: "ru",
// разрешить небезопасные операции в werkzeug
allow_unsafe_werkzeug: false,
// показать кнопку изменения темы
button_change_theme: true,
// показать кнопку перехода в полноэкранный режим
button_fullscreen: true,
// показать кнопку назад
button_backward: false,
// показать кнопку сохранения кадра
button_save_capture: false,
// показать клавиатуры свернутыми
collapsed_keyboard: true,
},
server: {
// адрес сервера
host: "0.0.0.0",
// порт сервера
port: 8080,
// включить режим перезагрузки
use_reloader: false,
// включить вывод журнала
log_output: true,
// socketio ключ
socketio_key: "",
// allowed origins
allowed_origins: "*",
},
users: {
// логин:пароль по умолчанию admin:admin
admin: "scrypt:32768:8:1$rsdPYhqaQqpXQQ0o$aa3359c86228b4cee5fe8c4ed694db4b371fa7fab5100fa7b446db7e1ed8077e3bb63228d4a1899aeeef9b8d15f8e8bdbcc3457f020bcb3ec320332c76b5896b",
},
db: {
// подключение к базе данных
uri: "sqlite:///system/database.db",
// префикс таблиц
prefix: "",
},
form: {
// показать форму брака
defect_show: true,
// показать форму коррекции
correct_show: true,
// конфигурация пользовательских полей
custom_fields: {
field_one: {
// название поля
name: "field_one",
// подпись поля
label: "Field One",
// тип поля
type: "text",
},
},
},
detection_default: {
// тип модели: yolo | opencv | opencv_dnn | onnx | onnxruntime
model_type: "yolo",
// путь к модели (.pt, .onnx, .weights и т.д.)
weights_path: "config/ultralytics/models/yolov8n.pt",
// путь к конфигу Darknet (.cfg), только для opencv/opencv_dnn
// model_config_path: "config/models/yolov4.cfg",
// размер входа модели (число или [width, height]), для opencv/onnx
// input_size: 640,
// OpenCV DNN backend/target (OPENCV, CUDA, CPU и т.д.)
// backend: "CUDA",
// target: "CUDA",
// провайдеры ONNX Runtime
// providers: ["CUDAExecutionProvider", "CPUExecutionProvider"],
// масштаб вывода видео на странице
video_show_scale: 50,
// качество вывода видео на странице
video_show_quality: 50,
// ручная установка FPS (0 - автоматическая установка)
video_fps: 0,
// макс. попыток подключения к камере при старте и после обрыва потока
video_reconnect_attempts: 5,
// порог доверия
confidence: 0.7,
// порог iou
iou: 0.7,
// указывает вычислительное устройство (см. документацию ultralytics / ONNX Runtime)
device: 0,
// шаг видеопотока
vid_stride: 1,
// размер индикатора
indicator_size: 10,
// площадь подсчета (многоугольник)
counting_area: [
[
0,
0
],
[
100,
0
],
[
100,
100
],
[
0,
100
],
],
// цвет зоны подсчета
counting_area_color: [
67,
211,
255
],
// классы (объекты) для обнаружения (оставьте пустым для всех классов)
classes: {},
// конфигурация записи видео для всех распознаваний
recording: {
// включить запись видео
enable: false,
// путь к папке хранения
path: "storage/saved_recordings",
// размер видео (в процентах)
scale: 100,
// качество видео
quality: 80,
},
},
detections: {
// конфигурации обнаружения
ExampleCam: {
// наименование подсчета (используется в адресе страницы, должно быть на латинице)
label: "Label ExampleCam",
// число с которого начинается подсчет (по умолчанию 0, но если необходимо начать с какого-то числа, то можно указать)
start_total_count: 0,
// путь к видеофайлу или источнику камеры
video_path: "",
// масштаб вывода видео на странице
video_show_scale: 70,
// качество вывода видео на странице
video_show_quality: 30,
// ручная установка FPS (необязательно)
video_fps: 0,
// макс. попыток подключения к камере (необязательно, наследуется из detection_default)
video_reconnect_attempts: 5,
// тип модели: yolo | opencv | opencv_dnn | onnx | onnxruntime
model_type: "yolo",
// путь к модели
weights_path: "config/ultralytics/models/yolov8n.pt",
// порог доверия
confidence: 0.7,
// порог iou
iou: 0.7,
// вычислительное устройство (см. документацию ultralytics / ONNX Runtime)
device: 0,
// шаг видеопотока
vid_stride: 1,
// размер индикатора
indicator_size: 10,
// площадь подсчета (многоугольник)
counting_area: [
[
0,
0
],
[
100,
0
],
[
100,
100
],
[
0,
100
],
],
// цвет зоны подсчета
counting_area_color: [
255,
64,
0
],
// классы (объекты) для обнаружения (оставьте пустым для всех классов)
classes: {},
// автоматическое создание набора данных
dataset_create: {
// включить создание набора данных
enable: true,
// вероятность создания изображения набора данных (число от 0.01 до 1, где 0.01 - 1% и 1 - 100%)
probability: 0.05,
// путь для сохранения набора данных
path: "storage/saved_images/ExampleCam",
},
// конфигурация записи видео для обнаружения
recording: {
// включить запись видео
enable: false,
// путь к папке хранения
path: "storage/saved_recordings",
// размер видео (в процентах)
scale: 100,
// качество видео
quality: 80,
},
},
},
}P.S.: Не лучший пример на скриншотах. Не нашел ничего лучше, чем камера в открытом доступе (((
Александр Киреев
Website: https://bespredel.name
E-mail: hello@bespredel.name
GitHub: https://github.com/BespredeL
Ultralytics: https://github.com/ultralytics
OpenCV: https://opencv.org/
ONNX Runtime: https://onnxruntime.ai/
AGPL-3.0 License: Эта OSI-approved лицензия с открытым исходным кодом идеально подходит для студентов и энтузиастов, способствуя открытому сотрудничеству и обмену знаниями.
Буду признателен за звезду ⭐ на GitHub, если проект оказался полезным.











