• 4 июля стартует курс «Python для Пентестера ©» от команды The Codeby

    Понятные и наглядные учебные материалы с информацией для выполнения ДЗ; Проверка ДЗ вручную – наставник поможет улучшить написанный вами код; Помощь преподавателей при выполнении заданий или в изучении теории; Групповой чат в Telegram с другими учениками, проходящими курс; Опытные разработчики – команда Codeby School, лидер по информационной безопасности в RU-сегменте

    Запись на курс до 15 июля. Подробнее ...

  • 11 июля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

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

    Запись на курс до 20 июля. Подробнее ...

Статья Парсим сгенерированные фото с помощью Python

Для Python, думаю, существует довольно много библиотек по генерации ненастоящих данных, которые впоследствии можно было бы использовать для регистрации на сайтах, когда указывать настоящую информацию не очень хочется. Но, вот генерация фото несуществующих людей уже связана с ИИ, ML и нейронными сетями. Не думаю, что стоит реализовать такой проект в одиночку. Хотя, если знания позволяют, то почему бы и нет. Однако, мои знания математики, к сожалению, далеки от идеала. Поэтому, я решил, что лучше поискать готовые решения, которые и помогут сгенерировать фото человека, которого никогда не существовало.

0001.jpg

Сначала, и это вполне очевидное решение, я подумал использовать сервис « », в силу его популярности. Но, вот реализация мне не особо понравилась. Во-первых, генерируется только одно фото. И для получения еще одного нужно перезапускать процесс генерации, а значит отправлять запрос на сервер еще раз. Во-вторых, нельзя указать параметры, по которым будет генерироваться фото, вроде пола, возраста, цвета волос и т.д. И тогда я решил еще немного поискать.

Впрочем, долго это делать не пришлось. Буквально тут же я наткнулся на сервис « ». И вот тут уже было немного интереснее.

screenshot1.png

Тут уже можно выбрать пол, возраст и прочие параметры, вплоть до наклона и поворота головы. Но, у меня-то была другая цель. Если бы мне было достаточно того, что предлагает сайт, я бы даже не думал про эту задачу. А моя задача была в том, чтобы с помощью питона сгенерировать новое лицо с указанными мною же параметрами и скачать это изображение себе на компьютер. Что же, надо идти в Инструменты разработчика. Обновляем страницу и видим, что полетел запрос на генерацию данных. Это POST-запрос, в котором передаются параметры выбранные пользователем.

screenshot2.png

При попытке перейти по ссылке запроса меня, собственно, никуда не пустили и, в ответ не прилетел никакой JSON с картинками. Значит, нужно копать глубже, подумал я. Щелкаю правой кнопкой мыши по POST-запросу, перехожу в меню Copy и выбираю пункт Copy all as cURL (bash).

screenshot3.png

Хорошо, данные скопированы. Но, вот что с ними делать дальше? В необработанном виде это… ну, скажем так, понятная, но немного (как по мне, хаотично упорядоченная штука):

Код:
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, вставляем скопированные данные и на выходе получаем код.

screenshot4.png

Очень хорошо. Получилось уже то, что можно использовать в дальнейшем. Но, в этом коде слишком много мусора. Поэтому, покопавшись и немного поэкспериментировав я пришел к несколько другому результату.

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()

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

three.jpg

Ну и еще одна, где так, по-быстрому приделал фотке фон в фотошопе:

see.png

Спасибо за внимание. Надеюсь, что данная информация будет кому-нибудь полезна
 
Последнее редактирование:
02.03.2021
360
237
Хватит в нас кидать статьями для мотивации изучать python! Мне так хорошо сидеть и не чего не делать, а тут разные интересные фичи можно смастерить, не отходя от кассы.

p.s. Спасибо интересная статья
 
  • Нравится
Реакции: Westus и Johan Van

Johan Van

Green Team
13.06.2020
129
224
Хватит в нас кидать статьями для мотивации изучать python! Мне так хорошо сидеть и не чего не делать, а тут разные интересные фичи можно смастерить, не отходя от кассы.

p.s. Спасибо интересная статья

Спасибо за отзыв. Очень приятно, так как я тоже только начинаю его изучать ))
 
Мы в соцсетях: