Детекция волейбольного поля / корта

Детекция волейбольного поля / корта

2026/01/08

Для автоматического анализа видео игры в волейбол желательно автоматически определять ключевые точки волейбольной площадки и сетки. Альтернатива — ручная разметка площадки для каждого видео перед началом анализа. Изучая существующие решения, наткнулся на репозиторий TennisCourtDetector. Проект 2022 года — время применения U-Net архитектуры для детекции в спорте. Небольшой простой проект со ссылкой на датасет более 8000 размеченных данных и предобученные веса — что позволяет провести собственные эксперименты.

Шаг первый - запуск tennis court detector

Клонируем репозитарий

Так как с момента последнего коммита прошло больше 3 лет (2023 г.), нужно актуализировать версии Python и библиотек. Маленький размер кода позволяет это сделать без особых проблем с использованием vibe coding

Ссылка на форк с поправленными зависимостями (в оригинальном репозитории автор давно не проявлял активность):

git clone https://github.com/asigatchov/TennisCourtDetector.git

Tracknet - для keypoints court

2023 год — пик работ в области детекции мелких спортивных объектов (теннисный мяч, волан в бадминтоне). Предположу, что на этой волне автор реализовал возможность детекции ключевых точек теннисного корта — 14 точек.

Классическая модель TrackNet, где для детекции маленького теннисного мяча подаётся 3 последовательных кадра в размере 640×360 — на выходе получаем тепловую карту среднего кадра (может быть реализация, где 3 кадра, и центральный имеет выше точность).

Dataset - залог успех

Автор предоставляет ссылки на датасет из 8000 картинок с JSON-описанием координат размеченных точек площадки. Для составления датасета использовался полуавтоматический метод: Обнаружение линий (с помощью преобразования Хафа). Источник —- Tennis Analysis using deep learning

Изучение и эксперименты

После запуска кода выяснил, что скорость работы — 1 fps на CPU и 23–36 fps на GPU (5070). Для ускорения работы было принято решение уменьшить число параметров сети за счёт уменьшения размера картинки до 512×288 (подсмотрено у современных моделей TrackNetV2/V4) и перевести кадры в чёрно-белый (1 канал вместо 3). Обучение на обрезанных данных позволило ускорить цикл обучения и немного ускорило выполнение.

Формат датасета и почему выбрал COCO

Для хорошего результата в обучении нужны размеченные данные. Ключевой момент — хорошо размеченные. Изучив данные разметки для теннисного корта, я понял, что используется пользовательский формат. Это значит, что в начале нужно разметить в один из популярных форматов, а потом конвертировать. Или модифицировать загрузчик данных под COCO-формат, а пользовательскую разметку для теннисного корта — конвертировать в COCO. COCO-формат поддерживают популярные инструменты разметки данных. Один из них — Roboflow. Roboflow имеет ежемесячный лимит кредитов, который покрывает любительские потребности. Написал CocoCourtDataset (загрузчик данных) и конвертер data_train.json → _annotation.coco.json. Тестовый цикл обучения показал, что всё проходит корректно.

Разметка волейбольного поля / корта

Так как конечная цель — работа с видео от моих любительских камер, то общедоступные датасеты не подходят. Экшен-камеры имеют рыбий глаз, и разметка от TV не подойдёт — будет работать некорректно. Первую попытку разметки я попытался сделать в Roboflow. Процесс оказался долгим, и, как выяснилось после разметки 50 кадров, данные я разметил некорректно, не разобравшись с skeleton и отрисовкой точек. Как говорится в классике — настоящие герои всегда идут в обход. Используя CV2, пишем свою среду разметки на минималках. Изначально хотел разметить 10 точек площадки (4 угла и 6 пересечений боковой линии). Затем подумал: а почему в теннисе не размечают сетку? — и добавил ещё верхние края сетки у антенн. В процессе разметки в Roboflow понял, что 8 точек размечать быстрее, чем 12, и сократил точки 3-метровых линий. Для теста я взял 15 видеозаписей игр с задней линии. Сделал автоматический механизм копирования точек. Камера неподвижна — значит, можно разметить первый кадр и переносить разметку дальше. Добавил кнопку A — авто листает видео по 50 кадров и сохраняет разметку. Кнопки N и P для перехода между точками по кругу.

Court-Keypoint-Detector

/media/photos/cv_annotatot_tools.jpg

yolo11m-pose - для определения ключевых точек площадки

Наличие данных позволяет проводить эксперименты с другими архитектурами сетей. Для сравнения решил попробовать обучение YOLOv11-pose. YOLOv11 от https://www.ultralytics.com/ позволяет быстро и просто дообучить нейронную сеть под свою специфику. Малое количество данных YOLO пытается компенсировать через аугментацию данных (искусственное изменение): наклоны, масштабирование, мозаика, повороты и т.д. Беглый тест показал, что можно смело брать модель — дообучать и использовать. Визуально на тестовых видео лучший результат был на конфигурации с mosaic.

data_yml = 'data/yolo-datasets/data.yaml'
results = model.train(
    data=data_yml,
    epochs=150,                  # Custom kp требует больше эпох
    imgsz=1280,                  # Сохраняем детали корта
    batch=4,                    # Auto-batch (или 8-16 вручную)
    device=0,                    # GPU
    patience=50,
    augment=True,                # Критично для вариаций кортов (освещение, угол)
    hsv_h=0.015, hsv_s=0.7, hsv_v=0.4,
    degrees=20,
    translate=0.2, 
    scale=0.9, shear=10.0, fliplr=0.5,
    mosaic=1.0, mixup=0.5,      # Сильные аугментации для generalization
    optimizer="AdamW",
    lr0=0.001,
    close_mosaic=20,
    name="volleyball_court_yolo11m_pose_mosaic_bl",
    project="runs/yolo11m_pose",
    exist_ok=True
)

Ручная augumentation данных

Разметил около 2800 кадров. Если уникализировать связку камера+место установки, то получается около 20 ± уникальных кадров, на которых перемещаются игроки. Для подготовки модели к видео, которых не было в обучении, и имитации разных наклонов камеры решил сделать поворот кадра на 10 градусов в одну из сторон. Сложность заключается в том, что одновременно с кадром нужно поворачивать и ключевые точки. Важным моментом является тестирование и контроль совпадения ключевых точек после поворота. Сюрприз возник в том, что модель имеет scale=2 по размеру вход/выход: на вход 512×288, на выходе 256×144. Первый вариант модели имел низкую точность, при локализации проблемы винил несогласованность кадра и точек после поворота. Отладка и попытки вывести, что подаётся на обучение, вызывали сложности, так как требовали прокидывания параметра о режиме отладки. Простым вариантом оказалось применение flag-file:

if os.path.exist('./tmp/debug.txt'):
    save_image_and_heatmaps(...)

и упрощение кода поворота

img_rotation_matrix = cv2.getRotationMatrix2D(img_center, angle, 1.0)

hm_rotation_matrix = cv2.getRotationMatrix2D(hm_center, angle, 1.0)

А так же добавление промежуточных примеров чему научилась модель на этапах валидации

/media/photos/val_vis_frame_2_epoch_6_iter_34.jpg

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

Подробнее об этом в следующей статье.

/media/photos/val_vis_frame_3_epoch_56_iter_44.jpg