ジャコ Lab

プログラミング関連のメモ帳的ブログです

IP-Adapter の GitHub リポジトリから ip_adapter-full-face_demo の生成を試してみる

zako-lab929.hatenablog.com

さて、前回は diffusers のドキュメント から IP-AdapterFace Model というものを使ってみました。具体的には ip-adapter-full-face_sd15 を使わせていただきました。

今回は GitHub リポジトリ から ip_adapter-full-face_demo を読み解きながら diffusers に置き換えてみようと思います。「読み解きながら」というのは恐らく GitHub リポジトリソースコードは diffusers に実装される前のデモになっているため load_ip_adapter() などが存在しないときのデモコードかもしれないためです。

目標は、 load_ip_adapter() のメソッドを使いつつ、GitHub リポジトリのデモと同じ系統の絵を生成することです。

デモケース1

IP-Adapter のインプットに利用する女性の画像
IP-Adapter のインプットに利用する女性の画像

IP-Adapter の生成物として期待値となる女性の画像
IP-Adapter の生成物として期待値となる女性の画像

デモコードから得られる情報
base_model_path = "SG161222/Realistic_Vision_V4.0_noVAE"
vae_model_path = "stabilityai/sd-vae-ft-mse"
image_encoder_path = "models/image_encoder/"
ip_ckpt = "models/ip-adapter-full-face_sd15.bin"
device = "cuda"

モデル等をロードする

import torch
from diffusers import AutoencoderKL, StableDiffusionPipeline, DDIMScheduler

# VAE をロードする
vae = AutoencoderKL.from_pretrained(
    "stabilityai/sd-vae-ft-mse"
).to(dtype=torch.float16)

# SD1.5系モデルをロードする
pipe = StableDiffusionPipeline.from_pretrained(
    "SG161222/Realistic_Vision_V4.0_noVAE",
    torch_dtype=torch.float16,
    vae=vae
).to("cuda")

# スケジューラを設定する
pipe.scheduler = DDIMScheduler.from_config(
    pipe.scheduler.config,
    num_train_timesteps=1000,
    beta_start=0.00085,
    beta_end=0.012,
    beta_schedule="scaled_linear",
    clip_sample=False,
    set_alpha_to_one=False,
    steps_offset=1,
)

# IP-Adapter をロードする
pipe.load_ip_adapter(
    "h94/IP-Adapter",
    subfolder="models",
    weight_name="ip-adapter-full-face_sd15.bin"
)
pipe.set_ip_adapter_scale(0.7)

IP-Adapter 用のインプット画像をロードする

from diffusers.utils import load_image

# IP-Adapter 用の画像をロードする
ip_adapter_image_url = "https://raw.githubusercontent.com/tencent-ailab/IP-Adapter/main/assets/images/ai_face2.png"
ip_adapter_image = load_image(ip_adapter_image_url)
ip_adapter_image = ip_adapter_image.resize((256, 256))

パイプラインを実行する

# シードを設定する
generator = torch.Generator(device="cuda")
generator.manual_seed(42)

# パイプラインを実行する
prompt = "A photo of a girl wearing a black dress, holding red roses in hand, upper body, behind is the Eiffel Tower"
images = pipe(
    prompt,
    ip_adapter_image=ip_adapter_image,
    num_images_per_prompt=4,
    num_inference_steps=50,
    width=512,
    height=704,
    generator=generator,
).images
黒いドレスを着て、赤いバラを手に持った女の子の上半身、後ろにエッフェル塔がある写真

実行結果

from datetime import datetime
from zoneinfo import ZoneInfo

# Asia/Tokyo タイムゾーンの現在時刻を YYYYMMDDhhmmss 形式で得る
formattedNow = datetime.now(tz=ZoneInfo("Asia/Tokyo")).strftime("%Y%m%d%H%M%S")

for idx, image in enumerate(images):
    # 実行結果
    image.save(f"image_{formattedNow}_{idx}_{generator.initial_seed()}.png")

黒いドレスを着て、赤いバラを手に持った女の子の上半身、後ろにエッフェル塔がある写真1黒いドレスを着て、赤いバラを手に持った女の子の上半身、後ろにエッフェル塔がある写真2黒いドレスを着て、赤いバラを手に持った女の子の上半身、後ろにエッフェル塔がある写真3黒いドレスを着て、赤いバラを手に持った女の子の上半身、後ろにエッフェル塔がある写真4
黒いドレスを着て、赤いバラを手に持った女の子の上半身、後ろにエッフェル塔がある写真

かなり近いものが出力されたのでは??

デモケース1 - 不要そうな設定を削除してみる

スケジューラのパラメータ

デフォルトで設定されてそうですもんね。

Scheduler のパラメータを削除して生成した女性の画像1Scheduler のパラメータを削除して生成した女性の画像2Scheduler のパラメータを削除して生成した女性の画像3Scheduler のパラメータを削除して生成した女性の画像4
Scheduler のパラメータを削除して生成した女性の画像

うんうん。予定通り。 pipe.scheduler.config をそのまま出力してみても同じ値の Dict が得られました

VAE

VAE ってよくわからないんだよな~。自ら使ったことないから。。。

VAE の設定を削除して生成した女性の画像
VAE の設定を削除して生成した女性の画像

4枚のうちの1枚目を GIF にしてみました。

チカチカしているので若干の色味などに違いがあるみたい
でも設定してもしなくてもあまり変わらないことがわかった

まとめ

かなり顔が固定されたまま出力されていました。

ちょっと長くなってしまったので、デモケース2 及び デモケース3 は次回の記事にします。