Создаем изображения для NFT с помощью python (2 часть)
Read Time:7 Minute, 17 Second

Создаем изображения для NFT с помощью python (2 часть)

В прошлой статье мы создали генератор условных NFT на языке python, в целом можно было бы закончить, но хотелось бы немного улучшить наш результат и сделать наши NFT анимированными.

Добавим новые переменные для настройки нашего генератора:

from PIL import Image
import os
import random
import numpy as np
import math

#sizes in
in_w, in_h = (500,500)
#sizes out
out_w, out_h = (500,500)
#sizes block
b_w, b_h = (500,50)

#gif settings
gif = 1
gif_duration = 500
gif_optimisation = True
collage_w, collage_h = (4,2)

#how many images uses in procces generate
use_src_images = 10

src_images = list()
path_images = list()
images = list()

def getFixBoxSize(a, b):
    for i in range(0, b+1)[::-1]:
        if a % i == 0:
            return i

Немного пояснений про добавленные переменные:

# Кол-во кадров в нашей будущей gif
gif = 10

# Пауза между переходами
gif_duration = 500

# Оптимизация gif от библиотеки pillow
gif_optimisation = True

# Мозаика из gif (колонки, строки)
collage_w, collage_h = (4,2)

И изменим наш основной код на следующий вид:

if gif > 1:
    finally_image_list = list()
    for c in range(0, gif):
        # Get imagesimg
        tmp_images = os.listdir('./img')
        # Shuffle images in the list
        tmp_images =  sorted(tmp_images, key=lambda A: random.random())
        # Save fixed count images
        if len(tmp_images) >= use_src_images:
            path_images = [tmp_images[x] for x in range(0, use_src_images)]
        # Load images to buffer
        for img in path_images:
            images.append(Image.open(f"./img/{img}").resize((in_w, in_h)))
        combimosaic = Image.new("RGB", (out_w * collage_w, out_h * collage_h), tuple(np.random.choice(range(256), size=3)))
        if collage_w > 0 and collage_h > 0:
            for c_row in range(0, collage_h):
                for c_col in range(0, collage_w):
                    mosaic = Image.new("RGB", (in_w, in_h), tuple(np.random.choice(range(256), size=3)))
                    print(f"Source Images: " + ", ".join(path_images))
                    print("Method generation: VERTICAL")
                    print(f"In size image: {in_w}x{in_h}")
                    print(f"Out size image: {out_w}x{out_h}")
                    print(f"SET Block size: {b_w}x{b_h}")
                    b_w = getFixBoxSize(in_w, b_w)
                    b_h = getFixBoxSize(in_h, b_h)
                    print(f"FIX Block size: {b_w}x{b_h}")
                    # calculate how many parts need
                    cols, rows = (math.ceil(in_w / b_w),math.ceil(in_h / b_h))
                    print(f"ROWS: {rows}")
                    print(f"COLS: {cols}")
                    block_lines = [sorted([x2 for x2 in range(0,cols)], key=lambda A: random.random()) for x in range(0,rows)]
                    print("                            M A T R I X")
                    print('\n'.join(str(x) for x in block_lines))
                    for row in range(0, rows):
                        for col in range(0, cols):
                            rand = random.randrange(0, len(images))
                            num = block_lines[row].pop(0)
                            quad = (b_w * num, b_h * row, b_w * num + b_w, b_h * row + b_h)
                            quadimg = images[rand].crop(quad)
                            mosaic.paste(quadimg, (b_w * num, b_h * row, b_w * num + b_w, b_h * row + b_h), quadimg)
                    fragment = mosaic.resize((out_w, out_h))
                    fragmentimg = fragment.crop((0,0,out_w,out_h))
                    combimosaic.paste(fragmentimg, (out_w * c_col, out_h * c_row, out_w * c_col + out_w, out_h * c_row + out_h))
            finally_image_list.append(combimosaic)
        else:
            mosaic = Image.new("RGB", (in_w, in_h), tuple(np.random.choice(range(256), size=3)))
            print(f"Source Images: " + ", ".join(path_images))
            print("Method generation: VERTICAL")
            print(f"In size image: {in_w}x{in_h}")
            print(f"Out size image: {out_w}x{out_h}")
            print(f"SET Block size: {b_w}x{b_h}")
            b_w = getFixBoxSize(in_w, b_w)
            b_h = getFixBoxSize(in_h, b_h)
            print(f"FIX Block size: {b_w}x{b_h}")
            # calculate how many parts need
            cols, rows = (math.ceil(in_w / b_w),math.ceil(in_h / b_h))
            print(f"ROWS: {rows}")
            print(f"COLS: {cols}")
            block_lines = [sorted([x2 for x2 in range(0,cols)], key=lambda A: random.random()) for x in range(0,rows)]
            print("                            M A T R I X")
            print('\n'.join(str(x) for x in block_lines))
            for row in range(0, rows):
                for col in range(0, cols):
                    rand = random.randrange(0, len(images))
                    num = block_lines[row].pop(0)
                    quad = (b_w * num, b_h * row, b_w * num + b_w, b_h * row + b_h)
                    quadimg = images[rand].crop(quad)
                    mosaic.paste(quadimg, (b_w * num, b_h * row, b_w * num + b_w, b_h * row + b_h), quadimg)
            mosaic = mosaic.resize((out_w, out_h))
            finally_image_list.append(mosaic)
    gif = Image.new("RGB", (out_w * collage_w, out_h * collage_h), tuple(np.random.choice(range(256), size=3)))
    temp = [x for x in finally_image_list]
    temp[0].save('out.gif', save_all=True, append_images=
    temp[1:],optimize=gif_optimisation, duration=gif_duration, loop=0) 
