Для Python, думаю, существует довольно много библиотек по генерации ненастоящих данных, которые впоследствии можно было бы использовать для регистрации на сайтах, когда указывать настоящую информацию не очень хочется. Но, вот генерация фото несуществующих людей уже связана с ИИ, ML и нейронными сетями. Не думаю, что стоит реализовать такой проект в одиночку. Хотя, если знания позволяют, то почему бы и нет. Однако, мои знания математики, к сожалению, далеки от идеала. Поэтому, я решил, что лучше поискать готовые решения, которые и помогут сгенерировать фото человека, которого никогда не существовало.
Сначала, и это вполне очевидное решение, я подумал использовать сервис «
Впрочем, долго это делать не пришлось. Буквально тут же я наткнулся на сервис «
Тут уже можно выбрать пол, возраст и прочие параметры, вплоть до наклона и поворота головы. Но, у меня-то была другая цель. Если бы мне было достаточно того, что предлагает сайт, я бы даже не думал про эту задачу. А моя задача была в том, чтобы с помощью питона сгенерировать новое лицо с указанными мною же параметрами и скачать это изображение себе на компьютер. Что же, надо идти в Инструменты разработчика. Обновляем страницу и видим, что полетел запрос на генерацию данных. Это POST-запрос, в котором передаются параметры выбранные пользователем.
При попытке перейти по ссылке запроса меня, собственно, никуда не пустили и, в ответ не прилетел никакой JSON с картинками. Значит, нужно копать глубже, подумал я. Щелкаю правой кнопкой мыши по POST-запросу, перехожу в меню Copy и выбираю пункт Copy all as cURL (bash).
Хорошо, данные скопированы. Но, вот что с ними делать дальше? В необработанном виде это… ну, скажем так, понятная, но немного (как по мне, хаотично упорядоченная штука):
Что же, нужно разбираться. Есть очень хороший сайт, который вот такие вот cURL переводит в код для разных языков программирования:
Очень хорошо. Получилось уже то, что можно использовать в дальнейшем. Но, в этом коде слишком много мусора. Поэтому, покопавшись и немного поэкспериментировав я пришел к несколько другому результату.
Вот, собственно и все. Больше, по сути, для получения ответа отправлять ничего не надо. Ну, кроме параметров в JSON. По сути, большая часть кода это вопросы пользователю и обработка ответов. Что же, теперь, когда мы разобрались, что и откуда берется, давайте приступим к написанию кода.
Что понадобиться?
Здесь требуется всего лишь одна библиотека для установки: requests. Набираем код в терминале:
А так же стандартные библиотеки os и random. Вот блок импорта:
Двигаемся дальше. Как можно уже понять, в POST-запросе на генерацию картинок нужно сформировать JSON, который будет отправляться в качестве параметров. Но, тут у меня, первоначально возникла небольшая трудность. Нужно было либо использовать те параметры, которые были получены при конвертации запроса, либо сформировать JSON самостоятельно. Я подумал, что лучше подойдет второй вариант. Хотя, если бы использовать первый, особой разницы бы не было.
Создадим функцию param_list(). Она не получает никаких значений и запускается из функции main. А вот на выходе она возвращает сформированный JSON. В принципе, объяснять тут особо нечего. Просто запрашиваются данные. В результате от ответа пользователя присваиваются переменным те или иные значения. Исключением здесь является лишь то, что параметров, например, цвета кожи или цвета волос может быть несколько. Поэтому, я создал списки. Изначальной задумкой было создать словари со значениями, но потом, все же остановился на списках. В принципе, то, что они заполнены параметрами, не имеет значения. Имеет значение только размер списка. К примеру, для эмоций он должен быть 8 элементов. Тут, конечно же, мой косяк. Но, переделывать не стал, потому, что тогда бы пришлось переписывать всю логику заполнения списков. Или придумывать другой способ записать значения в JSON.
Дальше в коде заполняется JSON в соответствии с теми значениями, что были получены. Ну и так же есть проверка на ошибки. Мало ли, чего введет пользователь, чтобы программа не рухнула, а просто подставила значение по умолчанию и продолжила работу. Вот, собственно, длинный код функции:
Пусть размеры не вводят вас в заблуждение. Тут просто много запросов на разные параметры для генерации. И да, когда увидел параметры JSON, в глаза бросился параметр, которого нет на основном сайте программы. Это image_num, то есть, количество генерируемых картинок. На сайте картинка генерируется одна. Поигрался со значениями и выяснил, что за один раз можно сгенерировать 16 картинок. Что довольно таки немало. Можно сказать, что нашел маленький баг. Но, он будет для нас очень полезен. Смею предположить, что количество сгенерированных картинок можно указывать в платной версии. Но, точно сказать не могу. Не знаю, не пользовался.
Ну и нужно написать еще одну функцию, которая и будет скачивать картинки. Назову ее get_photo_generate(param). Она принимает сформированный нами JSON и передает его в запросе серверу. В ответе, который получаем от сервера, в зависимости от количества запрошенных нами картинок, содержится один или несколько JSON элементов. В них разная информация и в том числе, ссылка на загрузки картинки. Выкорчевываю эту ссылку из полученного JSON. Для этого запускаю цикл. В этом же цикле делаю запрос на загрузку картинки, обрезаю ссылку, чтобы получить название картинки. Это для того, чтобы каждый раз не делать проверку, существует ли файл в папке. Чтобы имя картинки было уникальным. Создаю для картинок папку и сохраняю их в нее. После чего вывожу сообщение, о том, что все картинки загружены.
Вот полный код функции:
Ну и функция main. В ней вызывается функция для задавания глупых вопросов пользователю и формированию JSON. После, когда JSON сформирован, он передается в функцию для загрузки картинок. Ну и после всего безобразия объясняем пользователю, что полученные картинки, мы, при большом желании, могли бы еще немного повертеть. Но, в данном случае вертеть себе дороже. Овчинка не стоит выделки. А потому, для того, чтобы удалить водяной знак или фон с картинки лучше воспользоваться онлайн-сервисами, которые для этого и делались. С ИИ и всеми полагающимися плюшками.
Ну и вот, полный код скрипта:
А на этом, пожалуй, генерацию фото ненастоящих людей можно закончить. Ах, да. Вот то, что у меня получилось после генерации, загрузки и обработки полученного фото в сервисах:
Ну и еще одна, где так, по-быстрому приделал фотке фон в фотошопе:
Спасибо за внимание. Надеюсь, что данная информация будет кому-нибудь полезна
Сначала, и это вполне очевидное решение, я подумал использовать сервис «
Ссылка скрыта от гостей
», в силу его популярности. Но, вот реализация мне не особо понравилась. Во-первых, генерируется только одно фото. И для получения еще одного нужно перезапускать процесс генерации, а значит отправлять запрос на сервер еще раз. Во-вторых, нельзя указать параметры, по которым будет генерироваться фото, вроде пола, возраста, цвета волос и т.д. И тогда я решил еще немного поискать.Впрочем, долго это делать не пришлось. Буквально тут же я наткнулся на сервис «
Ссылка скрыта от гостей
». И вот тут уже было немного интереснее.Тут уже можно выбрать пол, возраст и прочие параметры, вплоть до наклона и поворота головы. Но, у меня-то была другая цель. Если бы мне было достаточно того, что предлагает сайт, я бы даже не думал про эту задачу. А моя задача была в том, чтобы с помощью питона сгенерировать новое лицо с указанными мною же параметрами и скачать это изображение себе на компьютер. Что же, надо идти в Инструменты разработчика. Обновляем страницу и видим, что полетел запрос на генерацию данных. Это POST-запрос, в котором передаются параметры выбранные пользователем.
При попытке перейти по ссылке запроса меня, собственно, никуда не пустили и, в ответ не прилетел никакой JSON с картинками. Значит, нужно копать глубже, подумал я. Щелкаю правой кнопкой мыши по POST-запросу, перехожу в меню Copy и выбираю пункт Copy all as cURL (bash).
Хорошо, данные скопированы. Но, вот что с ними делать дальше? В необработанном виде это… ну, скажем так, понятная, но немного (как по мне, хаотично упорядоченная штука):
Код:
curl 'https://api.generated.photos/api/frontend/v1/stylegans/generate' \
-H 'authority: api.generated.photos' \
-H 'sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Yandex";v="22"' \
-H 'dnt: 1' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'authorization: API-Key Cph30qkLrdJDkjW-THCeyA' \
-H 'content-type: application/json;charset=UTF-8' \
-H 'accept: application/json, text/plain, */*' \
-H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.2.644 Yowser/2.5 Safari/537.36' \
-H 'sec-ch-ua-platform: "Windows"' \
-H 'origin: https://generated.photos' \
-H 'sec-fetch-site: same-site' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-dest: empty' \
-H 'referer: https://generated.photos/' \
-H 'accept-language: ru,en;q=0.9,uk;q=0.8' \
-H 'cookie: __stripe_mid=ff2079cd-6e35-46d9-841d-71ba31580b629fa1dc; gp_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVG86HVJhY2s6OlNlc3Npb246OlNlc3Npb25JZAY6D0BwdWJsaWNfaWRJIkVkOTY4NWNmNDNiZTg3NGI5M2M1ZTVkZThkZjA0MzQ3M2FmYTY2YzI4ZGVmNzIzZjhmMzMwYjdjM2I3MTNhODhmBjsARkkiDGNhcnRfaWQGOwBGSSIdNjI1Y2YwMGIxMTVkZDYwMDBjOTliZjk3BjsAVA%3D%3D--e9cb11824dae8e43b276602dfd0e3dfcc81e753b; __stripe_sid=2117f364-4604-4d3e-9573-cec45cb87f50f82555' \
--data-raw '{"labels":{"gender":1,"age":15,"emotions":{"angry":0,"contempt":0,"disgust":0,"fear":0,"happy":0,"neutral":1,"sad":0,"surprise":0},"skin_colors":{"black":0,"dark_brown":0,"light_brown":0,"reddish":0,"white":1,"yellow":0},"hair_colors":{"black":1,"blond":0,"brown":0,"grey":0,"red":0},"glasses":{"no":1,"reading":0,"sun":0,"swimming":0},"yaw":0},"image_num":1}' \
--compressed ;
curl 'https://images.generated.photos/zvQTmyNSEr5V7asWT81tlhW4sRyulfYIYzh173EG9to/rs:fit:512:512/wm:0.95:sowe:18:18:0.33/czM6Ly9pY29uczgu/Z3Bob3Rvcy1wcm9k/LmNvbmQvM2UxNDE3/ZWMtOTUyMC00ZGU4/LWFkYWMtMzQwZDJm/MTBkNzc5LmpwZw.jpg' \
-H 'authority: images.generated.photos' \
-H 'sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Yandex";v="22"' \
-H 'dnt: 1' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.2.644 Yowser/2.5 Safari/537.36' \
-H 'sec-ch-ua-platform: "Windows"' \
-H 'accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8' \
-H 'sec-fetch-site: same-site' \
-H 'sec-fetch-mode: no-cors' \
-H 'sec-fetch-dest: image' \
-H 'referer: https://generated.photos/' \
-H 'accept-language: ru,en;q=0.9,uk;q=0.8' \
-H 'cookie: __stripe_mid=ff2079cd-6e35-46d9-841d-71ba31580b629fa1dc; gp_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVG86HVJhY2s6OlNlc3Npb246OlNlc3Npb25JZAY6D0BwdWJsaWNfaWRJIkVkOTY4NWNmNDNiZTg3NGI5M2M1ZTVkZThkZjA0MzQ3M2FmYTY2YzI4ZGVmNzIzZjhmMzMwYjdjM2I3MTNhODhmBjsARkkiDGNhcnRfaWQGOwBGSSIdNjI1Y2YwMGIxMTVkZDYwMDBjOTliZjk3BjsAVA%3D%3D--e9cb11824dae8e43b276602dfd0e3dfcc81e753b; __stripe_sid=2117f364-4604-4d3e-9573-cec45cb87f50f82555' \
--compressed ;
curl 'https://m.stripe.com/6' \
-H 'authority: m.stripe.com' \
-H 'sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Yandex";v="22"' \
-H 'dnt: 1' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.141 YaBrowser/22.3.2.644 Yowser/2.5 Safari/537.36' \
-H 'sec-ch-ua-platform: "Windows"' \
-H 'content-type: text/plain;charset=UTF-8' \
-H 'accept: */*' \
-H 'origin: https://m.stripe.network' \
-H 'sec-fetch-site: cross-site' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-dest: empty' \
-H 'referer: https://m.stripe.network/' \
-H 'accept-language: ru,en;q=0.9,uk;q=0.8' \
--data-raw 'JTdCJTIydjIlMjIlM0ExJTJDJTIyaWQlMjIlM0ElMjI0ZTAyOTk3YTEyMmU5NDNjOWVhZDk5M2JjYmZkNmUwZiUyMiUyQyUyMnQlMjIlM0ExMS40JTJDJTIydGFnJTIyJTNBJTIyNC41LjQyJTIyJTJDJTIyc3JjJTIyJTNBJTIyanMlMjIlMkMlMjJhJTIyJTNBbnVsbCUyQyUyMmIlMjIlM0ElN0IlMjJhJTIyJTNBJTIyJTIyJTJDJTIyYiUyMiUzQSUyMmh0dHBzJTNBJTJGJTJGMEJxbUxYWHc1ajM5eEpHMnVNZlhWN0VXUlJ1QTVNOHU4VHZsTzZua0hnVS5rUV9Sb0g1WFd4VHRjTXRnN0Nqcy1zTTVlM0hhTnBmS1NGSWhEVlhvRFJnJTJGOFlCM3dhV1R4bXd5Z3kxX2FxTjkySm9vUjJoMnVCV0RzeDlvV3EySmozTSUyRlRkVUE5SGtfMkE1WnlmV2pOSEllbUhQOXB1Wm9rTjNvNnVTYkhXaUJ2YTAlMjIlMkMlMjJjJTIyJTNBJTIybTVHTUxLMHBoQ2lvZkRxRDJ0dzVVZjhUbzFKQVB3UXFHZzU4UGt3VGJ1YyUyMiUyQyUyMmQlMjIlM0ElMjJmZjIwNzljZC02ZTM1LTQ2ZDktODQxZC03MWJhMzE1ODBiNjI5ZmExZGMlMjIlMkMlMjJlJTIyJTNBJTIyMjExN2YzNjQtNDYwNC00ZDNlLTk1NzMtY2VjNDVjYjg3ZjUwZjgyNTU1JTIyJTJDJTIyZiUyMiUzQWZhbHNlJTJDJTIyZyUyMiUzQXRydWUlMkMlMjJoJTIyJTNBdHJ1ZSUyQyUyMmklMjIlM0ElNUIlMjJsb2NhdGlvbiUyMiUyQyUyMmV2YWx1YXRlJTIyJTJDJTIyd3JpdGUlMjIlMkMlMjJ3cml0ZWxuJTIyJTJDJTIyb3BlbiUyMiUyQyUyMmNsb3NlJTIyJTJDJTIycmVtb3ZlRXZlbnRMaXN0ZW5lciUyMiUyQyUyMmFkZEV2ZW50TGlzdGVuZXIlMjIlNUQlMkMlMjJqJTIyJTNBJTVCJTIyZ2V0QmF0dGVyeSUyMiU1RCUyQyUyMm4lMjIlM0E1OTkuMDk5OTk5OTk5NjI3NSUyQyUyMnUlMjIlM0ElMjJnZW5lcmF0ZWQucGhvdG9zJTIyJTdEJTJDJTIyaCUyMiUzQSUyMjU4MjNjODhhMmRiZDJhNjkzNjY1JTIyJTdE' \
--compressed
Что же, нужно разбираться. Есть очень хороший сайт, который вот такие вот cURL переводит в код для разных языков программирования:
Ссылка скрыта от гостей
. Тут логика действий проста. Выбираем язык программирования, указываем тип запроса: post или get, вставляем скопированные данные и на выходе получаем код.Очень хорошо. Получилось уже то, что можно использовать в дальнейшем. Но, в этом коде слишком много мусора. Поэтому, покопавшись и немного поэкспериментировав я пришел к несколько другому результату.
Python:
headers = {
'accept': 'application/json, text/plain, */*',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.141 YaBrowser/22.3.2.628 Yowser/2.5 Safari/537.36',
}
response = requests.post('https://api.generated.photos/api/frontend/v1/stylegans/generate', headers=headers,
json=param).json()
Вот, собственно и все. Больше, по сути, для получения ответа отправлять ничего не надо. Ну, кроме параметров в JSON. По сути, большая часть кода это вопросы пользователю и обработка ответов. Что же, теперь, когда мы разобрались, что и откуда берется, давайте приступим к написанию кода.
Что понадобиться?
Здесь требуется всего лишь одна библиотека для установки: requests. Набираем код в терминале:
pip install requests
А так же стандартные библиотеки os и random. Вот блок импорта:
Python:
import os
import random
import requests
Двигаемся дальше. Как можно уже понять, в POST-запросе на генерацию картинок нужно сформировать JSON, который будет отправляться в качестве параметров. Но, тут у меня, первоначально возникла небольшая трудность. Нужно было либо использовать те параметры, которые были получены при конвертации запроса, либо сформировать JSON самостоятельно. Я подумал, что лучше подойдет второй вариант. Хотя, если бы использовать первый, особой разницы бы не было.
Создадим функцию param_list(). Она не получает никаких значений и запускается из функции main. А вот на выходе она возвращает сформированный JSON. В принципе, объяснять тут особо нечего. Просто запрашиваются данные. В результате от ответа пользователя присваиваются переменным те или иные значения. Исключением здесь является лишь то, что параметров, например, цвета кожи или цвета волос может быть несколько. Поэтому, я создал списки. Изначальной задумкой было создать словари со значениями, но потом, все же остановился на списках. В принципе, то, что они заполнены параметрами, не имеет значения. Имеет значение только размер списка. К примеру, для эмоций он должен быть 8 элементов. Тут, конечно же, мой косяк. Но, переделывать не стал, потому, что тогда бы пришлось переписывать всю логику заполнения списков. Или придумывать другой способ записать значения в JSON.
Дальше в коде заполняется JSON в соответствии с теми значениями, что были получены. Ну и так же есть проверка на ошибки. Мало ли, чего введет пользователь, чтобы программа не рухнула, а просто подставила значение по умолчанию и продолжила работу. Вот, собственно, длинный код функции:
Python:
def param_list():
if input('Выберите пол человека\n1.мужчина\n2.женщина\n>>> ') == '1':
gender = 1
else:
gender = random.randrange(0, 2)
try:
age = round(float(input('\nВведите возраст (целое число): ')))
except:
age = random.randrange(7, 101)
print(f'\nВы ввели неправильные значения. Возраст будет установлен по умолчанию: {age}\n')
emotions_list = ['angry', 'contempt', 'disgust', 'fear', 'happy', 'neutral', 'sad', 'surprise']
try:
emotion = int(input('\nВыберите эмоцию:\n1.злость\n2.презрение\n3.отвращение\n4.страх\n5.счастье\n'
'6.нейтральные эмоции\n7.грусть\n8.удивление\n>>> '))
except:
emotion = 7
for num, em in enumerate(emotions_list):
if emotion-1 == num:
emotions_list[num] = 1
else:
emotions_list[num] = 0
skin_colors_list = ['black', 'dark_brown', 'light_brown', 'reddish', 'white', 'yellow']
try:
colors = int(input('\nВыберите цвет кожи:\n1.черный\n2.тёмно-коричневый\n3.светло-коричневый\n4.красноватый\n'
'5.белый\n6.жёлтый\n>>> '))
except:
colors = 5
for num, clr in enumerate(skin_colors_list):
if colors-1 == num:
skin_colors_list[num] = 1
else:
skin_colors_list[num] = 0
hair_colors_list = ['black', 'blond', 'brown', 'grey', 'red']
try:
hair = int(input('\nВыберите цвет волос:\n1.чёрные\n2.белокурые\n3.каштановые\n4.седые\n5.рыжие\n>>> '))
except:
hair = 1
for num, hr in enumerate(hair_colors_list):
if hair-1 == num:
hair_colors_list[num] = 1
else:
hair_colors_list[num] = 0
hair_lengths_list = ['short', 'medium', 'long']
try:
hair_l = int(input('\nВыберите длину волос:\n1.короткие\n2.средние\n3.длинные\n>>> '))
except:
hair_l = 1
for num, hl in enumerate(hair_lengths_list):
if hair_l-1 == num:
hair_lengths_list[num] = 1
else:
hair_lengths_list[num] = 0
glasses_list = ['no', 'reading', 'sun', 'swimming']
try:
glass = int(input('\nВыберите тип очков:\n1.нет очков\n2.для чтения\n3.солнцезащитные\n4.для плавания\n>>> '))
except:
glass = 1
for num, gl in enumerate(glasses_list):
if glass-1 == num:
glasses_list[num] = 1
else:
glasses_list[num] = 0
if input('\nБудет ли человек лысым?\n1.Да\n2.Нет\n>>> ') == '1':
bald = 1
else:
bald = 0
if input('\nВыберите, будет ли около глаз "монгольская складка" (эпикантус)\n1.Да\n2.Нет\n>>> ') == '1':
epicanthus = 1
else:
epicanthus = 0
if input('\nБудет ли у человека макияж на глазах?\n1.Да\n2.Нет\n>>> ') == '1':
eye_makeup = True
else:
eye_makeup = False
if input('\nБудут ли у человека накрашены губы?\n1.Да\n2.Нет\n>>> ') == '1':
lip_makeup = True
else:
lip_makeup = False
print("\n (3) ")
print(" | ")
print(" (2) ")
print(" | ")
print(" (1) ")
print(" | ")
print('(-3)---(-2)---(-1)---0----(1)----(2)----(3)')
print(" | ")
print(" (-1) ")
print(" | ")
print(" (-2) ")
print(" | ")
print(" (-3) \n")
pitch_yaw_ch = [-0.12, -0.08000000000000002, -0.04000000000000001, 0, 0.04000000000000001, 0.08000000000000002,
0.12]
try:
pitch = int(input('\nВыберите наклон головы, согласно того, что вы видите на схеме >>> '))
except:
pitch = random.choice(pitch_yaw_ch)
if pitch == -3:
pitch = -0.12
elif pitch == -2:
pitch = -0.08000000000000002
elif pitch == -1:
pitch = -0.04000000000000001
elif pitch == 0:
pitch = 0
elif pitch == 1:
pitch = 0.04000000000000001
elif pitch == 2:
pitch = 0.08000000000000002
elif pitch == 3:
pitch = 0.12
else:
pitch = random.choice(pitch_yaw_ch)
try:
yaw = int(input('\nВыберите поворот головы, согласно того, что вы видите на схеме >>> '))
except:
yaw = random.choice(pitch_yaw_ch)
if yaw == -3:
yaw = -0.12
elif yaw == -2:
yaw = -0.08000000000000002
elif yaw == -1:
yaw = -0.04000000000000001
elif yaw == 0:
yaw = 0
elif yaw == 1:
yaw = 0.04000000000000001
elif yaw == 2:
yaw = 0.08000000000000002
elif yaw == 3:
yaw = 0.12
else:
yaw = random.choice(pitch_yaw_ch)
try:
image_num = int(input('\nВведите количество генерируемых фото >>> '))
except:
image_num = random.randrange(0, 17)
if image_num > 16:
image_num = '16'
param = {
'labels': {
'gender': gender,
'age': age,
'emotions': {
'angry': emotions_list[0],
'contempt': emotions_list[1],
'disgust': emotions_list[2],
'fear': emotions_list[3],
'happy': emotions_list[4],
'neutral': emotions_list[5],
'sad': emotions_list[6],
'surprise': emotions_list[7]
},
'skin_colors': {
'black': skin_colors_list[0],
'dark_brown': skin_colors_list[1],
'light_brown': skin_colors_list[2],
'reddish': skin_colors_list[3],
'white': skin_colors_list[4],
'yellow': skin_colors_list[5]
},
'hair_colors': {
'black': hair_colors_list[0],
'blond': hair_colors_list[1],
'brown': hair_colors_list[2],
'grey': hair_colors_list[3],
'red': hair_colors_list[4]
},
'hair_lengths': {
'short': hair_lengths_list[0],
'medium': hair_lengths_list[1],
'long': hair_lengths_list[2]
},
'glasses': {
'no': glasses_list[0],
'reading': glasses_list[1],
'sun': glasses_list[2],
'swimming': glasses_list[3]
},
'bald': bald,
'epicanthus': epicanthus,
'eye_makeup': eye_makeup,
'lip_makeup': lip_makeup,
'pitch': pitch,
'yaw': yaw,
},
'image_num': image_num
}
return param
Пусть размеры не вводят вас в заблуждение. Тут просто много запросов на разные параметры для генерации. И да, когда увидел параметры JSON, в глаза бросился параметр, которого нет на основном сайте программы. Это image_num, то есть, количество генерируемых картинок. На сайте картинка генерируется одна. Поигрался со значениями и выяснил, что за один раз можно сгенерировать 16 картинок. Что довольно таки немало. Можно сказать, что нашел маленький баг. Но, он будет для нас очень полезен. Смею предположить, что количество сгенерированных картинок можно указывать в платной версии. Но, точно сказать не могу. Не знаю, не пользовался.
Ну и нужно написать еще одну функцию, которая и будет скачивать картинки. Назову ее get_photo_generate(param). Она принимает сформированный нами JSON и передает его в запросе серверу. В ответе, который получаем от сервера, в зависимости от количества запрошенных нами картинок, содержится один или несколько JSON элементов. В них разная информация и в том числе, ссылка на загрузки картинки. Выкорчевываю эту ссылку из полученного JSON. Для этого запускаю цикл. В этом же цикле делаю запрос на загрузку картинки, обрезаю ссылку, чтобы получить название картинки. Это для того, чтобы каждый раз не делать проверку, существует ли файл в папке. Чтобы имя картинки было уникальным. Создаю для картинок папку и сохраняю их в нее. После чего вывожу сообщение, о том, что все картинки загружены.
Вот полный код функции:
Python:
def get_photo_generate(param):
headers = {
'accept': 'application/json, text/plain, */*',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.141 YaBrowser/22.3.2.628 Yowser/2.5 Safari/537.36',
}
response = requests.post('https://api.generated.photos/api/frontend/v1/stylegans/generate', headers=headers,
json=param).json()
for num in range(0, len(response['stylegans'])):
req = requests.get(url=response['stylegans'][num]['url'])
photo_name = response['stylegans'][num]['url'].split("/")[-1]
if not os.path.isdir('fake_human'):
os.mkdir('fake_human')
print(f"[+] Сохраняю фото {num+1}/{len(response['stylegans'])}")
with open(os.path.join('fake_human', f'image_{photo_name}'), 'wb') as file:
file.write(req.content)
print('\n[INFO] Все фото сохранены в папку "fake_human"\n')
Ну и функция main. В ней вызывается функция для задавания глупых вопросов пользователю и формированию JSON. После, когда JSON сформирован, он передается в функцию для загрузки картинок. Ну и после всего безобразия объясняем пользователю, что полученные картинки, мы, при большом желании, могли бы еще немного повертеть. Но, в данном случае вертеть себе дороже. Овчинка не стоит выделки. А потому, для того, чтобы удалить водяной знак или фон с картинки лучше воспользоваться онлайн-сервисами, которые для этого и делались. С ИИ и всеми полагающимися плюшками.
Ну и вот, полный код скрипта:
Python:
import os
import random
import requests
def get_photo_generate(param):
headers = {
'accept': 'application/json, text/plain, */*',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/98.0.4758.141 YaBrowser/22.3.2.628 Yowser/2.5 Safari/537.36',
}
response = requests.post('https://api.generated.photos/api/frontend/v1/stylegans/generate', headers=headers,
json=param).json()
for num in range(0, len(response['stylegans'])):
req = requests.get(url=response['stylegans'][num]['url'])
photo_name = response['stylegans'][num]['url'].split("/")[-1]
if not os.path.isdir('fake_human'):
os.mkdir('fake_human')
print(f"[+] Сохраняю фото {num+1}/{len(response['stylegans'])}")
with open(os.path.join('fake_human', f'image_{photo_name}'), 'wb') as file:
file.write(req.content)
print('\n[INFO] Все фото сохранены в папку "fake_human"\n')
def param_list():
if input('Выберите пол человека\n1.мужчина\n2.женщина\n>>> ') == '1':
gender = 1
else:
gender = random.randrange(0, 2)
try:
age = round(float(input('\nВведите возраст (целое число): ')))
except:
age = random.randrange(7, 101)
print(f'\nВы ввели неправильные значения. Возраст будет установлен по умолчанию: {age}\n')
emotions_list = ['angry', 'contempt', 'disgust', 'fear', 'happy', 'neutral', 'sad', 'surprise']
try:
emotion = int(input('\nВыберите эмоцию:\n1.злость\n2.презрение\n3.отвращение\n4.страх\n5.счастье\n'
'6.нейтральные эмоции\n7.грусть\n8.удивление\n>>> '))
except:
emotion = 7
for num, em in enumerate(emotions_list):
if emotion-1 == num:
emotions_list[num] = 1
else:
emotions_list[num] = 0
skin_colors_list = ['black', 'dark_brown', 'light_brown', 'reddish', 'white', 'yellow']
try:
colors = int(input('\nВыберите цвет кожи:\n1.черный\n2.тёмно-коричневый\n3.светло-коричневый\n4.красноватый\n'
'5.белый\n6.жёлтый\n>>> '))
except:
colors = 5
for num, clr in enumerate(skin_colors_list):
if colors-1 == num:
skin_colors_list[num] = 1
else:
skin_colors_list[num] = 0
hair_colors_list = ['black', 'blond', 'brown', 'grey', 'red']
try:
hair = int(input('\nВыберите цвет волос:\n1.чёрные\n2.белокурые\n3.каштановые\n4.седые\n5.рыжие\n>>> '))
except:
hair = 1
for num, hr in enumerate(hair_colors_list):
if hair-1 == num:
hair_colors_list[num] = 1
else:
hair_colors_list[num] = 0
hair_lengths_list = ['short', 'medium', 'long']
try:
hair_l = int(input('\nВыберите длину волос:\n1.короткие\n2.средние\n3.длинные\n>>> '))
except:
hair_l = 1
for num, hl in enumerate(hair_lengths_list):
if hair_l-1 == num:
hair_lengths_list[num] = 1
else:
hair_lengths_list[num] = 0
glasses_list = ['no', 'reading', 'sun', 'swimming']
try:
glass = int(input('\nВыберите тип очков:\n1.нет очков\n2.для чтения\n3.солнцезащитные\n4.для плавания\n>>> '))
except:
glass = 1
for num, gl in enumerate(glasses_list):
if glass-1 == num:
glasses_list[num] = 1
else:
glasses_list[num] = 0
if input('\nБудет ли человек лысым?\n1.Да\n2.Нет\n>>> ') == '1':
bald = 1
else:
bald = 0
if input('\nВыберите, будет ли около глаз "монгольская складка" (эпикантус)\n1.Да\n2.Нет\n>>> ') == '1':
epicanthus = 1
else:
epicanthus = 0
if input('\nБудет ли у человека макияж на глазах?\n1.Да\n2.Нет\n>>> ') == '1':
eye_makeup = True
else:
eye_makeup = False
if input('\nБудут ли у человека накрашены губы?\n1.Да\n2.Нет\n>>> ') == '1':
lip_makeup = True
else:
lip_makeup = False
print("\n (3) ")
print(" | ")
print(" (2) ")
print(" | ")
print(" (1) ")
print(" | ")
print('(-3)---(-2)---(-1)---0----(1)----(2)----(3)')
print(" | ")
print(" (-1) ")
print(" | ")
print(" (-2) ")
print(" | ")
print(" (-3) \n")
pitch_yaw_ch = [-0.12, -0.08000000000000002, -0.04000000000000001, 0, 0.04000000000000001, 0.08000000000000002,
0.12]
try:
pitch = int(input('\nВыберите наклон головы, согласно того, что вы видите на схеме >>> '))
except:
pitch = random.choice(pitch_yaw_ch)
if pitch == -3:
pitch = -0.12
elif pitch == -2:
pitch = -0.08000000000000002
elif pitch == -1:
pitch = -0.04000000000000001
elif pitch == 0:
pitch = 0
elif pitch == 1:
pitch = 0.04000000000000001
elif pitch == 2:
pitch = 0.08000000000000002
elif pitch == 3:
pitch = 0.12
else:
pitch = random.choice(pitch_yaw_ch)
try:
yaw = int(input('\nВыберите поворот головы, согласно того, что вы видите на схеме >>> '))
except:
yaw = random.choice(pitch_yaw_ch)
if yaw == -3:
yaw = -0.12
elif yaw == -2:
yaw = -0.08000000000000002
elif yaw == -1:
yaw = -0.04000000000000001
elif yaw == 0:
yaw = 0
elif yaw == 1:
yaw = 0.04000000000000001
elif yaw == 2:
yaw = 0.08000000000000002
elif yaw == 3:
yaw = 0.12
else:
yaw = random.choice(pitch_yaw_ch)
try:
image_num = int(input('\nВведите количество генерируемых фото >>> '))
except:
image_num = random.randrange(0, 17)
if image_num > 16:
image_num = '16'
param = {
'labels': {
'gender': gender,
'age': age,
'emotions': {
'angry': emotions_list[0],
'contempt': emotions_list[1],
'disgust': emotions_list[2],
'fear': emotions_list[3],
'happy': emotions_list[4],
'neutral': emotions_list[5],
'sad': emotions_list[6],
'surprise': emotions_list[7]
},
'skin_colors': {
'black': skin_colors_list[0],
'dark_brown': skin_colors_list[1],
'light_brown': skin_colors_list[2],
'reddish': skin_colors_list[3],
'white': skin_colors_list[4],
'yellow': skin_colors_list[5]
},
'hair_colors': {
'black': hair_colors_list[0],
'blond': hair_colors_list[1],
'brown': hair_colors_list[2],
'grey': hair_colors_list[3],
'red': hair_colors_list[4]
},
'hair_lengths': {
'short': hair_lengths_list[0],
'medium': hair_lengths_list[1],
'long': hair_lengths_list[2]
},
'glasses': {
'no': glasses_list[0],
'reading': glasses_list[1],
'sun': glasses_list[2],
'swimming': glasses_list[3]
},
'bald': bald,
'epicanthus': epicanthus,
'eye_makeup': eye_makeup,
'lip_makeup': lip_makeup,
'pitch': pitch,
'yaw': yaw,
},
'image_num': image_num
}
return param
def main():
param = param_list()
get_photo_generate(param)
print('[+] Для удаления водяного знака можно воспользоваться онлайн-сервисом:\n'
'https://ru.aiseesoft.com/watermark-remover-online/\n\n[+] Для удаления фона с фото:\n'
'https://www.remove.bg/ru\n\n[+] Ну или можете помучиться и сделать это самостоятельно в любой программе\nпо обработке изображений :-)\n')
if input('[+] Желаете повторить генерацию (y/n): ').lower() in ['y', 'д']:
main()
else:
print('Good by!')
exit(0)
if __name__ == "__main__":
main()
А на этом, пожалуй, генерацию фото ненастоящих людей можно закончить. Ах, да. Вот то, что у меня получилось после генерации, загрузки и обработки полученного фото в сервисах:
Ну и еще одна, где так, по-быстрому приделал фотке фон в фотошопе:
Спасибо за внимание. Надеюсь, что данная информация будет кому-нибудь полезна
Последнее редактирование: