Могут ли игральные кости быть нечестными? Чтобы ответить на этот вопрос, недостаточно просто бросить кости пару раз. Нужны тысячи, а лучше сотни тысяч бросков. Делать это вручную — путь в никуда. Поэтому мы решили научить компьютер делать это за нас. В этой статье — история о том, как мы создали систему, способную распознавать игральные кости в реальном времени, и с какими трудностями столкнулись.
Первая задача состояла в самом распознавании игральных костей, значении грани и цвета кости в реальном времени из любого источника. Существует два основных подхода к решению этой задачи: линейные алгоритмы компьютерного зрения(OpenCV) и нейронные сети (ИИ).
Преимущество ИИ заключается в том, что готовое решение хорошо себя показывает при изменении условий:
цвета костей,
количества костей,
фокуса,
ракурса,
разрешения камеры,
освещенности и т.д.
Вдобавок, обученная модель легко расширяема: если вместо точек на гранях будут цифры, то её можно дообучить на новых данных.
Начали мы с простого — OpenCV. Как и ожидалось, такое решение оказалось не устойчиво ко всем выше перечисленным изменениям условий, поэтому приступили к поиску фреймворка для обнаружения объектов с помощью ИИ. Выбор пал на Ultralytics YOLO — знаменитая модель для обнаружения и классификации объектов в реальном времени:
основан на передовом прогрессе в области глубокого обучения и компьютерного зрения
предлагает непревзойденную производительность в отношении скорости и «точности»
предоставляет удобный API на питоне
предоставляет CLI для обучения, предсказания и прочих действий.
Этап первый: подготовка к обучению
Обучение модели требует большой датасет из наборов пар - внутри каждой содержится из изображения и файла разметки. Разметка представляет из себя обычный текстовый файл с информацией: где на изображении располагаются кубики и значения граней.

Структура файла разметки представляет из себя строки, содержащие название класса, нормализованные координаты центра и нормализованную высоту с шириной:
название класса | нормализо- | нормализо- | нормализо- | нормализо- | |
Кость #1 | 6 | 0.425 | 0.597 | 0.03 | 0.053 |
Кость #2 | 6 | 0.442 | 0.319 | 0.03 | 0.041 |
Кость #3 | 5 | 0.206 | 0.502 | 0.032 | 0.05 |
Кость #4 | 4 | 0.268 | 0.725 | 0.034 | 0.057 |

Есть много инструментов для упрощения создания датасетов, так как их требуется несколько тысяч. Выбор пал на open source программу «LabelImg»: примитивно, просто и бесплатно. Для первоначального датасета этого вполне достаточно. С её помощью создание датасета свелось к простейшим манипуляциям: выделение мышкой костей на изображении и выбор значения грани.

Чувствуем вашу мысль: «Даже с подобными инструментами, создание нескольких тысяч наборов потребует месяцы работы!», согласны с мыслью! Посему скачали уже готовые наборы с игральными костями(из открытых источников): kaggle и Roboflow. Поскольку наборы находятся в различных источниках,каждый пользователь размечал и сохранял данные по-своему,
Нам потребовалось время, чтобы привести их к одному виду и формату YOLO, но оно того стоило!
Этап второй: обучение
Для обучения модели требовались большие вычислительные мощности: в основном CUDA и тензорные ядра видеокарты. Но для начального этапа нам было достаточно офисного ПК:
Материнская плата - Gigabyte B460M
Процессор - Intel i7-10700F
Видеокарта - GT1030
ОЗУ - 16GB
SSD - 256GB
Такой конфигурации достаточно для определения вектора разработки, но даже с ней обучение на скачанном датасете в размере 2 000 заняло всего 20 часов. Обученная модель имела неплохие результаты «точности», но работала только с тестовыми наборами данных. Вот тут и появилась первая проблема: профессиональные игральные кости - прозрачные, и нижняя грань просвечивается. В этой связи наша модель не может распознать значения граней правильно, да и в готовых датасетах отсутствовали такие кейсы.

Для решения этой проблемы пришлось прибегнуть к ручной разметке в LabelImg: добавили в стартовый датасет около 200-300 наборов с ручной разметкой и запустили следующую итерацию обучения.
Новая модель научилась распознавать профессиональные кости в реальном времени, но со средней «точностью». С увеличением датасета время обучения линейно увеличивается - потребовалось примерно 23 часа.

Эта модель открыла бОльшие возможности для дальнейшего обучения и применения. На её основе мы уже можем разработать некоторые инструменты, которые будут помогать в дальнейшем обучении:
Проверка датасета на наличие ошибок с помощью модели, обученной на этом же датасете:
прогнав датасет через модель и отсортировав результаты наборов по «точности» распознавания, можно взять часть, примерно 10%, наихудших результатов и проверить их вручную через LabelImg. С большой вероятностью, найдутся наборы, содержащие ошибки при ручной разметке - они очень портят итоговый результат модели.Полуавтоматическое дополнение датасета:
теперь необязательно размечать наборы вручную с помощью LabelImg. Достаточно показать кости с любого видеопотока и они определяются моделью Далее нужно только вручную подтвердить валидность, т.к. модель может ошибиться и набор сохранится в датасет.
Имея модель с приемлемой «точностью» и инструментами, можно определить цикл обучения для дальнейшего улучшения качества распознавания:
Проводим проверку датасета инструментом №1
Добавляем в датасет новые данные инструментом №2
Начинаем процесс обучения

После 5-7 таких циклов размер датасета увеличился до 5 000 наборов, «точность» вышла на приемлемый уровень но уперлась в «потолок» из-за ограниченной мощности ПК.


