ジャコ Lab

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

Compel の続きを遊んでみる

zako-lab929.hatenablog.com

前回の記事で、Compel を使って重み付けをしました。
この記事では Compel の他の機能で遊んでみようと思います。

Blending

huggingface.co

まずは、前回の記事同様、パイプライン及びスケジューラーを準備します

!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

Blending

今のところ一番可愛いと思います。この猫
文字列でメソッド呼び出しみたいなことを書いているのでなんとなく気持ち悪いです。。。
.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)

(左) 普通のプロンプト | (右) Compel(Blending) を使って生成した画像

Conjunction

huggingface.co

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

(左) ドキュメント | (右) Compel(Conjunction) を使って生成した画像

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

(左) ドキュメントの画像 | (右) Compel(Textual inversion) を使って生成した画像

シードを設定していないので同じ画像にならないのヨシとして、
同じ雰囲気の画像が出ていますね!

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

(左) ドキュメント | (右) Compel(DreamBooth) を使って生成した画像

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 で生成した画像

こちらはバッチリ出力されました!

まとめ

物によって Compel インスタンスを生成する際の引数が異なっていたり、
実際の Prompt の渡し方が異なっていたり、
それぞれ使い方が異なっていました!

DreamBooth も派生モデルなのかな?と思って触ってましたが、
既存のモデルに数枚の画像を喰わせてファインチューニングできるもの?なんですかね?
ちゃんと使えるようになったら面白そうだと思いました。 LoRA との違いも謎ですが!!LoRA も自分で作れたら楽しそうです!!