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

Покедекс

Pokédex (японский: ポ ケ モ ン 図 鑑 иллюстрированная энциклопедия покемонов) - это цифровая энциклопедия, созданная профессором Оук как бесценный инструмент для тренеров в мире покемонов. .

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

Задача Pokedex - идентифицировать покемона, а это значит, что классификация достаточно хороша. Но я хотел попробовать то, чего никогда раньше не делал, хочу отметить покемона на картинке. И не просто ограничивая покемона рамкой, я хочу отмечать пиксели и делать это в реальном времени.

Вместо модели, которая выводит процент для каждого покемона, эта модель выводит для каждого пикселя, какого покемона он представляет. Как мы уже знаем, в контролируемом обучении, чтобы что-то предсказать, нам нужно пометить это. Где взять картинки покемонов и в каком пикселе какой покемон? Мы собираемся пометить это вместе! (подробнее об этом позже). Я использовал кадры из первого сезона сериала «Покемон» и пометил эпизод (это заняло около часа).

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

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

Тренировка на протяжении одного эпизода, который я тренировал, дала мне хорошую отправную точку

Фактическое устройство

Моя первоначальная мысль заключалась в том, чтобы создать устройство с использованием Raspberry Pi, но это означало, что мне нужно было иметь дисплей, аккумулятор, камеру, динамики и несколько других вещей, о которых я, вероятно, не подумал. Чтение этого длинного списка продуктов кажется утомительным, но потом я понял, что простой телефон включает в себя все эти функции. Итак, я купил старый телефон.

Запуск модели на телефоне - сложная задача, особенно при запуске с несколькими кадрами в секунду. К счастью, Google (ссылка здесь не нужна) опубликовала TensorFlow lite (с этого момента TFlite). TFlite - это легкий оптимизированный Tensorflow. Можно преобразовать их модель Tensorflow в модель TFlite, и она (надеюсь) будет работать быстрее и легче.

Реагировать на родной

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

Родное приложение для Android

Хорошие люди из TFlite опубликовали несколько очень хороших примеров использования в приложении для Android. Так что я взял нужные мне части из каждого приложения и заполнил пробелы своими собственными вещами.

По сути, я объединил 3 примера приложений в одно. Демонстрационное приложение сегментации не запускается в потоке камеры, демонстрационное приложение обнаружения использует устаревший API Android, а классификация ничего не отображает в предварительном просмотре. Создание (копирование-вставка, но вы это понимаете) нативного приложения было намного быстрее и намного приятнее, чем использование React Native с TFlite.

Модель TensorFlow создается многими операторами, и, к сожалению, еще не все из них можно преобразовать в TFlite. Моя модель включала операторы, которые еще не поддерживаются TFlite, поэтому я столкнулся с этой дилеммой. Я решил не отказываться от этих операторов и использовал делегат Flex, что сделало приложение довольно тяжелым, но сохранило успешную архитектуру без изменений.

Операторы TFLite не поддерживают одного из операторов выбранной мной модели. Делегат Flex - это способ запускать обычные операторы TensorFlow в интерпретаторе TFlite, модель будет работать медленнее, а приложение будет весить больше, но, по крайней мере, я могу использовать выбранную мной архитектуру. Вот почему приложение такое тяжелое.

Запуск модели в моем приложении для Android выводит нули, массив из 30К нулей. Явно что-то не так. Непосредственный подозреваемый - это я. Я предполагаю, что я неправильно использую модель в приложении для Android. Исходная модель TensorFlow отлично работает в Python, но я не могу протестировать модель TFlite, поскольку делегат Flex не поддерживается в Python (пока). Итак, я создал фиктивную модель, построенную только с помощью операций, поддерживаемых TFlite, чтобы протестировать ее на Python. Прогнозы хорошие, теперь займемся Андроидом. Ух ты, наконец-то я получаю числа, отличные от нуля!

Вероятно, что-то не так с импортированной мной моделью или с гибким делегатом . Подождите! Выходные данные в приложении Android являются целыми числами, а в Python - числами с плавающей запятой. Может ли быть так, что предыдущая модель работает, но поскольку ее выходные данные представляют собой числа с плавающей запятой в диапазоне от 0 до 1, она всегда будет округлять их до 0?

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

Изменение кода на usegetFloatArray решило «проблему».
Неинтересно тратить столько времени на такую ​​глупую ошибку, но эй, я многому научился благодаря этому.

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

В дикой природе

Теперь, когда приложение заработало, пора протестировать! К сожалению, в городе, в котором я живу, покемонов нет, пришлось уйти в дикую природу.

Демо работает нормально! Но поскольку я пометил только один эпизод, результаты не очень точные, и это работает для очень немногих покемонов. Здесь вы все можете помочь! Данные тегов! Я создал небольшой учебник, чтобы вы узнали, как добавлять теги (пользователь и пароль для системы тегов указаны в учебнике).

После удаления всей информации, связанной с покемонами, из информации о приложении (если Google спросит, вы все опознаете существ, а не покемонов), я наконец смог загрузить приложение в Google Play! Как я уже упоминал ранее, поскольку я использую обычный TensorFlow, приложение очень тяжелое. В следующих версиях я буду использовать архитектуру, которая работает на TFLite без гибкости.

Теперь, став сертифицированным тренером по покемонам (нейронные сети), я могу начать работу над другими проектами.