ジャコ Lab

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

SDXL-Turbo

この記事では diffusers v0.24.0 のリリースノート から SDXL-Turbo を使ってみます。

1ステップで出力できるくらいターボ!

早速やってみる (Text-to-Image)

モデルのロード (AutoPipelineForText2Image, stabilityai/sdxl-turbo)

import torch
from diffusers import AutoPipelineForText2Image

# SDXL-Turbo のモデルを AutoPipelineForText2Image でロードする
pipe = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/sdxl-turbo",
    torch_dtype=torch.float16,
    variant="fp16"
).to("cuda")

パイプライン実行

import torch

# シードの設定
generator = torch.Generator()
generator.seed()

# パイプライン実行
prompt = "A cinematic shot of a baby racoon wearing an intricate italian priest robe."
image = pipe(
    prompt,
    guidance_scale=0.0,
    num_inference_steps=1,
    generator=generator
).images[0]
驚くべき、ステップ数1

Make sure to set guidance_scale to 0.0 to disable, as the model was trained without it.
(モデルはそれなしでトレーニングされたため、無効にする場合は必ず guide_scale を 0.0 に設定してください。)

注意事項としては guidance_scale0.0 にセットしておいた方が良いみたいです。

A single inference step is enough to generate high quality images. Increasing the number of steps to 2, 3 or 4 should improve image quality.
(高品質の画像を生成するには、単一の推論ステップで十分です。 ステップ数を 2、3、または 4 に増やすと、画質が向上します。)

ステップ数は増やしても良いみたい

実行結果

SDXL-Turbo で出力した様子
SDXL-Turbo で出力した画像

1ステップの品質とは思えない...
たぶん LCM よりつおい

早速やってみる (Image-to-Image)

SDXL-Turbo では Image-to-Image も可能です。

モデルのロード (AutoPipelineForImage2Image, stabilityai/sdxl-turbo)

import torch
from diffusers import AutoPipelineForImage2Image

# SDXL-Turbo のモデルを AutoPipelineForImage2Image でロードする
pipe = AutoPipelineForImage2Image.from_pretrained(
    "stabilityai/sdxl-turbo",
    torch_dtype=torch.float16,
    variant="fp16"
).to("cuda")

インプット画像の用意

from diffusers.utils import load_image

init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/cat.png")
init_image = init_image.resize((512, 512))

パイプライン実行

import torch

# シードの設定
generator = torch.Generator()
generator.seed()

# パイプライン実行
prompt = "cat wizard, gandalf, lord of the rings, detailed, fantasy, cute, adorable, Pixar, Disney, 8k"
image = pipe(
    prompt,
    image=init_image,
    guidance_scale=0.0,
    strength=0.5,
    num_inference_steps=2,
    generator=generator
).images[0]

Text-to-Image で guidance_scale0.0 にするというルールがありましたが、Image-to-Image にも特殊なルールがあります。

For image-to-image generation, make sure that num_inference_steps * strength is larger or equal to 1.
(Image-to-Image の生成では、num_inference_steps * strength が 1 以上であることを確認してください。)

num_inference_steps * strength >= 1である必要があるみたい

実行結果

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")

# 実行結果
init_image.save(f"init_image_{formattedNow}_{generator.initial_seed()}.png")
image.save(f"image_{formattedNow}_{generator.initial_seed()}.png")

インプット画像アウトプット画像
(左) インプット画像 | (右) アウトプット画像

ついでに Kandinsky 3.0 を触ろうとしたが、、、

こちらは、モデルの違いだけだったので触れなくても良かったのですが、とりあえず実行してみました。

まぁしかし OutOfMemoryError: CUDA out of memory. ということで、結局触れられませんでした。

まとめ

SDXL って時間かかるからあまり使ってなかった傾向があるのですが、今の時代ではかなり高速になったんですねぇ。