В данный момент обучение модели происходит в низком разрешении изображений 640. Для повышения «точности» распознавания нужны наборы данных в высоком разрешении 1920, но это невозможно с данной конфигурацией ПК. Поэтому собираем новый:
Было | Стало | |
Материнская плата | Gigabyte B460M | Gigabyte Z790 AORUS ELITE |
Процессор | Intel i7-10700F | Intel i7-12700K |
Видеокарта | GT1030 | RTX 4080 |
ОЗУ | 16GB | 64GB |
SSD | 256GB SATA | 1TB M2 |
CUDA / TENSOR ядра | 384 / 0 | 9728 / 76 |
Время обучения на одинаковом датасете | 28 минут | 15 секунд |
Запускаем обучение на текущем датасете в высоком разрешении 1920 и параллельно - обучение другой модели для распознавание цвета кости. В результате «точность» значительно выросла.

Продолжим увеличивать датасет, но в этот раз сделаем это быстрее! Где же можно найти столь много материала? Ответ прост - записи чемпионатов игры в нарды. Для получения видеопотока из интернета, в частности Ютуб, будем использовать OBS studio, через которую эмулируем веб камеру, которая транслирует видеоролик. Такой подход позволяет нам не менять программну�� часть и быстро менять ссылки на источник видео.

Таким способом мы быстро собираем около тысячи наборов для датасета, проверяем и снова запускаем обучение. Новая модель даёт ещё больше возможностей - например обрабатывать изображения 4к со сложным фоном.


Так как «точность» поднялась на высокий уровень, мы запустили автоматическое дополнение датасета: разработали инструмент, куда передается список ссылок на ютуб видео, которые далее скачиваются, и в нём модель находит наборы данных, которые добавляет в датасет. Для примера: выбрано 5 видео с играми в нарды общей продолжительностью около 20 часов. Разработанному инструменту потребовалось 3-4 минуты для обработки всех кадров, обнаружения 2 000 наборов данных и добавления их в общий датасет для дальнейшего обучения.
В итоге получилась обученная на датасете размером 10 000 модель для распознавания игральных костей любого типа. Скорость распознавания, вне зависимости от количества костей в кадре, составляет около 80 кадров в секунду (разрешение 1920рх). Ниже - таблица улучшения распознавания модели при увеличении датасета.Обозначим, что все модели обучались при стандартных гиперпараметрах, кроме разрешения:
итерация обучения | размер датасета | mAP50 | mAP50-95 | комментарий | время обучения |
1 | 2 000 | 0.88 | 0.77 | скачанные датасет | 20 часа |
2 | 2 300 | 0.92 | 0.81 | добавление 300 собственных наборов | 23 часа |
2-9 | 5 000 | 0.95 | 0.86 | 50 часов | |
10 | 5 200 | 0.96 | 0.89 | Новый ПК и добавление наборов высокого разрешении | 5 часов |
10-20 | 7 000 | 0.97 | 0.92 | 7 часов | |
21 | 10 000 | 0.98 | 0.94 | добавление наборов в автоматическом режиме | 10 часов |
22 | 11 000 | 0.994 | 0.96 | последняя проверка датасета на ошибки | 11 часов |
Последний этап: оценка точности модели
Сейчас мы разберёмся почему «точность» всю статью была в кавычках и опустим их. На рисунках 5, 7, 10, 11, помимо значения грани кости, присутствует дробная величина, которая варьируется от 0 до 1. Это значение не является точностью или вероятностью распознавания, как многие это считают - значение называется уверенностью. Модель YOLO при обнаружении объектов выдает так называемую оценку уверенности для каждого найденного объекта. Эта величина не является точностью или вероятностью в привычном смысле. Скорее, это комбинированный показатель, который отражает:
насколько модель уверена, что в данной области изображения действительно есть какой-то объект.
насколько хорошо модель подобрала границы этого объекта по сравнению с реальными (эталонными) границами.
Иными словами, если уверенность высокая — это значит, что модель считает, что объект точно есть, и она довольно точно определила его положение. Но это не «чистая» вероятность, и напрямую сравнивать её с метриками вроде точности или вероятности нельзя — она рассчитывается по внутренним правилам модели и используется в основном для фильтрации слабых или сомнительных предсказаний.
Значение уверенности в итоговой модели варьируется в пределах 0,85-0,95. А устраивает ли нас данная уверенность модели для ее дальнейшего применения? По многочисленным результатам исследований был выявлен условный порог уверенности, равный 0,8. Исследование заключалось в отслеживании значения уверенности с каждым кадром при постепенном ухудшении условий распознавания: изменение фокуса, освещённости, дальности, а затем снова улучшения, чтобы оценить стабильность.

На графике наглядно видны провалы функции уверенности до 0 - модель неверно распознала грань. Тут мы делаем вывод, что при значении уверенности ниже 0,8 начинают появляться разного рода осцилляции и срывы функции, что недопустимо. Это доказывает экспериментальным путём стабильную работу модели при уверенности больше 0,8.
Заключение
Для итоговой модели мы использовали датасет из более чем 10 000 наборов реальных фотографий, а не синтетических, которых можно сгенерировать огромное количество за пару часов. Именно это нам дало сильную устойчивость к разному фону, разрешению камеры, углу, фокусу, типа кубика, освещению и т.д. как можно заметить на рисунках 7, 8 и 11. Такая модель идеально подходит для следующего масштабного этапа — математическому анализу частоты выпадения граней и автоматическому устройству, которое бросает кости сотни тысяч раз подряд.