else:
    # Get images
    tmp_images = os.listdir('./img')
    # Shuffle images in the list
    tmp_images =  sorted(tmp_images, key=lambda A: random.random())
    # Save fixed count images
    if len(tmp_images) >= use_src_images:
        path_images = [tmp_images[x] for x in range(0, use_src_images)]
    # Load images to buffer
    for img in path_images:
        images.append(Image.open(f"./img/{img}").resize((in_w, in_h)))

    combimosaic = Image.new("RGB", (out_w * collage_w, out_h * collage_h), tuple(np.random.choice(range(256), size=3)))
    if collage_w > 0 and collage_h > 0:
        for c_row in range(0, collage_h):
            for c_col in range(0, collage_w):
                mosaic = Image.new("RGB", (in_w, in_h), tuple(np.random.choice(range(256), size=3)))
                print(f"Source Images: " + ", ".join(path_images))
                print("Method generation: VERTICAL")
                print(f"In size image: {in_w}x{in_h}")
                print(f"Out size image: {out_w}x{out_h}")
                print(f"SET Block size: {b_w}x{b_h}")
                b_w = getFixBoxSize(in_w, b_w)
                b_h = getFixBoxSize(in_h, b_h)
                print(f"FIX Block size: {b_w}x{b_h}")
                # calculate how many parts need
                cols, rows = (math.ceil(in_w / b_w),math.ceil(in_h / b_h))
                print(f"ROWS: {rows}")
                print(f"COLS: {cols}")
                block_lines = [sorted([x2 for x2 in range(0,cols)], key=lambda A: random.random()) for x in range(0,rows)]
                print("                            M A T R I X")
                print('\n'.join(str(x) for x in block_lines))
                for row in range(0, rows):
                    for col in range(0, cols):
                        rand = random.randrange(0, len(images))
                        num = block_lines[row].pop(0)
                        quad = (b_w * num, b_h * row, b_w * num + b_w, b_h * row + b_h)
                        quadimg = images[rand].crop(quad)
                        mosaic.paste(quadimg, (b_w * num, b_h * row, b_w * num + b_w, b_h * row + b_h), quadimg)
                fragment = mosaic.resize((out_w, out_h))
                fragmentimg = fragment.crop((0,0,out_w,out_h))
                combimosaic.paste(fragmentimg, (out_w * c_col, out_h * c_row, out_w * c_col + out_w, out_h * c_row + out_h))
        combimosaic.show()
    else:
        mosaic = Image.new("RGB", (in_w, in_h), tuple(np.random.choice(range(256), size=3)))
        print(f"Source Images: " + ", ".join(path_images))
        print("Method generation: VERTICAL")
        print(f"In size image: {in_w}x{in_h}")
        print(f"Out size image: {out_w}x{out_h}")
        print(f"SET Block size: {b_w}x{b_h}")
        b_w = getFixBoxSize(in_w, b_w)
        b_h = getFixBoxSize(in_h, b_h)
        print(f"FIX Block size: {b_w}x{b_h}")
        # calculate how many parts need
        cols, rows = (math.ceil(in_w / b_w),math.ceil(in_h / b_h))
        print(f"ROWS: {rows}")
        print(f"COLS: {cols}")
        block_lines = [sorted([x2 for x2 in range(0,cols)], key=lambda A: random.random()) for x in range(0,rows)]
        print("                            M A T R I X")
        print('\n'.join(str(x) for x in block_lines))
        for row in range(0, rows):
            for col in range(0, cols):
                rand = random.randrange(0, len(images))
                num = block_lines[row].pop(0)
                quad = (b_w * num, b_h * row, b_w * num + b_w, b_h * row + b_h)
                quadimg = images[rand].crop(quad)
                mosaic.paste(quadimg, (b_w * num, b_h * row, b_w * num + b_w, b_h * row + b_h), quadimg)
        mosaic = mosaic.resize((out_w, out_h))
        mosaic.show()
    mosaic.save('out.png')

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

Результат генерации анимированной мозаики

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *