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

Мы (Constanta) специализируемся на разработке букмекерских IT-продуктов: мобильных приложений, сайтов и в последнее время развиваем проекты в области компьютерного зрения и машинного обучения. Об одном из них и пойдет речь.

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


Мне нужны координаты и скорости всех твоих шаров и твоего кия.

Заметим, что при анализе многих спортивных игр для правильного определения результата необходимо безошибочно отследить цепочку событий. Отсюда вытекают высокие требования к надежности работы компонентов, отвечающих за определение этих событий. Поясним на простом примере: если в бильярде в среднем игроки закатывают все шары в лузы за 20 ударов, то при надежности определения исхода удара 99% вероятность определить победителя в розыгрыше составляет всего около 82% (0,9920?0,817). Матч продолжается до пяти побед одного из игроков, то есть всего происходит от 5 до 9 розыгрышей, в среднем 7. Таким образом, в среднем при такой надежности определения событий правильный результат матча получается с вероятностью всего лишь около 24% (0,8177?0,24). А ведь изначально вероятность ошибки составляла лишь 1%!

Пул “девятка”


Из всего многообразия бильярдных игр рассмотрим Пул-9. В розыгрыше побеждает игрок, битком закативший шар с номером 9 в лузу. Изначально “девятка” располагается в центре ромба из цветных шаров. Прицельным шаром, по которому должен ударить биток, является шар с наименьшим номером из имеющихся на столе. Если игрок не смог забить в результате удара ни один цветной шар или совершил фол, например не попал по прицельному шару или забил биток в лузу, ход переходит к оппоненту. Чтобы правильно засчитать очко, необходимо определять попадания шаров в лузы и все события, приводящие к смене игрока.

Компьютерное зрение


Для начала расскажем о том, как нейронная сеть получает данные. Входной информационный поток – видеотрансляция с одной камеры, расположенной над столом и снимающей с частотой 60 кадров в секунду.


Пример кадра видеопотока, обрабатываемого системой.

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


Общая схема системы.

Для решения задачи в первую очередь необходимо найти местоположение стола на кадре и всех шаров на нем. Еще один важный участник действия — кий, именно он определяет направление удара и, соответственно, траекторию движения битка. Над столом наклоняются игроки, частично закрывая его от камеры. С точки зрения анализа игры они представляют собой “посторонние предметы”, как и подставка для шаров, а также мобильные телефоны, перчатки, салфетки и прочие вещи, которые по воле игроков появляются на бортах стола. Таким образом, получается несколько целевых классов для семантической сегментации изображений: стол, его борта, лузы, кий, посторонние предметы и, разумеется, шары. При этом каждый шар представлен отдельным классом в зависимости от его цвета.

Для семантической сегментации используется полностью сверточная нейронная сеть с архитектурой LinkNet-34. Она относительно быстро работает и хорошо зарекомендовала себя в различных “боевых” задачах конкурсов по компьютерному зрению. Для определения перечисленного выше множества классов используется всего одна нейронная сеть, решающая все задачи компьютерного зрения.


Архитектура сети LinkNet-34 (см. arXiv).

На вход подаются изображения, а на выходе получается стопка “масок” всех требуемых классов. “Маски-предсказания” представляют собой двумерные массивы чисел со значениями от 0 до 1. Величина каждого элемента “маски” соответствует уверенности сети в том, что соответствующий пиксель относится к классу данной “маски”. Для итоговой классификации пикселей полученные предсказания бинаризируются пороговым фильтром.

Обучить нейронную сеть классифицировать пиксели можно на большом количестве примеров с соответствующими “масками”. Для этого мы собрали множество видео, разделили на кадры, а отдел разметки вручную подготовил “маски” для них. В сложных случаях потребовались дополнительные наборы данных. Например, когда шар “ныряет” в лузу или стоит около нее рядом с бортом стола, на него падает тень, из-за которой цвета выглядят иначе. Или, когда игрок разбивает ромб, шары летят быстро по сложным траекториям, из-за чего их изображения смазываются. Если нейронная сеть “видела” немного таких примеров, корректная классификация будет затруднительна.


Пример изображения и соответствующей ему разметки. Задача нейронной сети состоит в том, чтобы из входного изображение получать такие “маски”.

Быстро, быстрее, еще быстрее…


Конечному потребителю данных информация нужна в реальном времени (а еще лучше — быстрее риал-тайм). Для ускорения работы нейронной сети применено несколько техник, таких как объединение пакетной нормализации с 2D-сверткой (BatchNorm Fusion), что позволяет получить эквивалентную сеть без нескольких слоев. Хороший результат дает также подготовка и загрузка нового кадра параллельно с обработкой предыдущего на видеокарте. Помимо этого, на gpu выполняется часть подготовительных операций с кадрами и постобработки “масок”. Сократить суммарное время на обработку каждого кадра помогла даже простая идея — переносить результат работы сети с видеокарты в оперативную память после бинаризации в виде uint8 вместо получаемого из сети float32.

В результате семантическая сегментация одного кадра со всей требуемой пред- и постобработкой занимает в среднем всего 17 мс! А для работы системы достаточно лишь одной игровой видеокарты.

А было ли столкновение?


Координаты шаров мы определяем по “маскам”, но предварительно нужно исключить то, что лишь напоминает шар, например круглые нашивки на футболках игроков. Тут в дело вступают эвристики: проверяется форма и размер шаров, их положение относительно прошлого, хорошо известного. Далее, если с “маской” все в порядке, для обработки берется ее центроид.


Игрок в бильярд в страшных снах разработчиков.

На первый взгляд странно, но факт — результат определения положения шаров может отличаться между кадрами даже при неподвижных шарах. Объяснение простое — “зашумленность” реального видео, артефакты сжатия видеопотока, что вместе с погрешностью в определении положения смазанных изображений движущихся шаров приводит к необходимости сглаживать полученные результаты.

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


Демонстрация сглаживания определения положения и скорости шаров фильтром Калмана.
Слева: Raw: результат прямого измерения, векторы у шаров соответствуют скорости, цифры — обозначают оценку величины скорости; UKF: результат работы фильтра.
Справа: пример сглаживания направления скорости шара фильтром Калмана. Синим цветом изображены результаты измерений, красным — результат фильтрации. Резкие скачки направления соответствуют столкновениям шара.


Данные о состоянии и траектории шаров позволяют определить наступление так называемого низкоуровневого события, даже когда оно попало “между кадрами”.



Шары во время удара перемещаются так быстро, что зачастую нет кадра, на котором видно непосредственно событие, например, столкновение шаров. Поэтому для всех типов взаимодействий (столкновение шаров между собой, с бортом или попадание в лузу) вначале строится список возможных событий. Критериев здесь два. Во-первых, критически близкое взаимное расположение шаров. При медленном перемещении возникает большая относительная погрешность в определении скорости и траектории, поэтому важно расстояние между взаимодействующими объектами. Во-вторых, при большой скорости движения шаров возможные события определяются по пересечению траекторий, полученных из динамической модели. Такой подход дает весьма приятный бонус: возможность немного заранее предсказать вероятное попадание шара в лузу.


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

Изменение направления и величины вектора скорости позволяет судить, что событие, а именно столкновение, произошло. В случае, когда шар закатился в лузу, он “пропадает”. Но тут есть важный момент: необходимо использовать данные о его траектории и проверять, что шар был именно забит, а не исчез из поля зрения камеры из-за того, что над ним случайно оказалась рука игрока или иной предмет.

А если что-то пошло не так? Скажем, часть событий выпала из-за потери кадра или нависшей над столом фигуры игрока. Такие пропуски критичны для игровой логики. Спасает эвристическая система автокоррекции, повышающая устойчивость системы. Например, если определен удар по битку и падение прицельного шара в лузу, но при этом не зафиксировано столкновений битка и другие шары остались неподвижны, логично добавить столкновение битка с прицельным шаром.

Так мы играем или нет?


