とりあえず、昨日の記事同様、タイトルはすごい長いラノベ風にできたのは良いとして、、、
前回の IP-Adapter の記事に引き続き diffusers v0.24.0 のリリースノート に沿って IP-Adapter を使ってみる回になります。
前回は、 IP-Adapter を差し込んで LCM LoRA を併用していました。
今回は、 ControlNet を併用する形になります。
ControlNet とは?
ControlNet とは、 追加の入力画像を使用して調整することで、出力画像を制御するモデルの一種で、制御に使用できる入力には様々なタイプがある とのことで、以下で調べていました。
IP-Adapter と ControlNet を併用する
diffusers v0.24.0 のリリースノート によると IP-Adapter と ControlNet の Depth を併用するサンプルのようです。
ControlNet の Depth 単体を試している記事は以下になります。
ControlNet (Depth) のときには image=
プロパティに control_image (depth_image)
を渡しており、
「プロンプト」 + 「コントロール画像」 になります。
IP-Adapter を用いることで入力が 「画像」 「プロンプト」 「コントロール画像」 の3つになります。
モデルのロード等 (ControlNet(Depth), StableDiffusion1.5, IP-Adapter)
from diffusers import StableDiffusionControlNetPipeline, ControlNetModel import torch # ControlNetモデルのロード (Depth) controlnet = ControlNetModel.from_pretrained( "lllyasviel/control_v11f1p_sd15_depth", torch_dtype=torch.float16 ) # SD 系モデルのロード pipe = StableDiffusionControlNetPipeline.from_pretrained( "runwayml/stable-diffusion-v1-5", controlnet=controlnet, torch_dtype=torch.float16) pipe.to("cuda") # IP-Adapter のロード pipe.load_ip_adapter( "h94/IP-Adapter", subfolder="models", weight_name="ip-adapter_sd15.bin" ) # enable memory savings pipe.enable_vae_slicing() pipe.enable_model_cpu_offload()
入力画像等のロード
from diffusers.utils import load_image # インプット画像のロード input_image_url = "https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/statue.png" input_image = load_image(input_image_url) # コントロール画像のロード control_image_url = "https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/depth.png" control_image = load_image(control_image_url)
パイプライン実行
import torch generator = torch.Generator(device="cpu").manual_seed(33) prompt = "best quality, high quality" negative_prompt = "monochrome, lowres, bad anatomy, worst quality, low quality" image = pipe( prompt, negative_prompt=negative_prompt, image=control_image, ip_adapter_image=input_image, num_inference_steps=50, generator=generator, ).images[0]
実行結果
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") # 実行結果 image.save(f"image_{formattedNow}_{generator.initial_seed()}.png")
まとめ
ControlNet のときは、pix2pix や inpaint のようなインプット画像を用いるものもありましたが、
ほぼ「コントロール画像」と「プロンプト」を用いて実行するものでした。
IP-Adapter を差し込むことで、更に「インプット画像」を追加することができることがわかりました。