Compel の続きを遊んでみる
前回の記事で、Compel を使って重み付けをしました。
この記事では Compel の他の機能で遊んでみようと思います。
Blending
まずは、前回の記事同様、パイプライン及びスケジューラーを準備します
!pip install -U diffusers["torch"] transformers compel
import torch
from diffusers import StableDiffusionPipeline, UniPCMultistepScheduler
pipe = StableDiffusionPipeline.from_pretrained(
"CompVis/stable-diffusion-v1-4",
use_safetensors=True
)
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
pipe.to("cuda")
次に Compel を使って Blending を行います
from compel import Compel
compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
prompt_embeds = compel_proc('("a red cat playing with a ball", "jungle").blend(0.7, 0.8)')
generator = torch.Generator(device="cuda").manual_seed(33)
image = pipe(prompt_embeds=prompt_embeds, generator=generator, num_inference_steps=20).images[0]
image

今のところ一番可愛いと思います。この猫
文字列でメソッド呼び出しみたいなことを書いているのでなんとなく気持ち悪いです。。。
.blend() を使うところがポイントですね
jungle の部分を sea に変えて、ブレンドパラメータを調整してみました
from compel import Compel
from diffusers.utils import make_image_grid
compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
prompt_embeds = compel_proc('("a red cat playing with a ball", "sea").blend(0.8, 0.7)')
image = pipe(
"a red cat playing with a ball, sea",
generator=torch.Generator(device="cuda").manual_seed(33),
num_inference_steps=20
).images[0]
comple_image = pipe(
prompt_embeds=prompt_embeds,
generator=torch.Generator(device="cuda").manual_seed(33),
num_inference_steps=20
).images[0]
make_image_grid([image, comple_image], rows=1, cols=2)

Conjunction
Conjunction の意味を調べたら 接続詞 でした!
prompt_embeds = compel_proc('["a red cat", "playing with a", "ball"].and()')
generator = torch.Generator(device="cuda").manual_seed(55)
image = pipe(prompt_embeds=prompt_embeds, generator=generator, num_inference_steps=20).images[0]
image


Conjunction では .and() がポイントのようです
・torch.Generator(device="cuda").manual_seed(33)
・torch.Generator(device="cpu").manual_seed(55)
・torch.Generator(device="cpu").manual_seed(33)
Textual inversion
import torch
from diffusers import StableDiffusionPipeline
from compel import Compel, DiffusersTextualInversionManager
# パイプラインの準備
pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float16,
use_safetensors=True,
variant="fp16"
).to("cuda")
# Textual inversion
pipe.load_textual_inversion("sd-concepts-library/midjourney-style")
# Compel の準備
textual_inversion_manager = DiffusersTextualInversionManager(pipe)
compel_proc = Compel(
tokenizer=pipe.tokenizer,
text_encoder=pipe.text_encoder,
textual_inversion_manager=textual_inversion_manager
)
prompt_embeds = compel_proc('("A red cat++ playing with a ball <midjourney-style>")')
image = pipe(prompt_embeds=prompt_embeds).images[0]
image


シードを設定していないので同じ画像にならないのヨシとして、
同じ雰囲気の画像が出ていますね!
DreamBooth
import torch
from diffusers import DiffusionPipeline, UniPCMultistepScheduler
from compel import Compel
# パイプラインの準備
pipe = DiffusionPipeline.from_pretrained(
"sd-dreambooth-library/dndcoverart-v1",
torch_dtype=torch.float16
).to("cuda")
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
# Compel の準備
compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
prompt_embeds = compel_proc('("magazine cover of a dndcoverart dragon, high quality, intricate details, larry elmore art style").and()')
image = pipe(prompt_embeds=prompt_embeds).images[0]
image


Stable Diffusion XL
# --------------------------------------------------
# Stable Diffusion XL
# --------------------------------------------------
from compel import Compel, ReturnedEmbeddingsType
from diffusers import DiffusionPipeline
from diffusers.utils import make_image_grid
import torch
# パイプラインの準備
pipeline = DiffusionPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
variant="fp16",
use_safetensors=True,
torch_dtype=torch.float16
).to("cuda")
# Compel の準備
compel_proc = Compel(
tokenizer=[pipeline.tokenizer, pipeline.tokenizer_2] ,
text_encoder=[pipeline.text_encoder, pipeline.text_encoder_2],
returned_embeddings_type=ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED,
requires_pooled=[False, True]
)
# apply weights
prompt = ["a red cat playing with a (ball)1.5", "a red cat playing with a (ball)0.6"]
conditioning, pooled = compel_proc(prompt)
# generate image
generator = [torch.Generator().manual_seed(33) for _ in range(len(prompt))]
images = pipeline(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, generator=generator, num_inference_steps=30).images
make_image_grid(images, rows=1, cols=2)

こちらはバッチリ出力されました!
まとめ
物によって Compel インスタンスを生成する際の引数が異なっていたり、
実際の Prompt の渡し方が異なっていたり、
それぞれ使い方が異なっていました!
DreamBooth も派生モデルなのかな?と思って触ってましたが、
既存のモデルに数枚の画像を喰わせてファインチューニングできるもの?なんですかね?
ちゃんと使えるようになったら面白そうだと思いました。
LoRA との違いも謎ですが!!LoRA も自分で作れたら楽しそうです!!