さて、前回は diffusers のドキュメント から IP-Adapter の Face Model というものを使ってみました。具体的には ip-adapter-full-face_sd15 を使わせていただきました。
今回は GitHub リポジトリ から ip_adapter-full-face_demo を読み解きながら diffusers に置き換えてみようと思います。「読み解きながら」というのは恐らく GitHub リポジトリのソースコードは diffusers に実装される前のデモになっているため load_ip_adapter() などが存在しないときのデモコードかもしれないためです。
目標は、 load_ip_adapter() のメソッドを使いつつ、GitHub リポジトリのデモと同じ系統の絵を生成することです。
デモケース1
デモコードから得られる情報
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 - 不要そうな設定を削除してみる
スケジューラのパラメータ
デフォルトで設定されてそうですもんね。
うんうん。予定通り。
pipe.scheduler.config をそのまま出力してみても同じ値の Dict が得られました
VAE
VAE ってよくわからないんだよな~。自ら使ったことないから。。。
4枚のうちの1枚目を GIF にしてみました。
チカチカしているので若干の色味などに違いがあるみたい
でも設定してもしなくてもあまり変わらないことがわかった
でも設定してもしなくてもあまり変わらないことがわかった
まとめ
かなり顔が固定されたまま出力されていました。
ちょっと長くなってしまったので、デモケース2 及び デモケース3 は次回の記事にします。