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

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

Основным фидбеком было — что за каменный век использовать олдскульные технологии, обучаешь нейросеть и погнали. Я пробовал, но не взлетело — очень часто мяч настолько размыт, что его даже человеческим глазом не отличить от случайной кляксы, и даже простой бинарный классификатор не дает стабильных результатов, чего уже говорить о детекторах и прочих YOLO.

В общем, я это дело подзабросил, но вот весной завел себе дрон и конечно же первым делом приспособил его для волейбольных съемок. Если поднять его на нужную высоту (12–15 метров), в кадр влезает вся площадка, что дает прямо неограниченные возможности для анализа.

c888749d35984887240a916d577044d8.jpg

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

Шум и никакого мячаШум и никакого мяча

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

d7878c4b5348b72531806999f11b655f.gif

Для сравнения — похожая подача при старом подходе выглядит вот так:

ff90a686b451fc7951946d9a706d82b2.gif

Делать нечего, придется искать другие подходы. У нас есть OpenCV, так что далеко идти все равно не придется. Вместо фона выделяем границы помощью фильтра Канни — и у нас есть черно-белый скетч для дальнейшего разбора.

      gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
      gray = cv.GaussianBlur(gray, (5, 5),0)
      mask = cv.Canny(gray, 50, 100)

Если натравить на него детектор контуров — все прекрасно работает, мяч удается зацепить. Дальше подключается детектор траекторий и процесс идет как и в основном алгоритме.

      mask = backSub.apply(frame)
      mask = cv.dilate(mask, None)
      mask = cv.GaussianBlur(mask, (15, 15),0)
      ret,mask = cv.threshold(mask,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)
e35a8b3bad5e05ccf99372183340f559.gif

И опять же для сравнения — тот же фрагмент с неподвижной камеры с границами:

0719632d4ef7745e7265e63150aca6e8.gif

Как видно, палка имеет два конца — на трясущемся дроне Канни-фильтр дает лучшие результаты, а на статичной камере — генерит лишний фон, на котором теряется мяч.

Но что будет, если эти два подхода совместить? Для видео с дрона Канни сначала оставит только нужные фигуры, а затем, можно удалить фон.

Получается картинка не без шума, но его можно уже фильтровать, и мяч уже видно.

b0e7efd2aba405f667acbcd7042c6d49.gif

Результат — гораздо лучше, шума меньше (но есть еще) и траектория мяча распознается достаточно четко.

6a77ad1821012cfdf136a5dfb39ff698.gif

Прошлые статьи на эту же тему

Распознавание мяча в волейболе с OpenCV и Tensorflow
После первого опыта распознавания спортивных движений у меня зачесались руки сделать что-нибудь еще …
habr.com
Волейбол глазами компьютера
В прошлой статье я рассказал о своих подходах по распознаванию волейбольного мяча в игре. Задача сам…
habr.com
Архитектура облачного волейбольного сервиса
Не так давно я писал про волейбольный сервис, теперь пришло время описать его с технической точки зр…
habr.com

© Habrahabr.ru