В системе iOS 12, выпущенной в этом году, Apple представила интересную новую функцию — Memoji, представляющую собой новый тип Animoji, который может использовать переднюю камеру телефона для создания собственного эксклюзивного анимированного аватара. Когда эта функция была впервые запущена, в Интернете была волна сообщений Memoji.
Играя в Memoji, задумывались ли вы когда-нибудь о создании Memoji из фотографии? В этой статье представлены результаты эксперта по машинному обучению Пэта Нимейера, использующего нейронные сети для создания соответствующих Memoji для фотографий реальных людей. В частности, он протестировал модель VGG16Face, сеть, обученную распознаванию лиц, чтобы увидеть, насколько хорошо она работает при сравнении реальных фотографий с Memoji, которые «выглядят» как различные объекты. Затем используйте его для выбора функций для создания Memoji для новых объектов.
Кодовый адрес находится в конце текста.
спойлер
На двух рисунках выше показаны сгенерированные результаты нейронной сети. Это оставляет желать лучшего, но я нахожу это интересным и не только простым, но и эффективным. Я лично чувствую, что нейронная сеть может не обрабатывать эти Memoji как человеческие лица, и есть несколько недостатков, позвольте мне перечислить их:
- мультяшное изображение
Во-первых, первый вопрос: на что похоже «выглядеть», когда люди представлены в мультяшном виде? Мультяшные изображения могут преувеличивать самые очевидные черты персонажа, но некоторые черты, такие как прически, не являются постоянными по своей сути, сильно меняются от фотографии к фотографии и даже меняются изо дня в день. По этой причине кажется, что обучение нейронной сети, способной идентифицировать людей, может абстрактно собирать информацию о прическах, учитывающую это изменение. И наоборот, это означает, что он может не подходить для создания причесок из случайных изображений.
- оттенок кожи и цвет волос
Трудно определить оттенки кожи на фотографиях, сделанных в случайных условиях освещения, и я провел простой тест, который показал довольно плохие результаты. При тестировании нейронная сеть часто выбирала более светлые тона кожи и всегда плохо различала реалистичные и нереалистичные варианты (не показано). Кроме того, в то время как тест хорошо различал светлые и темные волосы, он был более или менее неверным, когда дело дошло до демонстрации ярко окрашенных волос.
- нет API
Одно из ограничений, с которым я столкнулся, экспериментируя с созданием Memoji, заключается в том, что в настоящее время нет API для их пакетного создания (нет прямого способа автоматизировать их на iOS). Это ограничивает нас в эффективном поиске возможных доменов Memoji как части процесса генерации. В идеале мы хотели бы использовать генетический алгоритм для значительной оптимизации комбинации признаков, а не полагаться на их разделимость, но в данном случае это невозможно.
- подборка фотографий
То, какую фотографию вы решите использовать для создания своих Memoji, также сильно повлияет на конечный результат. Некоторые фотографии дают гораздо лучшие результаты, чем другие, и я не знаю, почему. В общем, я стараюсь найти репрезентативные фотографии, хорошо обрезанные и обращенные лицом вперед.
Нейронные сети и настройки
Фактический код этого эксперимента на самом деле очень мал, я буду рассказывать о нем по порядку, а ссылка на исходный код находится в конце статьи.
- VGG
VGG — очень популярная архитектура нейронной сети для распознавания изображений. VGG Face реализует модель, предназначенную для распознавания лиц, и всю обученную сеть (включая информацию о сетевом уровне и веса обучения) можно загрузить и использовать публично. Так что использование такой предварительно обученной модели — один из лучших вариантов, обучение такой модели с нуля занимает много времени.
- Torch
Я использую инфраструктуру научных вычислений Torch, которая предоставляет среду, необходимую для запуска моделей VGG, среду программирования на основе Lua, библиотеки для математических вычислений с тензорами и стандартные блоки для построения нейронных сетей. Я выбрал Torch, потому что много раз им пользовался.
Torch может загрузить нам хорошую модель лица VGG и запустить на ней изображение всего несколькими строками кода. Основной процесс:
-- 加载神经网络
net = torch.load('./torch_model/VGG_FACE.t7')
net:evaluate()
-- 应用图像
img = load_image(my_file)
output = net:forward(img)
Есть еще несколько шагов, связанных с загрузкой изображений и нормализацией изображений, которые можно найти в исходном коде.
- Используйте сетевой уровень
Как показано на рисунке выше, VGG содержит различные типы сетевых уровней. Первый — это тензор, содержащий данные RGB-изображения, который применяет серию сверток, объединение, взвешивание и другие типы преобразований. «Форма» и размерность данных меняются по мере того, как каждый сетевой уровень продолжает изучать более абстрактные функции. В конечном итоге последний слой нейронной сети генерирует одномерный вектор предсказания из 2622 элементов. Этот вектор представляет собой вероятность совпадения с конкретным человеком, используемым для обучения сети.
В нашем случае нас не интересуют эти прогнозы, но мы хотим сравнить наш собственный произвольный набор данных о лицах с нейронной сетью. Для этого мы можем использовать выходные данные слоя ниже уровня прогнозирования. Этот слой предоставляет вектор из 4096 элементов, описывающих черты лица.
output = net.modules[selectedLayer].output:clone()
VGG16 имеет 16 слоев, используя фактические результаты реализации Torch для создания 40-слойной «модельной» настройки, где уровень 38 дает желаемые результаты.
- сходство
Что мы собираемся сделать, так это запустить нейронную сеть для пар изображений и сравнить соответствующие результаты с метрикой сходства. Один из способов сравнить два очень больших числовых вектора — использовать скалярное произведение:
torch.dot(output1, output2)
Это дает скалярное значение, которое можно рассматривать как отношение, представляющее «согласованность» между вектором и многомерным пространством.
В этом тесте мы хотим сравнить ожидаемые Memoji с несколькими эталонными изображениями и объединить их. Поэтому мне нужно нормализовать каждую пару значений и взять среднее значение, чтобы получить «оценку».
sum = 0
for i = 1, #refs do
local ref = refs[i]
local dotself = torch.dot(ref , ref)
sum = sum + torch.dot(ref, target) / dotself
end
...
return sum / #refs
Нормализация означает, что сравнение изображения с самим собой будет иметь оценку 1,0, поэтому более высокое значение «оценки» позже означает более высокое сходство.
Есть много других типов показателей, которые нам нужно использовать, два наиболее очевидных из них — евклидово расстояние и среднеквадратическая ошибка между выходными данными. Я кратко попробовал эти два, но кажется, что скалярное произведение дает лучшие результаты, я немного чешу здесь голову.
Первый тест: набор аватаров
Первое, что я хочу проверить, это то, может ли эта сеть лиц обрабатывать Memoji в мультяшном стиле. Сначала я получил 63 мемодзи с лицами из поиска Google (в основном из демонстраций Apple).
Затем я выбрал один, и нейронная сеть оценила все Memoji, чтобы показать мне три лучших совпадения на основе одного изображения, на которое ссылаются.
Получилось здорово. Мало того, что нейросеть нашла те же Memoji (первое место с оценкой 1,0), так второй и третий результаты оказались менее правдоподобными.
реальное изображение
Теперь идет проверка «реальных» изображений: по сравнению с этими Memoji, как нейронная сеть работает с реальными изображениями? Я взял несколько фотографий известных людей и вот результаты:
Результаты все равно интересны. Обратите внимание, что нейронная сеть может выбирать только из ограниченного числа Memoji, и основные функции, которые она видит на этих изображениях, могут не соответствовать нашим ожиданиям. Также обратите внимание, что оценки (достоверность) в этих сравнениях значительно ниже, чем по сравнению с другими Memojis.
Процесс генерации
Затем я хотел обратить процесс вспять и использовать нейронную сеть для выбора функций для создания Memoji. Здесь становится немного сложнее. Ранее я упоминал, что нет очевидного способа автоматического создания Memoji на iOS. Хотя это можно было сделать на взломанном устройстве или взломать какую-нибудь художественную сеть, я хотел попробовать простой метод нейронных сетей.
Для тестирования я использовал функцию записи видео в QuickTime Player, подключил свой телефон к ноутбуку и поместил его в угол ровно настолько, чтобы сценарий мог захватить запись для обработки. Я пробовал все возможности для каждой функции, выбирая каждую опцию, нажимая Enter, чтобы получить и упорядочить вывод.
Очевидно, что это не идеально по нескольким причинам: во-первых, процесс болезненный (с 93 парами вариантов, пытался запустить его десятки раз). Что еще более важно, это позволяет нам оценивать только одно различие функций за раз. Теоретически мы могли бы перебирать его, пробуя снова и снова, пока нейронная сеть не перестанет предлагать изменения, но это не идеально, поэтому могут быть «локальные минимумы» (если один признак влияет на восприятие другого, то предполагаемое порядок имеет значение).
Кроме того, есть еще один раздражающий момент: камера постоянно следит за мной, и даже небольшие движения могут повлиять на счет.
результат
Сначала я испортил несколько результатов, но их можно было бы еще немного отшлифовать.
Однако нейросеть оказывается неустойчивой при выборе черт лица, то есть в некоторых случаях первые 3 изображения, выбранные моделью, очень похожи, а иногда нет. Например, вот три лучших Memoji, выбранных нейросетью для прически Трампа:
Некоторые особенности также соответствуют моим ожиданиям. Например, говорят, что у Обамы есть пара «привлекательных ушей», а затем нейронная сеть выводит три результата в порядке убывания степени совпадения:
Но изменений в глазах больше:
Напротив, глаза, выбранные для Трампа, мало изменились:
Сначала подбородок Обамы показался мне слишком квадратным, но через некоторое время я подумал, что он выглядит в самый раз (так что нехорошо быть слишком субъективным в этом отношении).
Цвет волос
Как я уже говорил, оттенки кожи трудно различить, и выбор цвета волос не менее проблематичен. Цвет волос и у Трампа, и у Обамы выглядит правдоподобно, но позже, когда я тестировал его с ярко-рыжими волосами, нейросеть всегда хотела выбрать серый цвет:
Несмотря на то, что первые три сгенерированных результата имеют рыжие волосы, результаты не идеальны. Я экспериментировал с большим количеством фотографий, чтобы увидеть, что на них повлияло, например, настроить предварительную обработку изображения. Однако, несмотря на то, что я радикально изменил входное изображение, нейронная сеть продолжала генерировать седые Memoji.
В другом эксперименте я просмотрел сгенерированные результаты других сетевых слоев. Напомним, ранее мы выбрали 38-й сетевой слой, потому что это самый верхний слой, представляющий черты лица. Однако мы можем сравнить с более низкими сетевыми уровнями и увидеть, в чем разница. При использовании 32-го сетевого слоя результаты различаются, и больше внимания уделяется цвету волос. Этот слой соответствует последнему «объединяющему» слою в модели VGG16, непосредственно перед первым «полностью связанным слоем», поэтому он может сохранять больше пространственной и цветовой информации. Этот и другие нижние слои сети дают лучшие результаты при создании Memoji для ярко-рыжих волос.
Кроме того, я попробовал несколько способов усреднить цвет волос (согласно первым трем вариантам и новому сетевому слою). Хотя это дало более разумные результаты, оно также не привело к желаемому ярко-рыжему цвету волос.
См. мой проект GitHub для кода скрипта факела для этого проекта:
Использованная литература:
https://patniemeyer.github.io/2018/10/29/generating-memoji-from-photos.html