Diffusers 文档

Stable Diffusion XL

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

Stable Diffusion XL

Stable Diffusion XL (SDXL) 是一个强大的文本到图像生成模型,它在前代的 Stable Diffusion 模型的基础上,在三个关键方面进行了迭代。

  1. UNet 的尺寸是原来的 3 倍,SDXL 将第二个文本编码器 (OpenCLIP ViT-bigG/14) 与原始文本编码器结合起来,显著增加了参数数量
  2. 引入了尺寸和裁剪条件,以保留来自丢弃的训练数据,并更好地控制生成图像的裁剪方式
  3. 引入了两阶段模型流程;基础模型(也可以作为独立模型运行)生成一个图像作为 精炼器 模型的输入,后者添加额外的高质量细节

本指南将向您展示如何使用 SDXL 进行文本到图像、图像到图像和图像修复。

在开始之前,请确保您已安装以下库

# uncomment to install the necessary libraries in Colab
#!pip install -q diffusers transformers accelerate invisible-watermark>=0.2.0

我们建议安装 invisible-watermark 库,以帮助识别生成的图像。如果安装了 invisible-watermark 库,则默认情况下会使用它。要禁用水印

pipeline = StableDiffusionXLPipeline.from_pretrained(..., add_watermarker=False)

加载模型检查点

模型权重可能存储在 Hub 上或本地的单独子文件夹中,在这种情况下,您应该使用 from_pretrained() 方法

from diffusers import StableDiffusionXLPipeline, StableDiffusionXLImg2ImgPipeline
import torch

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float16, variant="fp16", use_safetensors=True
).to("cuda")

refiner = StableDiffusionXLImg2ImgPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-refiner-1.0", torch_dtype=torch.float16, use_safetensors=True, variant="fp16"
).to("cuda")

您还可以使用 from_single_file() 方法从 Hub 或本地加载以单文件格式(.ckpt.safetensors)存储的模型检查点

from diffusers import StableDiffusionXLPipeline, StableDiffusionXLImg2ImgPipeline
import torch

pipeline = StableDiffusionXLPipeline.from_single_file(
    "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/blob/main/sd_xl_base_1.0.safetensors",
    torch_dtype=torch.float16
).to("cuda")

refiner = StableDiffusionXLImg2ImgPipeline.from_single_file(
    "https://huggingface.co/stabilityai/stable-diffusion-xl-refiner-1.0/blob/main/sd_xl_refiner_1.0.safetensors", torch_dtype=torch.float16
).to("cuda")

文本到图像

对于文本到图像,传递文本提示。默认情况下,SDXL 生成 1024x1024 的图像以获得最佳效果。您可以尝试将 heightwidth 参数设置为 768x768 或 512x512,但任何低于 512x512 的尺寸都不太可能有效。

from diffusers import AutoPipelineForText2Image
import torch

pipeline_text2image = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float16, variant="fp16", use_safetensors=True
).to("cuda")

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
image = pipeline_text2image(prompt=prompt).images[0]
image
generated image of an astronaut in a jungle

图像到图像

对于图像到图像,SDXL 在 768x768 到 1024x1024 之间的图像尺寸下效果特别好。传递初始图像和文本提示来调节图像

from diffusers import AutoPipelineForImage2Image
from diffusers.utils import load_image, make_image_grid

# use from_pipe to avoid consuming additional memory when loading a checkpoint
pipeline = AutoPipelineForImage2Image.from_pipe(pipeline_text2image).to("cuda")

url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/sdxl-text2img.png"
init_image = load_image(url)
prompt = "a dog catching a frisbee in the jungle"
image = pipeline(prompt, image=init_image, strength=0.8, guidance_scale=10.5).images[0]
make_image_grid([init_image, image], rows=1, cols=2)
generated image of a dog catching a frisbee in a jungle

图像修复

对于图像修复,您需要原始图像和要替换的原始图像部分的蒙版。创建一个提示来描述您要用什么替换蒙版区域。

from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

# use from_pipe to avoid consuming additional memory when loading a checkpoint
pipeline = AutoPipelineForInpainting.from_pipe(pipeline_text2image).to("cuda")

img_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/sdxl-text2img.png"
mask_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/sdxl-inpaint-mask.png"

init_image = load_image(img_url)
mask_image = load_image(mask_url)

prompt = "A deep sea diver floating"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, strength=0.85, guidance_scale=12.5).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
generated image of a deep sea diver in a jungle

精细化图像质量

SDXL 包含一个 精炼器模型,专门用于对低噪声阶段图像进行去噪,以从基础模型生成更高质量的图像。 有两种使用精炼器的方法

  1. 一起使用基础模型和精炼器模型以生成精细化图像
  2. 使用基础模型生成图像,然后使用精炼器模型向图像添加更多细节(这是 SDXL 最初的训练方式)

基础 + 精炼器模型

