Augmented reality для Dota2

в 16:51, , рубрики: android, opencv, обработка изображений, Разработка под android

Предлагаю вашему вниманию суровую историю о разработке программы машинного зрения под Android с использованием OpenCV. Задача такова — необходимо распознать вражеских героев на экране и показать победоносную комбинацию для своей команды.

Augmented reality для Dota2 - 1

План работ

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

Для начала было решено разработать x86 приложение (C++ / OpenCV), позже портировать под Android с реальной камерой. Нужен был быстрый и точный алгоритм сравнения изображений. После продолжительного поиска выяснились наиболее популярные подходы:

  • Simple euclidean distance
  • Cross Correlation
  • Histogram comparison
  • Detectors of salient points/areas

Остальные варианты отброшены как слишком сложные или не реализованные в OpenCV.

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

  • Подготовить двоичную маску иконок
  • Найти контуры
  • Отфильтровать ложные срабатывания
  • Запустить потоки распознавания

Оригинальное изображение:

Augmented reality для Dota2 - 2

Маска:

Augmented reality для Dota2 - 3

Контуры героев:

Augmented reality для Dota2 - 4

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

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

Долго боролся с проблемой сравнения похожих иконок, но в итоге забил, т.к. редкое явление. Например, входное изображение A распознается как герой C:

Augmented reality для Dota2 - 5

Итого, по результатам распознавания погрешность около 10%, один кадр на Core i5 вычисляется до 200ms, на Nexus7 до 2sec. Наверняка можно много чего оптимизировать, но для прототипа было достаточно.

Основной функционал приложения был готов, оставалось портировать его на Android, добавить поддержку камеры и отобразить результат. Тут я очень сильно ошибался, около 70% времени работы над приложением ушло на борьбу с багами Android на разных устройствах.

Особенно порадовал camera API. Управление фокусом, разрешение видео искателя и фотографии – все это может вызвать проблемы вплоть до полного зависания. Советую тестировать на малобюджетных китайских телефонах, чтобы поймать максимум багов.

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

Небольшой совет по оптимизации размера apk. Весь native код я собрал в одну shared library и удалил лишнее, в результате общий размер сократился в 3 раза:

CFLAGS := -DANDROID_NDK -DNDEBUG -O3 -Ofast -flto -fvisibility=hidden -ffunction-sections -fdata-sections
LDFLAGS := -Wl,--gc-sections -Wl,--exclude-libs=ALL

Автор: realimba

Источник

Поделиться новостью

* - обязательные к заполнению поля