RAVEL-VB — модель для детекта игроков в волейбол на площадке

от автора

Всё началось с того, что на «Хабре» мне попалась статья о модели TAPe — Theory of Active Perception, или «теории активного восприятия». В статье были громкие заявления и интересные описания, но попробовать модель на практике не удалось.

Я собрал ключевые тезисы о TAPe и обратился к ChatGPT с запросом:

«Я студент и хочу в рамках дипломной работы реализовать модель, использующую подходы Theory of Active Perception. Она должна определять, где находятся игроки и какие действия они выполняют: подачу, приём, передачу или атаку».

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

Почему именно девять кадров? Ранее я уже модифицировал модель TrackNet для трекинга волейбольного мяча по девяти последовательным кадрам и решил придерживаться похожего подхода, чтобы сократить вычислительные затраты.

Первые итерации

Первая версия модели использовала query-based-подход для одновременного поиска игроков и мяча в видеоклипе.

Принцип работы

  1. На вход модели подаётся фиксированный клип из девяти кадров в формате [B, T, C, H, W]. Каждый кадр приводится к разрешению 512 × 288 пикселей.

  2. TinyBackbone извлекает признаки на трёх уровнях пирамиды FPN: 1/4, 1/8 и 1/16 от исходного разрешения.

  3. Для поиска игроков используются 20 обучаемых query-слотов с начальными пространственными якорями. Декодер последовательно применяет:

    • self-attention между query;

    • cross-attention к визуальным признакам;

    • temporal attention между кадрами.

  4. Для каждого query модель предсказывает:

    • класс объекта — player или background;

    • ограничивающий прямоугольник — bounding box;

    • embedding для сопоставления одного и того же игрока между кадрами.

  5. Мяч обнаруживается отдельной grid-head. Для каждого кадра модель предсказывает карту уверенности и смещение объекта внутри наиболее вероятной ячейки.

  6. После инференса применяются порог уверенности и NMS для боксов игроков. Для мяча выбирается ячейка с максимальным значением уверенности.

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

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

Главная проблема обучения подобных моделей — наличие качественных размеченных датасетов.

Первые эксперименты я проводил на датасете по паделу, состоящем из двух двадцатиминутных видео с покадровой разметкой.

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

первые обучение на padel датасете

первые обучение на padel датасете

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

Причина оказалась в разметке. В одном из матчей был эпизод с крупным планом, но соответствующие кадры при аннотации пропустили. Из-за этого вся последующая разметка сдвинулась относительно видео. В результате почти половина датасета оказалась некорректной.

Датасет для пляжного волейбола

Почему именно пляжный волейбол? Сейчас лето, и мы регулярно играем на песке. Я записываю матчи, чтобы потом посмотреть на свою игру со стороны.

На площадке всего четыре человека, поэтому такие видео проще размечать. Кроме того, в будущем мне было бы интересно автоматически получать статистику собственных матчей: нарезку игровых эпизодов без пауз, количество касаний, длительность розыгрышей и другие показатели.

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

Особенно заметны ошибки во время атак и блоков. Когда игрок прыгает, модель иногда обрезает bounding box по голове или не включает в него поднятые руки атакующего и блокирующего.

В процессе работы над датасетом я также понял, что мои записи слишком однообразны: одна и та же площадка, похожее освещение и практически неизменная позиция камеры. Чтобы увеличить разнообразие данных, я добавил видео с играми профессиональных спортсменов.

Обратная связь от LLM

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

В идеальном мире после этого мы получили бы работающий детектор. В реальности модель действительно что-то находит, но часто не там, где нужно. А иногда, наоборот, не находит игроков там, где они явно присутствуют.

Тогда мы берём результаты и пишем:

«Дорогой ChatGPT, посмотри, что за ерунда получилась…»

LLM отвечает:

«Ты совершенно прав: это предсказуемая ошибка, которая заложена в архитектуре твоей сети…»

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

отладка модели и попытки понять почему есть ошибки

отладка модели и попытки понять почему есть ошибки

После каждого изменения архитектуры модель нужно заново обучать на моём датасете из 21 000 кадров. Одна эпоха занимает 6–7 минут, а полный цикл обучения на RTX 3060 с 12 ГБ видеопамяти — около 8–10 часов.

После более чем двадцати итераций мы получили модель, которая почти работает. Она уже достаточно уверенно находит игроков, но остаются проблемы с «прыгающими» боксами и периодической потерей детекций на отдельных кадрах.

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

Смена архитектуры

После множества «правильных исправлений», предложенных LLM, в модели постепенно накопилось большое количество костылей, дополнительных параметров и механизмов, подогнанных под детекцию игроков. При этом качество предсказаний почти не улучшалось.

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

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

Компонент

Нулевая версия

ravel-vb-001

Входные данные

Grayscale, 1 канал

RGB, 3 канала по умолчанию

Backbone

backbone_dim=64

backbone_dim=32, более лёгкий вариант

Поиск игроков

20 фиксированных обучаемых queries и пространственные anchors

Динамические proposals из карты P4, top-K до 32

Работа с признаками

Cross-attention между queries и всей evidence memory

grid_sample вокруг каждого proposal на трёх уровнях FPN

Временная связь

Temporal self-attention внутри decoder

Явный TemporalPlayerLinker: affinity по embedding и расстоянию, затем GRU

Уточнение боксов

Общий query decoder и единая box head

Несколько PlayerRefinementLayer, последовательно уточняющих reference box

Дополнительные выходы

Класс, bounding box и embedding

Класс, bounding box, embedding, точки головы и ног, visibility, court points и association

Версия архитектуры

18

19

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

Схема рабочей модели REVEL‑VB

Запустить модель самостоятельно можно из репозитория:

RAVEL-VB Beach Volleyball Tracking

Модель состоит из двух независимых ветвей:

  • первая отвечает за детекцию игроков;

  • вторая — за поиск мяча и построена на базе vballnet_grid_v1a.

Замеры производительности

В качестве отправной точки я запустил YOLO11n через OpenVINO и получил производительность 19,16 FPS.

На этом фоне результаты собственной модели выглядели вполне обнадёживающе:

  • на CPU использовался OpenVINO;

  • на GPU — PyTorch с CUDA.

Backend

Модель

Устройство

Pipeline FPS

OpenVINO

ravel_vb_001_9f.xml

CPU

23,557

OpenVINO

ravel_vb_001_18f.xml

CPU

12,745

PyTorch

ravel_vb_001_18f.pt

CUDA

84,71

PyTorch

ravel_vb_001_9f.pt

CUDA

84,40

Во время подготовки статьи я решил сравнить производительность и точность модели с дообученной YOLO26n. Результат оказался неожиданным: YOLO26n-VB в OpenVINO показала 43,87 FPS.

Кадры в моём датасете имеют разрешение 512 × 288 пикселей. Это позволило ускорить YOLO-модели по сравнению с запуском на стандартном входном разрешении 640 × 640.

Почти двукратное отставание заставило меня глубже разобраться в вопросе производительности. Модель, которая должна была стать «убийцей YOLO», сама оказалась заметно медленнее.

Профилирование модели

Этап

Доля времени

Backbone

51,4%

Ball grid

27,0%

Proposal head

15,3%

New query sampler

1,6%

Persistent queries

1,5%

Temporal linker

0,7%

Остальные операции

≈1,1%

Профилирование показало, что больше половины времени выполнения занимает backbone. Ещё 27% приходится на ветку поиска мяча, а 15,3% — на proposal head.

Главный вывод: в первую очередь необходимо ускорять backbone. Именно он является основным узким местом всей архитектуры.

Архитектурные оптимизации RAVEL-VB-002/003 относительно RAVEL-VB-001

В качестве базовой рассматривается стандартная конфигурация модели: входное разрешение 512 × 288 пикселей, ширина признакового пространства 128 каналов, 32 запроса и плотная генерация предложений на карте P4.

1. Уменьшение ширины признакового пространства

В RAVEL-VB-001 размер скрытого представления составляет 128 каналов, тогда как RAVEL-VB-002 и RAVEL-VB-003 по умолчанию используют 64 канала.

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

2. C3k2/CSP-backbone вместо полноканальных блоков

Backbone в оптимизированных версиях построен на блоках C3k2, использующих CSP-подобное разделение потока признаков:

  1. входные признаки проецируются в два потока уменьшенной ширины;

  2. вычислительно дорогие свёртки выполняются только над одним из потоков;

  3. промежуточные признаки объединяются;

  4. итоговая карта формируется с помощью компактной проекции.

При коэффициенте расширения 0,5 основные свёртки работают примерно с половиной исходного числа каналов. Остаточные связи внутри блоков C3k при этом помогают сохранить стабильность обучения.

Количество параметров backbone:

Модель

Количество параметров

RAVEL-VB-001

1 209 328

RAVEL-VB-002

404 848

RAVEL-VB-003

375 792

Таким образом, backbone RAVEL-VB-002 содержит примерно в три раза меньше параметров, чем backbone RAVEL-VB-001. В RAVEL-VB-003 количество параметров уменьшено ещё сильнее.

RAVEL-VB-002 сохраняет более информативное представление уровня P4, тогда как RAVEL-VB-003 реализует более агрессивный подход «вычисления по требованию». Плотная карта высокого разрешения используется только для первичного поиска объектов, после чего основная обработка переносится на разреженные запросы и признаки более низкого разрешения.

FPS бывают разными

Производительность модели можно измерять по-разному.

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

В другом случае измеряется скорость обработки конкретного видео целиком.

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

  • чтение и декодирование кадров;

  • предварительная обработка;

  • инференс модели;

  • постобработка предсказаний.

Такой показатель правильнее называть производительностью всего конвейера, или pipeline FPS.

Тестовое видео

Для тестирования использовалось видео со следующими характеристиками:

Duration: 00:00:40.01 Start: 0.000000Bitrate: 1119 kb/sCodec: H.264 HighPixel format: yuv420pColor space: BT.709Resolution: 1280 × 720Video bitrate: 982 kb/sFrame rate: 29.97 FPS

Для обеспечения повторяемости тестов замеры проводились на VPS и выделенном GPU. Это позволяет сравнивать версии модели в одинаковых условиях и уменьшает влияние фоновой нагрузки, различий в процессорах, настройках системы и скорости накопителей.

Сравнение точности моделей

Model

Weights

Input

mAP50

mAP50:95

Player mAP50:95

Ball mAP50:95

Precision

Recall

RAVEL-VB-001-9f

beach-trained

18×288×512

0.5888

0.3114

0.4870

0.1359

0.9069

0.7327

RAVEL-VB-002-9f

beach-trained

9×288×512

0.6428

0.3312

0.5094

0.1529

0.7830

0.8178

RAVEL-VB-003-9f

beach-trained

9×288×512

0.5889

0.2719

0.4114

0.1324

0.8158

0.7503

YOLO26n

official COCO

640

0.3820

0.2815

0.5396

0.0234

0.8458

0.6802

YOLO26n-VB

beach-trained

512

0.5808

0.3950

0.4269

0.3631

0.8594

0.5985

YOLO11n

official COCO

640

0.4262

0.3102

0.5829

0.0375

0.9676

0.7260

YOLO11n-VB

beach-trained

512

0.6005

0.3974

0.4741

0.3208

0.7031

0.6837

Замер производительности на облачном провейдере для повторяемости

Модель

OpenVINO, FPS

CV OpenVINO

PyTorch (GPU), FPS

CV PyTorch

RAVEL-VB-001-18f

27,69

1,56%

101,99

4,15%

RAVEL-VB-001-9f

14,39

0,69%

58,53

1,55%

RAVEL-VB-002-9f

32,12

0,99%

73,10

1,55%

RAVEL-VB-003-9f

38,93

1,51%

79,84

2,33%

YOLO26n

39,48

0,84%

91,45

3,17%

YOLO26n-VB

55,09

1,33%

89,09

4,24%

YOLO11n

36,83

0,76%

97,71

0,92%

YOLO11n-VB

51,47

2,60%

94,62

2,64%

CV — коэффициент вариации FPS между повторными запусками. Чем он ниже, тем стабильнее результаты замеров.

ссылка на оригинал статьи https://habr.com/ru/articles/1064760/