Stable Diffusion は、文章のプロンプトから画像を生成します。

ここで2つのプロンプトを考えます。

p1 = バナナの写真(”High-resolution photo of bananas”) p2 = オレンジの写真(”High-resolution photo of oranges”)

このp1とp2の中間のプロンプトで画像を生成させる方法があります。p1とp2の混合比率を変えることも可能です。KerasCVでのstable Diffusion を使った実装がこちらで紹介されています。

具体的には、p1とp2から変換された行列c1 とc2に対して、その中間表現c_tを生成し(c_t = c1 + t(c2 – c1), t = 0, 0.1, 0.2, …, 1.0 というイメージです) 、c_tから画像を作るという方法です。

これと同様なことをローカルなStable Diffusionで試してみたのが以下の画像です。ここでは、c1(バナナ)からc2(オレンジ)までの7点を作成し、画像にしました。

生成された画像は、バナナから徐々にオレンジに変わっていっているように見えます。特に3枚目でバナナともオレンジとも似ているような中間の物体が出てきているのが面白いです。

コードは以下です。

import torch
import numpy as np
from omegaconf import OmegaConf
from PIL import Image, ImageOps
from einops import rearrange
from pytorch_lightning import seed_everything
from ldm.util import instantiate_from_config
from ldm.models.diffusion.plms import PLMSSampler
# from ldm.models.diffusion.ddim import DDIMSampler

def load_model_from_config(config, ckpt, verbose=False):
    print(f"Loading model from {ckpt}")
    pl_sd = torch.load(ckpt, map_location="cpu")
    if "global_step" in pl_sd:
        print(f"Global Step: {pl_sd['global_step']}")
    sd = pl_sd["state_dict"]
    model = instantiate_from_config(config.model)
    m, u = model.load_state_dict(sd, strict=False)
    if len(m) > 0 and verbose:
        print("missing keys:")
        print(m)
    if len(u) > 0 and verbose:
        print("unexpected keys:")
        print(u)
    model.cuda()
    model.eval()
    return model

def concat_images_with_border(imgs, border_width=2):
    """
    複数の画像を縦に連結して一つの画像を生成し、各画像に3ピクセルの黒色縁を追加する関数。
    """
    width, height = imgs[0].size
    concatenated_height = sum(img.size[1] for img in imgs) + (len(imgs) - 1) * border_width
    concatenated_image = Image.new("RGB", (width, concatenated_height), (0, 0, 0))
    y_offset = 0
    for i, img in enumerate(imgs):
        # 画像に縁を追加
        img_with_border = ImageOps.expand(img, border=border_width, fill=(0, 0, 0))
        concatenated_image.paste(img_with_border, (0, y_offset))
        y_offset += img_with_border.size[1]
        # 最後の画像以外には縦の空白スペースを追加
        if i  h w c')
    img = Image.fromarray(x_sample.astype(np.uint8))

    # 結果の表示
    display(img)
    imgs.append(img)

concat_img = concat_images_with_border(imgs)
display(concat_img)

# 解放
del model, sampler, device