Шары катятся, сталкиваются, попадают в лузы… А идет ли на самом деле в этот момент игра? Или, напротив, все на столе кажется незыблемо… Значит игра остановилась? Правильный ответ на эти вопросы, вероятно, так же важен, как и определение столкновений. Когда игрок готовится к удару, обдумывает его, целится, движения нет. Но бывает и наоборот, в неигровые моменты жизнь на столе может идти весьма динамично: забитые шары перемещают из одной лузы в другую, биток могут катать по столу при его установке после фола, причем делают это в том числе кончиком кия (очень похоже на удар!). Если окончание текущего удара легко можно определить — после корректного удара все шары перестают двигаться, то с началом все не так однозначно. Конечно, можно обучить нейронную сеть обнаруживать события в видео, в том числе и настоящие удары кия по битку. А можно составить набор эвристик, которые анализируют положение и угол кия, траекторию и скорость его концов и траекторию битка после предполагаемого удара. Мы пошли вторым путем, и в результате получился очень быстрый и надежный алгоритм, определяющий текущее состояние игры.


Система пытается понять, началась игра или нет.

И кто в итоге выиграл?


Все данные о низкоуровневых событиях (удар по битку, положения и столкновения шаров, попадания в лузы) отправляются в модуль, который по их последовательности определяет, что произошел фол или корректное падение шара в лузу, переход хода или окончание игры. Беспристрастный модуль ведет счет и объявляет победителя. Особенность его в том, что он работает без всяких автокоррекций и эвристик, просто формально применяя правила игры. Блок с правилами можно целиком заменить, что позволяет без существенного вмешательства в систему адаптировать ее к локальным правилам турнира или использовать для обработки других видов бильярдных игр.
Как беспилотные автомобили до сих пор полностью не избавились от инженера-испытателя в салоне, который следит за безопасностью, так и наш модуль правил позволяет осуществлять внешнее ручное управление через web-интерфейс. Вмешательство может потребоваться, если автоматическая система ошибется. Кроме того, необходим ручной ввод отсутствующих в видеопотоке данных: о начинающем игроке, специальных ударах, которые объявляются по ходу игры голосом и т.п. Один человек потенциально может следить за несколькими играми одновременно.

Как это работает


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


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


Техническая визуализация того, как работает система. Шар около «Cue ball» обозначает с каким первым шаром столкнулся биток; «State» — состояние системы: может быть «wait» — пока игрок не совершил удар и «play» — пока шары находятся в движении; «Player» — текущий игрок; цифры около шаров обозначают оценку скорости в см/с.

Комментарии (13)


  1. S_A
    16.11.2018 10:48

    Полагаю, подобное полезно было бы не только букмейкерам.


    Впрочем, у кого деньги есть, тому и музыка :)


  1. Igor_Shumilov
    16.11.2018 11:03

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

    Например, ставка на тотал больше 0.5 в тайме футбольного матча. Т.е. пари на то, что кто-то забьёт гол.
    В начале игры коэффициент низкий и зависит от статистики/составов команд. А вот в ходе игры он начинает меняться. Причём с одной стороны он зависит от реального хода игры (если игра от ворот до ворот, то и шансы на гол повышаются), а с другой стороны от времени, оставшегося до конца тайма. Причём первое может и понижать и повышать коэффициент, а второе его только повышает.
    Получается, что если ИИ хорошо делает свою работу, просто по движению коэффициентов можно определить, что в этой игре весьма вероятен/мало вероятен гол. И надо просто дождаться какой-то минуты встречи, когда по тяжестью времени коэффициент вырастет до приемлемого игроку. Эдакий выстрел в ногу со стороны букмекера.


    1. Hardcoin
      16.11.2018 12:27

      в этой игре весьма вероятен/мало вероятен гол

      То, что он весьма вероятен, как раз коэффициент и определяет. И этот коэффициент вполне прибыльный для букмекера. Т.е. да, можно поставить на "почти гол", но и коэффициент будет 1.01, а срабатывать будет всё-таки не всегда.


      1. Igor_Shumilov
        16.11.2018 12:58

        С такой системой можно поставить на «почти гол» с коэффициентом 1.8 — 2.0 (и больше). Чем меньше времени до конца тайма, тем выше коэффициент. И если времени осталось, скажем, 10 минут, он будет весьма высок. А за это время можно наколотить пачку голов, если игра открытая и одна атака сменяется другой.
        И вот эту характеристику можно определить по поведению коэффициентов самого букмекера, благодаря его ИИ, который чётко её «читает».


        1. Hardcoin
          17.11.2018 00:37

          Вы имеете ввиду, что эта система есть у вас, но нет у букмекера? Тогда да, это потенциально возможность его обыграть. А если она у букмекера есть, что заставляет вас думать, что можно поставить на "почти гол" с коэффициентом 2?


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


          То есть если просто конец матча, то коэф растет, да. Но если голевой момент, то он резко упадет, это логично. Скауты именно за этим и нужны. Тем более ИИ-скауты.


          1. Igor_Shumilov
            17.11.2018 11:37

            Он не упадёт резко. Потому что помимо события «забьют гол», есть событие «не забью гол». Соответственно когда на первое событие коэффициент падает, на второе он растёт. И если до конца тайма остаётся 5-10 минут, и коэффициент на «забьёт» резко падает до 1.01, то коэффициент на «не забьёт» улетает куда-то в десятки. И это будет очень хорошей ставкой. Ведь футболисты могут промахнуться и по пустым воротам с трёх метров.


            1. Hardcoin
              17.11.2018 11:46

              Вы определитесь, что у вас хорошая ставка. На гол или не гол? Под конец матча, если игра вялая, коэф на "забьет" не будет 1.01. Наоборот, он будет высоким, потому что шанс низкий.


              Если же шанс гола очень велик, то коэф 10 на "не забьет" — это не хорошая ставка. А если шанс только высокий (но не крайне высокий), то и коэф будет, например, 1:2 на "не забьет".


              Где вы тут видите шанс обыграть брокера, всё ещё не ясно. Могу только пожелать удачи.


              1. Igor_Shumilov
                17.11.2018 12:17

                Для игрока нет понятия «хорошая ставка на гол» или «хорошая ставка на „не гол“». Есть просто «хорошая ставка». Это когда вероятность события, оцененная игроком, выше, чем отражено в коэффициенте (с учётом маржи букмекера).
                Условному Роналду нет разницы, забить ему на первой минуте или на 43й. Если он в порядке вероятность того, что он забьёт в каждый отдельный момент времени примерно одинакова высока. Но это для игрока. А вот для букмекера есть такие дополнительные условия как время и противоположная ставка.

                Эта система позволит игроку с минимальной ошибкой узнать о том, что Роналду в этой игре в порядке. И если он к 35й минуте ещё не забил коэффициент будет уже в районе 2, а то и выше.


                1. Hardcoin
                  17.11.2018 12:28

                  Вопрос был про ваш конкретный пример. Но вообще, если букмекер не налажал и это не договорняк — все ставки плохие. На длинном отрезке будет убыток.


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

                  Да, но это уже учтено в коэффициенте. Вы думаете, о Роналду впорядке, значит точно забьет. Но это уже учтено. И если он забьет "точно", то коэф 1.01. Но он, конечно, забьет не точно. Вы сделаете свою "хорошую ставку", на коэф 2, но сработает она с вероятностью 30%, не выше. Просто вы её оцените как 50% и решите, что надо ставить.


                  Вообще, это стандартная ошибка. Когда статистика говорит Х, то эксперт, зная эту вероятность, пытается её улучшить. По исследованиям, в среднем он точность наоборот ухудшает.


                  Но если вы игрок, это вас вряд ли убедит, конечно.


                  1. Igor_Shumilov
                    17.11.2018 12:36

                    Да, но это уже учтено в коэффициенте
                    Помимо этого в нём отражено и время до конца тайма. На которое самому Роналду наплевать.


  1. watti
    16.11.2018 13:24

    тоже занимаюсь спортивной аналитикой, только в cs:go. всегда интересно почитать про методы сбора данных в других видах спорта, но самое интересное — работу с данными вы не затронули :( у меня возникло два вопроса

    в самом начале вы привели расчет дающий 24% точность определения исхода матча
    «точность исхода удара 99%» — это перед ударом или когда уже известно как полетел биток?

    если модель дает результат меньше 50% на бинарной классификации то ясно что проще кинуть монетку и она бесполезна для решения задачи. можете привести если не примеры построенных моделей (что понятное дело приватная инфа) то хотя бы какие-нибудь интересные статистики или общепринятые метрики из бильярда?

    всегда интересно как это делается в других видах спорта. несколько лет в школе играл в бильярд на Сеге и в браузере :D


    1. NikolasEnt Автор
      16.11.2018 14:05

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

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

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


  1. watti
    16.11.2018 14:57

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

    интересно во всех ли видах спорта уже сделано распознавание или это только недавно начали делать?