Stable Diffusion XL on diffusers

Stable Diffusion XL on diffusers

翻译自:https://huggingface.co/docs/diffusers/using-diffusers/sdxl v0.24.0 非逐字翻译

Stable Diffusion XL (SDXL) 是一个强大的图像生成模型,其在上一代 Stable Diffusion 的基础上主要做了如下优化:

  1. 参数量增加:SDXL 中 Unet 的参数量比前一代大了 3 倍,并且 SDXL 还引入了第二个 text-encoder(OpenCLIP ViT-bigG/14),整体参数量大幅增加。
  2. 引入了 size-conditioning 和 crop conditioning,在训练阶段有效利用起低分辨率图像,并在推理对生成的图片是否需要裁剪有更好的控制。
  3. 使用了两阶段的生成过程,除了第一阶段的 base 模型生成之外,还加入了一个 refiner 模型,使得生成图像的细节质量更高(其中 base 模型也可以单独使用,直接生成)

本文将介绍如何使用 diffusers 进行 text-to-image、image-to-image 和 inpainting。

加载模型参数

模型参数分别保存在不同的子目录中,可以使用 from_pretrained 方法来加载:

from diffusers import StableDiffusionXLPipeline, StableDiffusionXLImg2ImgPipeline
import torchpipeline = 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 方法来从单个文件 ( .ckpt 或 .safetensors) 中加载:

from diffusers import StableDiffusionXLPipeline, StableDiffusionXLImg2ImgPipeline
import torchpipeline = 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, variant="fp16", use_safetensors=True
).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, use_safetensors=True, variant="fp16"
).to("cuda")

text-to-image

在进行 text-to-image 生成时,需要传入文本 prompt。SDXL 默认生成分辨率为 1024 * 1024,也可以设置为 768 或 512,但不要再低于 512 了:

from diffusers import AutoPipelineForText2Image
import torchpipeline_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

在这里插入图片描述

image-to-image

在进行 image-to-image 生成时,SDXL 在 768 - 1024 这个分辨率区间工作的最好。此时需要输入一张原始图像,并给一段文本 prompt:

from diffusers import AutoPipelineForImage2Image
from diffusers.utils import load_image, make_image_grid# 使用 from_pipe,避免在加载 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)

在这里插入图片描述

inpainting

在记性 inpainting 时,需要传入一张原始图片和原始图片中你想要修改部分的 mask 图,并给一个文本 prompt 来描述 mask 区域需要生成什么内容:

from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_gridpipeline = 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)

在这里插入图片描述

refine image quality

SDXL 相比于之前的 SD 模型,一个很大的差别在于它包含了一个 refiner 模型。refiner 模型 可以接收 base 模型经过几步去噪之后的低噪声图像,并为图像生成更多高质量的细节。有两种使用 refiner 模型的方式:

  1. 同时使用 base 模型和 refiner 模型,来生成高质量图片
  2. 使用 base 模型生成一张图片,然后使用 refiner 模型为图片添加更多的细节(这是 SDXL 训练时的方式)

接下来分别介绍这两种方式的使用。

base + refiner model

当使用第一种方式,即同时使用 base 模型和 refiner 模型来生成图片时,称为 ensemble of expert denoisers。这种方式相比于第二种将 base 模型的输出给 refiner 模型中的方式来说,整体需要的去噪步数更少,因此会快很多。但这种方式我们看到的 base 模型的输出是带有一些噪声的。

在第一种方式中,base 模型负责高噪声阶段的去噪,refiner 模型负责低噪声阶段的去噪。首先加载 base 模型和 refiner 模型:

from diffusers import DiffusionPipeline
import torchbase = 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")

在使用 ensemble of expert denoisers 这种方式时,我们需要定义不同的模型在他们各自阶段的去噪步数。对于 base 模型,需要 denoising_end 参数,对于 refiner 模型,需要 denoising_start 参数。

denoising_startdenoising_end 参数都时 0-1 之间的一个小数,用于表示当前 schduler 下步数的比例。如果同时还传入了 strength 参数,它将被忽略,因为去噪步骤的数量是由模型训练的离散时间步长和声明的比例截止值决定的。

这里,我们设置 denoising_end 为 0.8,从而 base 模型会负责前 80% 的高噪声阶段的降噪,并设置 denoising_start 为 0.8,从而 refiner 模型会负责后 20% 的低噪声阶段的降噪。注意 base 模型的输出是在隐层 latent 空间的,而非可见的图片。

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

在这里插入图片描述

在 StableDiffusionXLInpaintPipeline 中,refiner 模型也可以用于进行 inpainting:

from diffusers import StableDiffusionXLInpaintPipeline
from diffusers.utils import load_image, make_image_grid
import torchbase = 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.7image = 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)

这种 ensemble of expert denoisers 的方式对于所有 scheduler 都可用。

base to refiner model

