Гостевой пост Куну Пак, Мугунг Ким, Ынсунг Хан

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

Вот почему в VoyagerX мы разработали vFlat, приложение для Android, которое использует глубокое обучение для решения этой проблемы. Приложение vFlat позволяет пользователям легко сканировать свои книги, не беспокоясь об изогнутых страницах. Он также пытается уменьшить ручной ввод со стороны пользователей, автоматически определяя границы страницы книги.

Это удобно, когда пользователь пытается извлечь текст из фотографии страницы книги с помощью OCR (оптического распознавания символов). При извлечении текста из «левого» изображения выше OCR не может правильно распознать некоторые слова и текстовые строки из-за того, что они слишком изогнуты. Однако применение этой же технологии к «правильному» изображению дает гораздо больший процент успеха и позволяет извлекать текст с небольшими ошибками.

Как мы создали приложение vFlat

Мы разработали модель глубокого обучения, которая выравнивает изогнутые страницы книг, и решили сделать это на мобильных устройствах, чтобы обеспечить максимальное удобство для конечных пользователей. В приложении vFlat есть функция «предварительного просмотра в реальном времени», при которой пользователи могут видеть страницу книги, выровненную в реальном времени (выше 20 кадров в секунду). Если пользователи могут предварительно просмотреть отсканированную страницу как сплющенное изображение в реальном времени, просто используя приложение, они могут отрегулировать угол и рамку перед съемкой.

Чтобы добиться вывода в реальном времени в мобильном приложении, мы оптимизировали нашу обученную модель и воспользовались преимуществами аппаратного ускорения. Наша первоначальная мысль заключалась в том, чтобы реализовать модуль вывода с помощью OpenGL самостоятельно, поэтому мы готовились реализовать слои модели с помощью GLSL (OpenGL Shading Language).

К счастью, мы наткнулись на поддержку графического процессора TensorFlow Lite и решили попробовать (на момент написания версия пакета tenorflow-lite-gpu была обновлена ​​до 'org.tensorflow: tensorflow-lite-gpu: 0.0 .0-nightly '). Мы сократили количество весов и сложных операций, чтобы разработать облегченную версию модели, и использовали делегат TFLite GPU для аппаратного ускорения.

Глубокие нейронные сети отлично подходят для графических процессоров, поскольку они обладают большей вычислительной мощностью, чем процессоры, и превосходны при обработке массивных параллельных рабочих нагрузок. Но использование мобильного GPU - нетривиальная задача; вот тут-то и появляется делегат TFLite GPU.

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

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

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

Например, поскольку операция LeakyReLU не поддерживается делегатом TFLite GPU, нам пришлось использовать поддерживаемую операцию PReLU следующим образом:

Путем изменения

> tf.keras.layers.LeakyReLU(alpha=0.3)

to

> tf.keras.layers.PReLU(alpha_initializer=Constant(0.3), shared_axes=[1, 2], trainable=False)

Однако мы столкнулись с неожиданным поведением, когда попытались уменьшить количество параметров в операции PReLU до 1, разделяя все оси (shared_axes = [1,2,3]). Хотя этот код работал нормально в режиме ЦП, делегат ГП завершился с ошибкой «Линейная альфа-форма не соответствует количеству входных каналов». Поэтому мы закончили тем, что разделяли параметры только по осям 1 и 2.

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

> tf.keras.layers.Lambda(lambda x : (x / 127.5) — 1.0)

Кажется, это работает с делегатом GPU, но при фактическом запуске он возвращается к CPU без предупреждения. Обычно, когда это происходит, TFLite предупреждает нас таким сообщением, как «Не удалось применить делегат. Только первые M ops будут выполняться на GPU, а оставшиеся N - на CPU ». Поэтому будьте осторожны при использовании слоев Lambda и всегда старайтесь измерить фактическое время вывода, прежде чем продолжить.

Заключение

Хотя на этом пути возникло несколько препятствий, мы сократили время вывода нашей модели более чем наполовину с помощью делегата TFLite GPU. Наконец-то мы смогли предоставить пользователям функцию «предварительного просмотра», при которой сплющенные страницы отображаются в реальном времени.

Мы можем с уверенностью сказать, что использование делегата TFLite GPU было отличным выбором, и настоятельно рекомендуем попробовать его тем, кто хочет развернуть свою обученную модель на мобильном устройстве.

Чтобы узнать больше и попробовать сами, прочтите Делегат TensorFlow Lite GPU.