本文是Stable Diffusion系列第三篇。

前两篇文章我们介绍了在本地运行Stable Diffusion模型的方法,以及使用LoRA对模型生成的图片进行微调。

本篇文章中,我们将介绍两种技术来控制图像的生成过程,对模型图像生成进行引导,使得生成的图像更符合我们的需求。这样生成的图片,更具有商业价值。

图像生成引导技术

Stable Diffusion等文本转图像模型中,“对模型图像生成进行引导"是指通过提供额外的信息来控制图像生成过程,使其生成更符合预期的图像。引导的方法有多种,比如前两篇文章提及的“引导词”和LoRA都是引导技术的一种。在本篇文章中,重点介绍的是“使用参考图像”进行引导的方法,也就是Image to Image。试想一下:你先用草稿将绘画元素勾勒出来,然后利用该技术即可让AI对作品细节进行补充。

ControlNetAdapter

  • ControlNet是一种基于神经网络的技术。ControlNet使用一个神经网络来学习图像和文本描述之间的关系,并利用该关系来引导图像生成过程。
  • Adapter是一种基于提示嵌入prompt embedding的技术。提示嵌入是将文本提示转换为向量表示的过程。Adapter通过将提示嵌入与图像嵌入进行结合,来引导图像生成过程。

这个表格展示了这两种技术的工作原理及优缺点:

特性AdapterControlNet
工作原理基于提示嵌入基于神经网络
优点易于使用、灵活效果好、可控性强
缺点效果可能不佳、需要额外的训练数据使用复杂、需要训练数据

controlnet-aux

在开始前,我们先下载一个工具:

1
pip install controlnet-aux mediapipe

controlnet-aux提供了多种辅助模型,称为Detector。这些 Detector可以分析图像并提取特定的信息,然后将这些信息作为条件传递给 ControlNet,从而更精细地控制图像生成过程。这一步骤我们称之为生成“引导图”。以下是一些常见的Detector模型及其简介:

  • CannyDetector:
    • 功能:利用 Canny 边缘检测算法提取图像的边缘信息。
    • 应用场景:生成卡通插画、突出图像中的线条和结构、控制图像的锐利程度。
  • HEDdetector:
    • 功能:利用 HED 边缘检测算法提取图像的边缘信息,与 Canny 边缘检测相比,HED 能够检测更复杂的边缘。
    • 应用场景:类似于 CannyDetector,但适用于细节更丰富的图像。
  • LineartDetector:
    • 功能:提取图像中的线条艺术信息,例如漫画和素描中的线条。
    • 应用场景:生成线条艺术图像、将照片转换为线条艺术风格。
  • MidasDetector:
    • 功能:估计图像中物体的深度信息。
    • 应用场景:生成具有三维立体感和景深效果的图像、控制图像中景物的前后关系。
  • MLSDdetector (Multi-Line Style Detector):
    • 功能:提取图像中多种线条的样式信息,例如粗细、颜色和纹理。
    • 应用场景:生成具有特定线条风格的图像,例如漫画的不同类型或者艺术流派。
  • NormalBaeDetector:
    • 功能:估计图像中物体的表面法线信息,可以理解为物体表面的朝向。
    • 应用场景:生成更加逼真写实的图像,例如控制光照效果和材质质感。
  • OpenposeDetector:
    • 功能:检测图像中人体关键点的位置,例如头部、肩部、肘部等。
    • 应用场景:生成包含人物的图像,并控制人物的姿势和动作。
  • ZoeDetector (Object detector):
    • 功能:检测并识别图像中的物体类别。
    • 应用场景:控制图像中要生成或排除的物体类型,例如生成特定场景或物体组合的图像。

要使用这些Detector,需要先下载模型,地址:https://huggingface.co/lllyasviel/Annotators。你需要哪些Detector就下载哪些模型。省事的话就全部下载。

各种Detector对比

首先写一段代码运行Detector

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from controlnet_aux import HEDdetector
from diffusers.utils import load_image, make_image_grid

device = 'mps'
original_image = load_image("data/3.jpg")
hed = HEDdetector.from_pretrained("your/path/controlnet-annotators").to(device)

hed_image = hed(original_image)
image_grid = make_image_grid([original_image, hed_image], rows=1, cols=2)
image_grid.save("data/out.jpg")

代码很简单,就不做解释了,下面是各种Detector的效果演示:

  • CannyDetector:
  • HEDdetector:
  • LineartDetector:
  • MidasDetector:
  • MLSDdetector (Multi-Line Style Detector):
  • NormalBaeDetector:
  • OpenposeDetector:
  • ZoeDetector (Object detector):

