Сегодня я расскажу, как можно изменить лицо на фотографии, используя сложный конвейер с несколькими генеративными нейронными сетями (GAN). Вы, наверное, видели множество популярных приложений, которые превращают ваше селфи в женщину или старика. Они не используют глубокое обучение полностью по двум основным причинам:

  • Обработка GAN по-прежнему тяжелая и медленная
  • Качество классических методов CV достаточно хорошее для производственного уровня.

Но, в любом случае, предложенный метод имеет некоторый потенциал, и работа, описанная ниже, подтверждает концепцию применимости GAN к задачам этого типа.

Конвейер для преобразования вашей фотографии может выглядеть так:

  1. обнаруживать и извлекать лицо из входного изображения
  2. преобразовать извлеченное лицо желаемым образом (преобразовать в женское, азиатское и т. д.)
  3. масштабировать / улучшать трансформированное лицо
  4. вставить преобразованное лицо обратно в исходное изображение

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

Распознавание лиц

Это самая легкая часть. Вы можете просто использовать что-то вроде dlib.get_frontal_face_detector() (пример). Детектор лиц по умолчанию, предоставляемый dlib, использует линейную классификацию функций HOG. Как показано в приведенном ниже примере, получившийся прямоугольник не может уместиться на всем лице, поэтому лучше расширить этот прямоугольник с некоторым коэффициентом в каждом измерении.

Настраивая эти факторы вручную, вы можете получить следующий код:

и со следующим результатом:

Если по какой-либо причине вы не удовлетворены работой этого старого метода, вы можете попробовать методы глубокого обучения SOTA. Любая архитектура обнаружения объектов (например, Faster-RCNN или YOLOv2) легко справится с этой задачей.

Трансформация лица

Это самая интересная часть. Как вы, наверное, знаете, GAN довольно хороши в создании и преобразовании изображений. И есть много моделей, названных как ‹префикса на ваш выбор› GAN. Проблема преобразования изображения из одного подмножества (домена) в другой называется передачей домена. Я выбрал сеть передачи доменов Cycle-GAN.

Cycle-GAN

Почему Cycle-GAN? Потому что это работает. И потому что с ним действительно легко начать. Посетите сайт проекта для ознакомления с примерами применения. Вы можете преобразовывать картины в фотографии, зебр в лошадей, панд в медведей или даже лица в рамэн (что это за безумство ?!).

Для начала вам просто нужно подготовить две папки с изображениями ваших двух доменов (например, мужские фотографии и женские фотографии), клонировать репозиторий автора с реализацией Cycle-GAN PyTorch и начать обучение. Вот и все.

Как это работает

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

Помимо GAN Loss и Cycle-Consistency Loss авторы также добавляют Identity Mapping Loss. Он действует как регуляризатор для модели и не хочет, чтобы изображения изменялись, если они пришли из целевого домена. Например. если на вход Zebra-generator поступает изображение зебры - его вообще не надо преобразовывать. Эта дополнительная потеря помогает сохранить цвета входных изображений (см. Рис. Ниже).

Сетевые архитектуры

Генераторные сети содержат две свертки с шагом 2 для двукратной субдискретизации входного сигнала, несколько остаточных блоков и две свертки с дробным шагом для повышающей дискретизации. Активация ReLu и нормализация экземпляра используются на всех уровнях.

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

Полностью сверточный дискриминатор сопоставляет входные данные с несколькими картами характеристик, а затем принимает решение, является ли изображение реальным или поддельным. Это можно интерпретировать как извлечение ряда патчей из входных данных и их классификацию на настоящие / поддельные. Размер пятен (или размер воспринимающего поля) контролируется количеством слоев в сети. Дискриминаторы этого типа также называются Patch-GAN. В этом посте Филип Изола объяснил мне магию этих сетей. Просмотрите это для лучшего понимания. Например. 1-слойная Patch-GAN смотрит на патчи 16x16, тогда как 5-слойная сеть будет иметь поле восприятия 286x286. Дискриминатор, который используется в документе Cycle-GAN, имеет рецептивное поле размером 70x70 с 3 сверточными слоями 4x4, за которыми следуют активации Batch Normaliztion и LeakyReLu.