当您一起使用基础模型和精炼器模型来生成图像时,这被称为 专家去噪器集成。与将基础模型的输出传递给精炼器模型相比,专家去噪器集成方法需要的总体去噪步骤更少,因此运行速度应该明显更快。但是,您将无法检查基础模型的输出,因为它仍然包含大量噪声。

作为专家去噪器集成,基础模型在高噪声扩散阶段充当专家,而精炼器模型在低噪声扩散阶段充当专家。加载基础模型和精炼器模型

from diffusers import DiffusionPipeline
import torch

base = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float16, variant="fp16", use_safetensors=True
).to("cuda")

refiner = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-refiner-1.0",
    text_encoder_2=base.text_encoder_2,
    vae=base.vae,
    torch_dtype=torch.float16,
    use_safetensors=True,
    variant="fp16",
).to("cuda")

要使用此方法,您需要为每个模型定义时间步数,以便它们各自完成其阶段。对于基础模型,这由 denoising_end 参数控制,对于精炼器模型,这由 denoising_start 参数控制。

denoising_enddenoising_start 参数应为介于 0 和 1 之间的浮点数。这些参数表示为调度器定义的离散时间步长的比例。如果您还使用 strength 参数,它将被忽略,因为去噪步骤的数量由模型训练的离散时间步长和声明的分数截止值决定。

让我们设置 denoising_end=0.8,以便基础模型执行前 80% 的去噪高噪声时间步,并设置 denoising_start=0.8,以便精炼器模型执行后 20% 的去噪低噪声时间步。基础模型输出应为 latent 空间而不是 PIL 图像。

prompt = "A majestic lion jumping from a big stone at night"

image = base(
    prompt=prompt,
    num_inference_steps=40,
    denoising_end=0.8,
    output_type="latent",
).images
image = refiner(
    prompt=prompt,
    num_inference_steps=40,
    denoising_start=0.8,
    image=image,
).images[0]
image
generated image of a lion on a rock at night
默认基础模型
generated image of a lion on a rock at night in higher quality
专家去噪器集成

精炼器模型也可以用于 StableDiffusionXLInpaintPipeline 中的图像修复

from diffusers import StableDiffusionXLInpaintPipeline
from diffusers.utils import load_image, make_image_grid
import torch

base = StableDiffusionXLInpaintPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float16, variant="fp16", use_safetensors=True
).to("cuda")

refiner = StableDiffusionXLInpaintPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-refiner-1.0",
    text_encoder_2=base.text_encoder_2,
    vae=base.vae,
    torch_dtype=torch.float16,
    use_safetensors=True,
    variant="fp16",
).to("cuda")

img_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo.png"
mask_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo_mask.png"

init_image = load_image(img_url)
mask_image = load_image(mask_url)

prompt = "A majestic tiger sitting on a bench"
num_inference_steps = 75
high_noise_frac = 0.7

image = base(
    prompt=prompt,
    image=init_image,
    mask_image=mask_image,
    num_inference_steps=num_inference_steps,
    denoising_end=high_noise_frac,
    output_type="latent",
).images
image = refiner(
    prompt=prompt,
    image=image,
    mask_image=mask_image,
    num_inference_steps=num_inference_steps,
    denoising_start=high_noise_frac,
).images[0]
make_image_grid([init_image, mask_image, image.resize((512, 512))], rows=1, cols=3)

这种专家去噪器集成方法适用于所有可用的调度器!

基础模型到精炼器模型

SDXL 通过使用精炼器模型以图像到图像设置向来自基础模型的完全去噪图像添加额外的高质量细节,从而提高了图像质量。

加载基础模型和精炼器模型

from diffusers import DiffusionPipeline
import torch

base = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float16, variant="fp16", use_safetensors=True
).to("cuda")

refiner = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-refiner-1.0",
    text_encoder_2=base.text_encoder_2,
    vae=base.vae,
    torch_dtype=torch.float16,
    use_safetensors=True,
    variant="fp16",
).to("cuda")

您可以将 SDXL 精炼器与不同的基础模型一起使用。例如,您可以使用 Hunyuan-DiTPixArt-Sigma pipelines 生成具有更好 prompt 一致性的图像。生成图像后,您可以将其传递给 SDXL 精炼器模型以增强最终生成质量。

从基础模型生成图像,并将模型输出设置为 latent 空间

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"

image = base(prompt=prompt, output_type="latent").images[0]

将生成的图像传递给精炼器模型

image = refiner(prompt=prompt, image=image[None, :]).images[0]
generated image of an astronaut riding a green horse on Mars
基础模型
higher quality generated image of an astronaut riding a green horse on Mars
基础模型 + 精炼器模型

对于图像修复,在 StableDiffusionXLInpaintPipeline 中加载基础模型和精炼器模型,删除 denoising_enddenoising_start 参数,并为精炼器选择较小的推理步骤数。

微调条件

SDXL 训练涉及多种额外的条件技术,这些技术被称为 微调条件。这些条件包括原始图像尺寸、目标图像尺寸和裁剪参数。微调条件可以在推理时使用,以创建高质量的居中图像。