各种Controlnet对比

以上我们使用Detector生成了各种“引导图”,接下来我们使用Controlnet对引导图进行创作。老规矩,先去hugging face下载模型,我们这次测试的Controlnet都是sdxl的,具体原因参考前两篇文章:

  • controlnet-canny-sdxl-1.0
  • controlnet-openpose-sdxl-1.0
  • controlnet-zoe-depth-sdxl-1.0
  • controlnet-depth-sdxl-1.0

编写代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from diffusers import StableDiffusionXLControlNetPipeline, ControlNetModel, DPMSolverSinglestepScheduler
from diffusers.utils import load_image, make_image_grid
from controlnet_aux import CannyDetector


device = 'mps'
original_image = load_image("data/3.jpg")
canny = CannyDetector()
canny_image = canny(original_image)

controlnet = ControlNetModel.from_pretrained(
    "your/path/controlnet-canny-sdxl-1.0",
    use_safetensors=True
)

pipe = StableDiffusionXLControlNetPipeline.from_single_file(
    "your/path/dreamshaperXL_v21TurboDPMSDE.safetensors",
    controlnet=controlnet,
    use_safetensors=True
).to(device)
pipe.scheduler = DPMSolverSinglestepScheduler.from_config(pipe.scheduler.config, use_karras_sigmas=True)
# pipe.enable_model_cpu_offload()

prompt = "masterpiece, 1girl, long hair, asian, sundress, cartoon"
negative_prompt = 'low quality, bad quality, sketches'

image = pipe(
    prompt,
    negative_prompt=negative_prompt,
    image=canny_image,
    # controlnet_conditioning_scale=0.5,
    height=1024,
    width=576,
    num_inference_steps=6,
    guidance_scale=2,
).images[0]
image_grid = make_image_grid([original_image, image], rows=1, cols=2)
image_grid.save("data/out.jpg")

提示词与上一篇文章一模一样,让我们来看一下生成的图片。

  • 使用CannyDetectorCannyControlnet
  • 使用OpenposeDetectorPoseControlnet
  • 使用MidasDetectorMidasControlnet

各种Adapter对比

Contronet一样,先去hugging face上下载模型,这次我们使用腾讯的t2i-adapter进行测试:

  • t2i-adapter-openpose-sdxl-1.0
  • t2i-adapter-depth-zoe-sdxl-1.0
  • t2i-adapter-sketch-sdxl-1.0
  • t2i-adapter-lineart-sdxl-1.0
  • t2i-adapter-canny-sdxl-1.0
  • t2i-adapter-depth-midas-sdxl-1.0

编写代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from diffusers import T2IAdapter, StableDiffusionXLAdapterPipeline, DPMSolverSinglestepScheduler
from diffusers.utils import load_image, make_image_grid
from controlnet_aux import CannyDetector

device = 'mps'
original_image = load_image("data/3.jpg")
canny = CannyDetector()
canny_image = canny(original_image)

adapter = T2IAdapter.from_pretrained("your/path/t2i-adapter-canny-sdxl-1.0")

pipe = StableDiffusionXLAdapterPipeline.from_single_file(
    "your/path/dreamshaperXL_v21TurboDPMSDE.safetensors",
    # controlnet=controlnet,
    adapter=adapter,
    use_safetensors=True
).to(device)
pipe.scheduler = DPMSolverSinglestepScheduler.from_config(pipe.scheduler.config, use_karras_sigmas=True)
# pipe.enable_model_cpu_offload()

prompt = "masterpiece, 1girl, long hair, asian, sundress, cartoon"
negative_prompt = 'low quality, bad quality, sketches'

image = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    image=canny_image,
    # controlnet_conditioning_scale=0.5,
    height=1024,
    width=576,
    num_inference_steps=6,
    guidance_scale=2,
).images[0]
image_grid = make_image_grid([original_image, image], rows=1, cols=2)
image_grid.save("data/out.jpg")
  • 使用CannyDetectorCannyAdapter
  • 使用OpenposeDetectorPoseAdapter
  • 使用CannyDetectorSketchAdapter
  • 使用HEDdetectorSketchAdapter
  • 使用LineartDetectorLineartAdapter
  • 使用MidasDetectorMidasAdapter

总结

从图片质量可以看出,ControlNet对于引导图的遵循和生成图片的质量都较Adapter高,具体使用情况如何,大家在使用前还是自己测试一下。