Цикл обучения-GAN

Попробуем решить задачу преобразования мужского фото в женское и наоборот. Для этого нам нужны наборы данных с мужскими и женскими изображениями. Что ж, CelebA dataset идеально подходит для наших нужд. Он доступен бесплатно, в нем 200k изображений и 40 бинарных меток, таких как Gender, Eyeglasses, WearingHat, BlondeHair и т. Д.

В этом наборе данных 90 тыс. Мужских и 110 тыс. Женских фотографий. Этого достаточно для наших DomainX и DomainY. Средний размер лица на этих изображениях невелик, всего 150x150 пикселей. Поэтому мы изменили размер всех извлеченных лиц до 128x128, сохранив соотношение сторон и используя черный фон для изображений. Типичный ввод в наш Cycle-GAN может выглядеть так:

Потеря восприятия

В наших настройках мы изменили способ расчета потери идентичности. Вместо использования попиксельной потери мы использовали функции стиля из предварительно обученной сети vgg-16. И это вполне разумно, имхо. Если вы хотите сохранить стиль изображения, зачем рассчитывать пиксельную разницу, когда у вас есть слои, отвечающие за представление стиля изображения? Эта идея была впервые представлена ​​в статье Потери восприятия при передаче стиля в реальном времени и сверхвысоком разрешении и широко используется в задачах передачи стиля. И это небольшое изменение привело к интересному эффекту, о котором я расскажу позже.

Обучение

Что ж, в целом модель довольно большая. Обучаем одновременно 4 сети. Входные данные проходят через них несколько раз для расчета всех потерь, плюс все градиенты также должны распространяться. 1 эпоха обучения на 200k изображениях на GForce 1080 занимает около 5 часов, поэтому сложно много экспериментировать с разными гиперпараметрами. Замена потери идентичности перцептивной была единственным изменением по сравнению с исходной конфигурацией Cycle-GAN в нашей окончательной модели. Patch-GAN с меньшим или более чем 3 слоями не показали хороших результатов. В качестве оптимизатора использовался Адам с бета-версией = (0,5, 0,999). Скорость обучения начиналась с 0,0002 с небольшим спадом в каждую эпоху. Размер пакета был равен 1, и везде использовалась нормализация экземпляра вместо нормализации пакета. Один интересный трюк, который мне нравится замечать, заключается в том, что вместо подачи дискриминатору последнего выходного сигнала генератора использовался буфер из 50 ранее сгенерированных изображений, поэтому случайное изображение из этого буфера передается дискриминатору. Таким образом, сеть D использует изображения из более ранних версий G. Этот полезный прием - один из других, перечисленных в этой замечательной заметке Сумита Чинтала. Я рекомендую всегда иметь этот список перед вами при работе с GAN. У нас не было времени опробовать их все, например LeakyReLu и альтернативные слои повышающей дискретизации в Generator. Но советы по настройке и контролю расписания тренировок для пары Генератор-Дискриминатор действительно добавили стабильности процессу обучения.

Эксперименты

Наконец-то мы получили раздел примеров.

Обучение генеративных сетей немного отличается от обучения другим моделям глубокого обучения. Вы не будете часто видеть графики уменьшения потерь и повышения точности. Оценка того, насколько хороша ваша модель, делается в основном путем визуального просмотра выходных данных генераторов. Типичная картина тренировочного процесса Cycle-GAN выглядит так:

Генераторы расходятся, другие потери постепенно снижаются, но тем не менее, выход модели неплохой и разумный. Кстати, чтобы получить такую ​​визуализацию тренировочного процесса, мы использовали visdom, простой в использовании продукт с открытым исходным кодом, поддерживаемый Facebook Research. На каждой итерации было показано 8 картинок:

  • real_A - ввод из домена A
  • fake_B - real_A преобразованный генератором A- ›B
  • rec_A - восстановленное изображение, fake_B преобразовано генератором B- ›A
  • idty_B - real_A, преобразованный генератором B- ›A
  • и 4 соответствующих изображения для преобразования из области B в A.

После 5 эпох обучения можно было ожидать, что модель будет давать неплохие изображения. Посмотрите на пример ниже. Потери генераторов не уменьшаются, но все же женский генератор умеет превращать лицо мужчины, похожего на Дж. Хинтона, в женское. Как это могло быть? !!

Иногда все могло пойти совсем плохо:

В этом случае просто нажмите Ctrl + C и позвоните репортеру, чтобы заявить, что вы «только что выключили ИИ».

В итоге, несмотря на некоторые артефакты и низкое разрешение, можно сказать, что Cycle-GAN очень хорошо справляется с этой задачей. Вот несколько примеров.

Еще примеры со знаменитостями:

А теперь крайний случай:

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

Заткнись и отдай мне свои деньги!

Сверхразрешение изображения

Изображения, созданные Cycle-GAN, имеют низкое разрешение. Лучше их увеличивать и усиливать. Проблема увеличения разрешения изображения называется сверхразрешением. В этой области было проведено множество исследований. Хочу выделить две современные модели глубокого обучения, которые способны решать задачу сверхразрешения изображений: SRResNet и EDSR.

SRResNet

В статье Фотореалистичное сверхразрешение одиночного изображения с использованием генерирующей состязательной сети авторы предлагают генеративную сеть для сверхразрешения, основанную на архитектуре ResNet. В качестве объективной потери MSE между целевым и сверхразрешенным изображением используется. Но с двумя дополнительными терминами: потеря дискриминатора и потеря восприятия на функциях VGG (видите, все это делают!)

Генератор использует остаточные блоки со свертками 3x3, пакетной нормализацией и параметрическим ReLu. Свертки субпикселей используются для повышения частоты дискретизации.

Дискриминатор использует 8 сверток с ядрами 3x3 и активациями Leaky ReLu. Пониженная дискретизация выполняется с помощью чередующихся сверток (без объединения слоев). Классификация проводится по двум последним полностью связанным слоям с активацией сигмовидной кишки в конце.

EDSR

Усовершенствованная сеть глубокого сверхвысокого разрешения похожа на SRResNet с некоторыми улучшениями:

  • Нормализация партии не используется. Это экономит до 40% памяти и позволяет увеличить количество слоев и фильтров.
  • ReLu не используется вне остаточных блоков.
  • Все блоки ResNet масштабируются на 0,1 перед объединением с вектором идентичности. Это помогает стабилизировать тренировочный процесс.

Обучение

Для обучения сетей SR нам нужен набор изображений с высоким разрешением. Мы проанализировали несколько тысяч изображений с хештегом #face из Instagram. Обучение обычно проводится на небольших участках, а не на полных изображениях. Это помогает генератору обрабатывать мелкие мелкие детали. В режиме оценки передаются полноразмерные изображения, что возможно из-за полностью сверточного режима сети. На практике EDSR, который должен был быть усовершенствованием SRResNet, не показал лучших результатов и был медленным во времени обучения. Итак, в нашем последнем конвейере мы использовали SRResNet, обученную на патчах 64x64 с потерями восприятия и без дискриминатора. Ниже приведены несколько примеров из обучающей выборки.

Именно так эта сеть работала с нашими искусственными изображениями. Не идеально, но пока все в порядке.

Вставка изображения обратно в оригинал

Даже эту задачу можно решить с помощью глубокого обучения. Я нашел интересную статью о смешивании изображений. GP-GAN: на пути к реалистичному смешиванию изображений с высоким разрешением. Вместо того, чтобы углубляться в детали, я просто покажу вам этот рисунок из бумаги.

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

Заключение

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