第二种方式通过 base 模型先生成一张完全去噪的图片,然后使用 refiner 模型以 image-to-image 的形式,为图片添加更多的高质量细节,这使得 SDXL 的生成质量有了极大的提高。首先加载 base 和 refiner 模型:

from diffusers import DiffusionPipeline
import torchbase = 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")

先使用 base 模型生成一张图片,注意将输出形式设置为 latent:

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"image = base(prompt=prompt, output_type="latent").images[0]

将生成的图片输入到 refiner 模型中:

image = refiner(prompt=prompt, image=image[None, :]).images[0]

在这里插入图片描述

要进行 inpainting,在 StableDiffusionXLInpaintPipeline 中加载 base 和 refiner 模型,去掉 denoising_enddenoising_start 参数,并为 refiner 模型设置一个较小的步数。

micro-conditioning

SDXL 训练时使用了许多额外的条件方式,即 micro-conditioning,包括 original_image_size、target_image_size 和 cropping parameters。在推理阶段,合理地使用 micro-conditioning 可以生成高质量的、居中的图片。

由于 classfier-free guidance 的存在,可以在 SDXL 相关的 pipeline 中使用 micro-conditioning 和 negative micro-conditioning 参数。

size conditioning

size conditioning 有两种:

  1. original size conditioning。训练集中有许多图片的分辨率是较低的,但又不能直接不用这些低分辨率图像(占比达 40%,丢了太浪费了),因此通常会对这些图像进行 resize,从而得到高分辨率的图像。在这个过程中,不可避免得会引入插值这种人工合成的模糊痕迹,被 SDXL 学到,而在真正的高分辨率图像中,是不该有这些痕迹的。因此训练时会告诉模型,这张图片实际是多少分辨率的,作为条件。

    在推理阶段,我们可以指定 original_size 来表示图像的原始尺寸。使用默认的 1024,能生成出与原始数据集中高分辨率图像类似的高质量图像。而如果将这个值设得很低,如 256,模型还是会生成分辨率为 1024 的图像,但就会带有低分辨率图像的特征(如模糊、模式简单等)。

  2. target size conditioning。SDXL 训练时支持多种不同的长宽比。

    推理时,如果使用默认的值 1024,生成的图像会看起来像方形图像(长宽比1:1)。这里建议将 target_size 和 original_size 设置为相同的值,但你也可以调一调这些参数实验一下看看。

在 diffusers 中,我们还可以指定有关图像大小的 negative 条件,从而引导生成远离某些图像分辨率:

from diffusers import StableDiffusionXLPipeline
import torchpipe = 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]

在这里插入图片描述

crop conditioning

SDXL 之前的 SD 模型的生成结果有时会看起来像是被裁剪过得。这是因为为了保证训练时每个 batch 内的尺寸一致,输入的训练数据确实有很多是裁剪过的。因此训练时,裁剪坐标也会作为条件给到模型。从而,在推理时,我们将裁剪坐标指定为 (0, 0) (也是 diffusers 默认值),就可以生成非裁剪的图片了。你也可以试着调一下裁剪坐标这个参数,看模型的生成结果会是什么样子,应该可以得到非居中的构图。

from diffusers import StableDiffusionXLPipeline
import torchpipeline = 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

在这里插入图片描述

同样可以指定 negative 裁剪坐标以引导生成远离某些裁剪参数:

from diffusers import StableDiffusionXLPipeline
import torchpipe = 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

Use a different prompt for each text-encoder

SDXL 有两个 text encoder,所以给两个 text encoder 传入不同的文本 prompt 是可能的,这可以提高生成质量(参考)。将原本的 prompt 传到 prompt 中,另一个 prompt 传到 prompt_2 中。如果使用 negative prompt 也是类似的,分别传到 negative_promptnegative_prompt_2

from diffusers import StableDiffusionXLPipeline
import torchpipeline = 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

SDXL 的双 text encoder 同样支持 textual inversion embeddings,需要分别加载,详情见:SDXL textual inversion 。

Optimizations

SDXL 的模型还是很大的,可能在一些设备上运行会比较吃力,以下是一些节约内存和提高推理速度的技巧。

  1. 如果显存不够,可以临时将模型 offload 到内存中

    # base.to("cuda")
    # refiner.to("cuda")
    base.enable_model_cpu_offload()
    refiner.enable_model_cpu_offload()
    
  2. 如果你使用的 torch 版本 > 2.0,那么使用 torch.cmpile 可以提速约 20%

    base.unet = torch.compile(base.unet, mode="reduce-overhead", fullgraph=True)
    refiner.unet = torch.compile(refiner.unet, mode="reduce-overhead", fullgraph=True)
    
  3. 如果你使用的 torch 版本 < 2.0,记得要用 xFormers 来提供 flash attention

    base.enable_xformers_memory_efficient_attention()
    refiner.enable_xformers_memory_efficient_attention()
    

