[Перевод] Как я сгенерировал на Python тысячу лиц для своей игры

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

Поэтому я решил создать генератор лиц на основе знаменитой игры Papers, Please.

19230f7205e6d80ed32988aeedce43cc.gif


Генератор лиц Dukope (из Papers, Please)
Я скачал примерно 50 портретов с pixabay.com (все изображения имеют лицензию CC и не требуют указания авторства).

Затем я вырезал фон каждого изображения в Photoshop (просто выбрал всё инструментом выделения многоугольника и нажал на Delete). В дальнейшем я планировал воспользоваться эффектом cutout , чтобы скрыть все недочёты.

5dd4f869e63251b42fa35319ada5eae5.png


Изображения с удалённым фоном

Сегментация лиц


Для сегментации лиц я использую слои. Просто размываю кистью «нос и рот», а затем «глаза и брови», а затем создаю для них в PS новый слой. Это я делаю, выбрав видимые пиксели (Ctrl+нажатие на миниатюру слоя) и создав новый слой из выделенного. Все волосы, очки и другие объекты, закрывающие лицо, отправляются на слой под названием «hair_overlap». Я помечаю сегменты во всех 50 изображениях.

a27255ac63f1477a4cd24156146a04b1.png


Процесс работы со слоями

Также мне нужно подготовить лица для только что созданных элементов. Я использую Clone Stamp Tool, клонирую кожу и затираю все черты лица (новый слой затёрт инструментом «Палец» (Smudge)).

Извлечение черт лица


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

Я буду извлекать черты при помощи библиотек Python psd_tools и Pillow (их можно установить командой pip install psd-tools Pillow или при помощи IDE).

18dc9f3304c20b9626ddee23403b7510.png


Этот фрагмент кода должен составить список всех слоёв и ограничивающих их прямоугольников.

febd3b0438deadd539042a04e3d1e8cd.png


… что он и делает.

Затем мне нужно экспортировать все слои в отдельные файлы изображений. Также я создаю по папке для каждого названия слоя (представленный ниже фрагмент кода создаёт множество папок и файлов, например, eyes/girl-919048_1920.psd.png).

724dd221f13904bf9e22e2734460c1f4.png


Извлечение слоёв в файлы изображений

d5fcd946eebeb0ceac6e98b1ea70f6de.png


Извлечённые слои «eyes»

6fbabdebe879f9350669e796d0b801a9.png


Извлечённые слои «nose_mouth»
Теперь мне просто нужно всё это соединить вместе, и в этом мне поможет Pillow Image.

a209011073f8fb0b9300a19b2bea552b.png


Слой за слоем

Сгенерированные изображения довольно уродливы, поэтому нужно попытаться как-то скрыть их несовершенство фильтром cutout.

f1d83efc04ac744f28bf252bb3e8de8a.png


Сгенерированные изображения

Фильтр cutout довольно хорошо справляется с сокрытием изъянов.

c3a6d6770561e7817c4ce131b7bca661.png


Влияние Cutout в действии

К сожалению, в Python невозможно создать этот эффект без использования фильтров Собеля, медианных фильтров и дизеринга, для реализации которых потребуется очень много времени. Я нашёл плагин для GIMP FU_artist_cutout.scm, который делает то же самое, но использовать его будет неправильно. Я буду применять библиотеку G«MIC, у которой также есть онлайн-UI.

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


Имея его и инструмент командной строки, я готов к дальнейшей работе.

73627d0cd7dc1dea7d0038a1f6ecd22f.png


G«MIC в действии

229378ea6fc6608c9b82455b91a3ca73.jpg


Случайное лицо. Наложение волос работает, замечательно.

Теперь я просто подключаю всё это к подпроцессу и жду, пока он не сгенерирует нужное мне количество случайных лиц. Готово.

fd95c2cab677771554b1c7087d92d2b6.png


Код и несколько файлов .psd есть на моём github.

janjilecek/faceGenerator

© Habrahabr.ru