Использование CoreML для сложных видеофильтров и эффектов для iPhone

Создание художественных фильтров живого видео с помощью глубоких нейронных сетей

В предыдущем проекте я работал над воспроизведением быстрой передачи нейронных стилей, преобразовывая изображение, беря художественный стиль из одного изображения и применяя его к другому изображению через глубокие нейронные сети. Хотя преобразование изображений в записной книжке на Python работает хорошо, она не очень доступна для обычного пользователя. Я хотел развернуть модель на устройстве iOS, аналогичном популярному несколько лет назад Prisma app. Более того, я хотел проверить пределы генеративной модели и преобразовать кадры в прямом видео. Целью этого проекта было запустить генеративную модель на видео в реальном времени, исследуя возможности с учетом текущих границ технологии. Это стало возможным благодаря нескольким вещам: 1) масштабирование входных данных, 2) использование графического процессора устройства и 3) упрощение модели. Поскольку это основано на предыдущем проекте, будет полезно ознакомиться с предыдущим постом.

Масштабирование входов

Многие современные телефоны могут снимать потрясающие видео в формате 4K, включая iPhone XS, на котором я работал. Хотя чип A12 в устройстве мощный, было бы слишком медленно использовать глубокую нейронную сеть для каждого кадра такого размера. Обычно видеокадры уменьшаются для распознавания изображений на устройствах, и модель запускается на подмножестве кадров. Например, приложение для распознавания объектов может запускать модель каждую секунду в кадре 224 x 244 вместо 30 раз в секунду в кадре 4096 x 2160. Это работает в случае использования обнаружения объектов, поскольку объекты не сильно меняются между кадрами.

Очевидно, это не сработает для стилизации видеокадров. Пользователю не понравится только одно стилизованное мерцание кадра каждую секунду. Однако из этого есть некоторые выводы. Во-первых, вполне разумно уменьшить размер кадра. Обычно видео транслируется с разрешением 360p и масштабируется до экрана устройства с разрешением 1080p. Во-вторых, возможно, нет необходимости запускать модель на 30 кадрах в секунду, и будет достаточно более низкой частоты кадров.

Существует компромисс между разрешением модели и частотой кадров, поскольку количество вычислений, которые графический процессор может выполнить за секунду, ограничено. Вы можете увидеть, что некоторые платформы видеочата имеют более низкую частоту кадров или большую буферизацию при использовании сверток для видеоэффектов (т. Е. При изменении фона). Чтобы понять, как выглядят разные частоты кадров и формы ввода, я создал несколько стилизованных видеороликов на компьютере с исходной нейронной сетью и OpenCV. Я остановился на целевой частоте кадров 15 кадров в секунду при входах 480 x 853. Я обнаружил, что они по-прежнему привлекательны как визуально, так и в качестве узнаваемых чисел для сравнительного тестирования.

Использование графического процессора

Я использовал tfcoreml и coremltools для преобразования модели Tensorflow в модель CoreML. Суть полного метода можно найти ниже. В связи с этим было несколько соображений. Во-первых, я перешел к пакетной нормализации вместо нормализации экземпляра. Это было связано с тем, что CoreML не имеет стандартного уровня нормализации экземпляра, и это упростило реализацию, поскольку во время интерференции в каждом пакете будет только один кадр. Пользовательский метод также можно использовать в tfcoreml для преобразования уровня нормализации экземпляра.

Далее, тензорные формы различаются между TensorFlow и CoreML. Модель TensorFlow имеет выход (B, W, H, CH), в то время как CoreML поддерживает (B, CH, W, H) для изображений. После преобразования модели в модель CoreML я отредактировал спецификацию модели, чтобы иметь транспонированный слой для адаптации к форме. Только после изменения формы вывода модели на формат (B, CH, W, H) я изменил тип вывода на изображение. Это то, что нужно сделать вручную в спецификации модели; на момент написания этой статьи tfcoreml поддерживает изображения в качестве входных параметров в качестве параметра, но не выходных данных.

Кроме того, поскольку я уменьшил масштаб изображений, чтобы передать их по сети, я смог добавить уровень масштабирования с помощью coremltools, чтобы довести изображение до разумного размера кадра 1920 x 1080. Альтернативой могло бы быть изменение размера буфера пикселей после получения результата сети, но это потребовало бы либо работы со стороны ЦП, либо дополнительной постановки в очередь на ГП. Слой изменения размера CoreML имеет билинейное масштабирование и обеспечивает удовлетворительное масштабирование с небольшими характеристиками или артефактами пикселей. Поскольку этот слой изменения размера не основан на свертках, он также добавил минимальное время ко времени вывода модели.

Еще один способ, которым я использовал графический процессор, - это отображение кадров. Поскольку я добавил к кадрам настраиваемую обработку, я не мог отправлять их напрямую в стандартный AVCaptureVideoPreviewLayer. Я использовал MTKView из Metal Kit, чтобы представить кадры, в которых используется графический процессор. Хотя шейдер Metal был простой функцией прохода (входные данные возвращались как выходные данные), рисунок оказался работоспособным, и очереди в представлении также были полезны в случае потери кадра.

Упрощение архитектуры модели

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

Я протестировал несколько различных архитектур на графическом процессоре компьютера, чтобы сузить круг наиболее производительных сетей с минимальным ухудшением текстуры. Я сохранил масштабирование по сравнению с исходной архитектурой в значительной степени согласованным, хотя я использовал только ядра размером 3 x 3. Некоторые изменения (уменьшение остаточных блоков до 1, сужение количества фильтров до 64) имели быстрое время вывода, но имели большое ухудшение качества. После тестирования графического процессора я протестировал модели на iPhone XS с чипом A12.

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

Я использовал 3 полных (неотделимых) остаточных блока для следующих результатов. Эта модель очень хорошо подходит для различных стилей и корпусов. Поскольку 15 кадров в секунду составляют 66 миллисекунд на кадр, эта реализация, вероятно, была верхней границей устройства с этой реализацией, поскольку было несколько случаев пропуска кадров или задержки.

Результаты и соображения

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

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

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

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

Связанных с работой

Передача нейронного стиля видео в реальном времени, Кейт Баумли, Дэниел Диамонт и Джон Сигмон - https://towardsdatascience.com/real-time-video-neural-style-transfer-9f6f84590832