Other resources

如果你想要研究下 SDXL 中 UNet2DConditionModel 的最小版本,可参考minSDXL 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/258148.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最新版IDEA专业版大学生申请免费许可证教学(无需学校教育邮箱+官方途径+非破解手段)

文章目录 前言1. 申请学籍在线验证报告2. 进入IDEA官网进行认证3. 申请 JB (IDEA) 账号4. 打开 IDEA 专业版总结 前言 当你进入本篇文章时, 你应该是已经遇到了 IDEA 社区版无法解决的问题, 或是想进一步体验 IDEA 专业版的强大. 本文是一篇学生申请IDEA免费许可证的教学, 在学…

Android之Binder原理剖析

一&#xff1a;Binder的全面介绍 binder的出现 George Hoffman当时任Be公司的工程师&#xff0c;他启动了一个名为OpenBinder 的项目&#xff0c;在Be公司被ParmSource公司收购后&#xff0c; OpenBinder 由Dinnie Hackborn继续开发&#xff0c;后来成为管理ParmOS6 Cobalt O…

全景万店通打造掌上智慧生活助手,助力店铺全景引流

随着网络经济的崛起&#xff0c;新一代的消费群体的消费习惯逐渐变得富有个性化&#xff0c;因此他们对于传统的营销方式具有视觉疲劳&#xff0c;传统广告的效果也越发微小&#xff0c;但是请明显来代言&#xff0c;成本又十分高昂&#xff0c;那么还有什么引流好方法呢&#…

无人机高空巡查+智能视频监控技术,打造森林防火智慧方案

随着冬季的到来&#xff0c;森林防火的警钟再次敲响&#xff0c;由于森林面积广袤&#xff0c;地形复杂&#xff0c;且人员稀少&#xff0c;一旦发生火灾&#xff0c;人员无法及时发现&#xff0c;稍有疏忽就会酿成不可挽救的大祸。无人机高空巡查智能视频监控是一种非常有效的…

element-ui upload组件中将file文件数据转成二进制流数据格式

方法一 handleBeforeUpload (file)const reader new FileReader()reader.readAsArrayBuffer(file)reader.onload async function (theFile) {const binary new Blob([theFile.target.result]) // 转成二进制流数据 即binary数据格式}}方法二 const aBlob new Blob([file],…

Ultimate VFX

Ultimate VFX 构建套件:

学习笔记9——JUC三种量级的锁机制

学习笔记系列开头惯例发布一些寻亲消息 链接&#xff1a;https://baobeihuijia.com/bbhj/contents/3/197325.html 多线程访问共享资源冲突 临界区&#xff1a;一段代码块存在对共享资源的多线程读写操作&#xff0c;称这段代码块为临界区 竞态条件&#xff1a;多个线程在临界…

基于jsp+servlet的图书管理系统

基于jspservlet的图书管理系统演示地址为 图书馆后台管理系统 用户名:mr ,密码:123 图书馆管理系统主要的目的是实现图书馆的信息化管理。图书馆的主要业务就是新书的借阅和归还&#xff0c; 因此系统最核心的功能便是实现图书的借阅和归还。此外&#xff0c;还需要提供图书…

如何排查rpc mount export: RPC: Timed out问题

文章目录 问题描述查看nfs服务是否运行正常如果以上都通过,尝试下面步骤 问题描述 我们将讨论您在 NFS 客户端上看到的 NFS 错误之一的故障排除。在尝试与 NFS 相关的命令时可以看到此错误&#xff0c;如下所示&#xff1a; 通常&#xff0c;当您看到此错误时&#xff0c;您也…

两个观察伦敦银关键点位的方法

所谓关键点位&#xff0c;就是伦敦银价格测试了之后容易出现走势转向的位置。例如银价上涨至某些关键点位后出现反转下跌&#xff0c;或者跌到某些关键点位后反转上涨。我们清楚关键点位对交易的重要性之后&#xff0c;就要开始了解怎么找到这些关键点位&#xff0c;下面我们就…

Xilinx FPGA——ISE时序约束“建立时间不满足”问题解决记录

一、现象 最近使用赛灵思的FPGA设计项目时&#xff0c;出现时序约束失效问题。 点进去发现如下&#xff1a; 一个始终约束没有生效&#xff0c;有多处报错。 二、原因 出现这个问题的原因是&#xff0c;建立时间不满足。 时序违例的主要原因是建立时间和保持时间不满足要求&a…

SAP 按比例替代的使用简介

相信很多PP顾问比较头大的问题就是替代料的问题,尤其是电子行业的替代料颇为复杂,本文主要讲解的是SAP系统标准的替代料的使用方式。 第一种:按比例替代 1、创建物料—MM01 成品: 11000001 原材料 31000002 原材料 31000003 原材料 31000004 2、创建BOM—CS01 维护替代…