由于使用了无分类器引导,您可以使用微调条件和负微调条件参数。 它们在 StableDiffusionXLPipelineStableDiffusionXLImg2ImgPipelineStableDiffusionXLInpaintPipelineStableDiffusionXLControlNetPipeline 中可用。

尺寸条件控制

尺寸条件控制有两种类型

  • original_size 条件控制来自训练批次中放大后的图像(因为丢弃占总训练数据近 40% 的较小图像会造成浪费)。 这样,SDXL 就学习到放大伪影不应出现在高分辨率图像中。 在推理期间,您可以使用 original_size 来指示原始图像分辨率。 使用 (1024, 1024) 的默认值会生成更高质量的图像,这些图像类似于数据集中的 1024x1024 图像。 如果您选择使用较低的分辨率,例如 (256, 256),模型仍会生成 1024x1024 图像,但它们看起来会像数据集中的低分辨率图像(更简单的图案、模糊)。

  • target_size 条件控制来自微调 SDXL 以支持不同的图像宽高比。 在推理期间,如果您使用 (1024, 1024) 的默认值,您将获得一张类似于数据集中正方形图像构图的图像。 我们建议对 target_sizeoriginal_size 使用相同的值,但请随意尝试其他选项!

🤗 Diffusers 还允许您指定关于图像尺寸的负面条件,以引导生成避开某些图像分辨率

from diffusers import StableDiffusionXLPipeline
import torch

pipe = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float16, variant="fp16", use_safetensors=True
).to("cuda")

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
image = pipe(
    prompt=prompt,
    negative_original_size=(512, 512),
    negative_target_size=(1024, 1024),
).images[0]
在图像分辨率为 (128, 128)、(256, 256) 和 (512, 512) 的负面条件下生成的图像。

裁剪条件控制

先前 Stable Diffusion 模型生成的图像有时可能看起来被裁剪了。 这是因为图像实际上是在训练期间被裁剪的,以便批次中的所有图像都具有相同的大小。 通过以裁剪坐标为条件,SDXL 学习到不裁剪 - 坐标 (0, 0) - 通常与居中的主体和完整的面部相关联(这是 🤗 Diffusers 中的默认值)。 如果您想生成非中心构图,可以尝试不同的坐标!

from diffusers import StableDiffusionXLPipeline
import torch

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float16, variant="fp16", use_safetensors=True
).to("cuda")

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
image = pipeline(prompt=prompt, crops_coords_top_left=(256, 0)).images[0]
image
generated image of an astronaut in a jungle, slightly cropped

您还可以指定负面裁剪坐标,以引导生成避开某些裁剪参数

from diffusers import StableDiffusionXLPipeline
import torch

pipe = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float16, variant="fp16", use_safetensors=True
).to("cuda")

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
image = pipe(
    prompt=prompt,
    negative_original_size=(512, 512),
    negative_crops_coords_top_left=(0, 0),
    negative_target_size=(1024, 1024),
).images[0]
image

为每个文本编码器使用不同的提示

SDXL 使用两个文本编码器,因此可以为每个文本编码器传递不同的提示,这可以提高质量。 将您的原始提示传递给 prompt,并将第二个提示传递给 prompt_2(如果您使用负面提示,请使用 negative_promptnegative_prompt_2

from diffusers import StableDiffusionXLPipeline
import torch

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float16, variant="fp16", use_safetensors=True
).to("cuda")

# prompt is passed to OAI CLIP-ViT/L-14
prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
# prompt_2 is passed to OpenCLIP-ViT/bigG-14
prompt_2 = "Van Gogh painting"
image = pipeline(prompt=prompt, prompt_2=prompt_2).images[0]
image
generated image of an astronaut in a jungle in the style of a van gogh painting

双文本编码器还支持文本反演嵌入,这些嵌入需要单独加载,如 SDXL 文本反演 部分所述。

优化

SDXL 是一个大型模型,您可能需要优化内存才能使其在您的硬件上运行。 以下是一些节省内存和加速推理的技巧。

  1. 使用 enable_model_cpu_offload() 将模型卸载到 CPU 以解决内存溢出错误
- base.to("cuda")
- refiner.to("cuda")
+ base.enable_model_cpu_offload()
+ refiner.enable_model_cpu_offload()
  1. 使用 torch.compile 可加速约 20%(您需要 torch>=2.0
+ base.unet = torch.compile(base.unet, mode="reduce-overhead", fullgraph=True)
+ refiner.unet = torch.compile(refiner.unet, mode="reduce-overhead", fullgraph=True)
  1. 如果 torch<2.0,请启用 xFormers 以运行 SDXL
+ base.enable_xformers_memory_efficient_attention()
+ refiner.enable_xformers_memory_efficient_attention()

其他资源

如果您有兴趣尝试 SDXL 中使用的 UNet2DConditionModel 的最小版本,请查看以 PyTorch 编写并直接与 🤗 Diffusers 兼容的 minSDXL 实现。

< > 在 GitHub 上更新