На определённом этапе разработки своей игры я осознал, что мне нужна система диалогов с лицами-аватарами.
Поэтому я решил создать генератор лиц на основе знаменитой игры Papers, Please.
![](https://habrastorage.org/getpro/habr/post_images/192/30f/720/19230f7205e6d80ed32988aeedce43cc.gif)
Генератор лиц Dukope (из Papers, Please)
Я скачал примерно 50 портретов с pixabay.com (все изображения имеют лицензию CC и не требуют указания авторства).
Затем я вырезал фон каждого изображения в Photoshop (просто выбрал всё инструментом выделения многоугольника и нажал на Delete). В дальнейшем я планировал воспользоваться эффектом cutout , чтобы скрыть все недочёты.
![](https://habrastorage.org/getpro/habr/post_images/5dd/4f8/69e/5dd4f869e63251b42fa35319ada5eae5.png)
Изображения с удалённым фоном
Для сегментации лиц я использую слои. Просто размываю кистью «нос и рот», а затем «глаза и брови», а затем создаю для них в PS новый слой. Это я делаю, выбрав видимые пиксели (Ctrl+нажатие на миниатюру слоя) и создав новый слой из выделенного. Все волосы, очки и другие объекты, закрывающие лицо, отправляются на слой под названием «hair_overlap». Я помечаю сегменты во всех 50 изображениях.
![](https://habrastorage.org/getpro/habr/post_images/a27/255/ac6/a27255ac63f1477a4cd24156146a04b1.png)
Процесс работы со слоями
Также мне нужно подготовить лица для только что созданных элементов. Я использую Clone Stamp Tool, клонирую кожу и затираю все черты лица (новый слой затёрт инструментом «Палец» (Smudge)).
Некоторые скачанные мной портретные фото не подходят для использования целиком, поэтому я извлекаю только те черты лиц, которые можно использовать в генераторе (например, только нос и губы).
Я буду извлекать черты при помощи библиотек Python psd_tools и Pillow (их можно установить командой pip install psd-tools Pillow или при помощи IDE).
![](https://habrastorage.org/getpro/habr/post_images/18d/c9f/330/18dc9f3304c20b9626ddee23403b7510.png)
Этот фрагмент кода должен составить список всех слоёв и ограничивающих их прямоугольников.
![](https://habrastorage.org/getpro/habr/post_images/feb/d3b/043/febd3b0438deadd539042a04e3d1e8cd.png)
… что он и делает.
Затем мне нужно экспортировать все слои в отдельные файлы изображений. Также я создаю по папке для каждого названия слоя (представленный ниже фрагмент кода создаёт множество папок и файлов, например, eyes/girl-919048_1920.psd.png).
![](https://habrastorage.org/getpro/habr/post_images/724/dd2/21f/724dd221f13904bf9e22e2734460c1f4.png)
Извлечение слоёв в файлы изображений
![](https://habrastorage.org/getpro/habr/post_images/d5f/cd9/46e/d5fcd946eebeb0ceac6e98b1ea70f6de.png)
Извлечённые слои «eyes»
![](https://habrastorage.org/getpro/habr/post_images/6fb/abd/ebe/6fbabdebe879f9350669e796d0b801a9.png)
Извлечённые слои «nose_mouth»
Теперь мне просто нужно всё это соединить вместе, и в этом мне поможет Pillow Image.
![](https://habrastorage.org/getpro/habr/post_images/a20/901/107/a209011073f8fb0b9300a19b2bea552b.png)
Слой за слоем
Сгенерированные изображения довольно уродливы, поэтому нужно попытаться как-то скрыть их несовершенство фильтром cutout.
![](https://habrastorage.org/getpro/habr/post_images/f1d/83e/fc0/f1d83efc04ac744f28bf252bb3e8de8a.png)
Сгенерированные изображения
Фильтр cutout довольно хорошо справляется с сокрытием изъянов.
![](https://habrastorage.org/getpro/habr/post_images/c3a/6d6/770/c3a6d6770561e7817c4ce131b7bca661.png)
Влияние Cutout в действии
К сожалению, в Python невозможно создать этот эффект без использования фильтров Собеля, медианных фильтров и дизеринга, для реализации которых потребуется очень много времени. Я нашёл плагин для GIMP FU_artist_cutout.scm, который делает то же самое, но использовать его будет неправильно. Я буду применять библиотеку G’MIC, у которой также есть онлайн-UI.
![](https://habrastorage.org/getpro/habr/post_images/ad9/51e/b57/ad951eb57a354e6c0386be6a529b87eb.png)
Онлайн-утилита G’MIC
Как оказалось, gmic может только использовать скрипты, у него нет параметра командной строки для эффекта cutout. Я нашёл определение эффекта cutout в файле gmic_stdlib.gmic:
Теперь я мог создать собственный фильтр cutout для g’mic:
Имея его и инструмент командной строки, я готов к дальнейшей работе.
![](https://habrastorage.org/getpro/habr/post_images/736/27d/0cd/73627d0cd7dc1dea7d0038a1f6ecd22f.png)
G’MIC в действии
![](https://habrastorage.org/getpro/habr/post_images/229/378/ea6/229378ea6fc6608c9b82455b91a3ca73.jpg)
Случайное лицо. Наложение волос работает, замечательно.
Теперь я просто подключаю всё это к подпроцессу и жду, пока он не сгенерирует нужное мне количество случайных лиц. Готово.
![](https://habrastorage.org/getpro/habr/post_images/fd9/5c2/cab/fd95c2cab677771554b1c7087d92d2b6.png)
Код и несколько файлов .psd есть на моём github.
janjilecek/faceGenerator
Поэтому я решил создать генератор лиц на основе знаменитой игры Papers, Please.
![](https://habrastorage.org/getpro/habr/post_images/192/30f/720/19230f7205e6d80ed32988aeedce43cc.gif)
Генератор лиц Dukope (из Papers, Please)
Сбор данных
Я скачал примерно 50 портретов с pixabay.com (все изображения имеют лицензию CC и не требуют указания авторства).
Затем я вырезал фон каждого изображения в Photoshop (просто выбрал всё инструментом выделения многоугольника и нажал на Delete). В дальнейшем я планировал воспользоваться эффектом cutout , чтобы скрыть все недочёты.
![](https://habrastorage.org/getpro/habr/post_images/5dd/4f8/69e/5dd4f869e63251b42fa35319ada5eae5.png)
Изображения с удалённым фоном
Сегментация лиц
Для сегментации лиц я использую слои. Просто размываю кистью «нос и рот», а затем «глаза и брови», а затем создаю для них в PS новый слой. Это я делаю, выбрав видимые пиксели (Ctrl+нажатие на миниатюру слоя) и создав новый слой из выделенного. Все волосы, очки и другие объекты, закрывающие лицо, отправляются на слой под названием «hair_overlap». Я помечаю сегменты во всех 50 изображениях.
![](https://habrastorage.org/getpro/habr/post_images/a27/255/ac6/a27255ac63f1477a4cd24156146a04b1.png)
Процесс работы со слоями
Также мне нужно подготовить лица для только что созданных элементов. Я использую Clone Stamp Tool, клонирую кожу и затираю все черты лица (новый слой затёрт инструментом «Палец» (Smudge)).
Извлечение черт лица
Некоторые скачанные мной портретные фото не подходят для использования целиком, поэтому я извлекаю только те черты лиц, которые можно использовать в генераторе (например, только нос и губы).
Я буду извлекать черты при помощи библиотек Python psd_tools и Pillow (их можно установить командой pip install psd-tools Pillow или при помощи IDE).
![](https://habrastorage.org/getpro/habr/post_images/18d/c9f/330/18dc9f3304c20b9626ddee23403b7510.png)
Этот фрагмент кода должен составить список всех слоёв и ограничивающих их прямоугольников.
![](https://habrastorage.org/getpro/habr/post_images/feb/d3b/043/febd3b0438deadd539042a04e3d1e8cd.png)
… что он и делает.
Затем мне нужно экспортировать все слои в отдельные файлы изображений. Также я создаю по папке для каждого названия слоя (представленный ниже фрагмент кода создаёт множество папок и файлов, например, eyes/girl-919048_1920.psd.png).
![](https://habrastorage.org/getpro/habr/post_images/724/dd2/21f/724dd221f13904bf9e22e2734460c1f4.png)
Извлечение слоёв в файлы изображений
![](https://habrastorage.org/getpro/habr/post_images/d5f/cd9/46e/d5fcd946eebeb0ceac6e98b1ea70f6de.png)
Извлечённые слои «eyes»
![](https://habrastorage.org/getpro/habr/post_images/6fb/abd/ebe/6fbabdebe879f9350669e796d0b801a9.png)
Извлечённые слои «nose_mouth»
Генератор лиц
Теперь мне просто нужно всё это соединить вместе, и в этом мне поможет Pillow Image.
![](https://habrastorage.org/getpro/habr/post_images/a20/901/107/a209011073f8fb0b9300a19b2bea552b.png)
Слой за слоем
Сгенерированные изображения довольно уродливы, поэтому нужно попытаться как-то скрыть их несовершенство фильтром cutout.
![](https://habrastorage.org/getpro/habr/post_images/f1d/83e/fc0/f1d83efc04ac744f28bf252bb3e8de8a.png)
Сгенерированные изображения
Фильтр cutout довольно хорошо справляется с сокрытием изъянов.
![](https://habrastorage.org/getpro/habr/post_images/c3a/6d6/770/c3a6d6770561e7817c4ce131b7bca661.png)
Влияние Cutout в действии
К сожалению, в Python невозможно создать этот эффект без использования фильтров Собеля, медианных фильтров и дизеринга, для реализации которых потребуется очень много времени. Я нашёл плагин для GIMP FU_artist_cutout.scm, который делает то же самое, но использовать его будет неправильно. Я буду применять библиотеку G’MIC, у которой также есть онлайн-UI.
![](https://habrastorage.org/getpro/habr/post_images/ad9/51e/b57/ad951eb57a354e6c0386be6a529b87eb.png)
Онлайн-утилита G’MIC
Как оказалось, gmic может только использовать скрипты, у него нет параметра командной строки для эффекта cutout. Я нашёл определение эффекта cutout в файле gmic_stdlib.gmic:
fx_cutout :
-repeat $! -l[$>] -split_opacity -l[0]
-median {10-$3}
-quantize $1
--area. 0,1 med=${-med} -rm.
-inpaint_holes {$med*$2%},0,1
-if $4 -n 0,255 -endif-endl -a c -endl -done
Теперь я мог создать собственный фильтр cutout для g’mic:
# File `myCutout.gmic`
cutout :
-echo "Arguments : $1,$2"
-input $1
-repeat $! -l[$>] -split_opacity -l[0]
-median 6
-quantize 20
--area. 0,1 med=${-med} -rm.
-inpaint_holes {$med*0%},0,1
-endl -a c -endl -done -output $2
Имея его и инструмент командной строки, я готов к дальнейшей работе.
![](https://habrastorage.org/getpro/habr/post_images/736/27d/0cd/73627d0cd7dc1dea7d0038a1f6ecd22f.png)
G’MIC в действии
![](https://habrastorage.org/getpro/habr/post_images/229/378/ea6/229378ea6fc6608c9b82455b91a3ca73.jpg)
Случайное лицо. Наложение волос работает, замечательно.
Теперь я просто подключаю всё это к подпроцессу и жду, пока он не сгенерирует нужное мне количество случайных лиц. Готово.
![](https://habrastorage.org/getpro/habr/post_images/fd9/5c2/cab/fd95c2cab677771554b1c7087d92d2b6.png)
Код и несколько файлов .psd есть на моём github.
janjilecek/faceGenerator
mwizard
Почему не предобученный StyleGAN2? Он в https://www.thispersondoesnotexist.com/ используется, результаты весьма неплохи. Есть даже ноутбук с примером https://colab.research.google.com/drive/1ShgW6wohEFQtqs_znMna3dzrcVoABKIH