使用ControlNet 控制 Stable Diffusion

news/2024/11/28 8:23:14/

本文将要介绍整合HuggingFace的diffusers 包和ControlNet调节生成文本到图像,可以更好地控制文本到图像的生成

ControlNet是一种通过添加额外条件来控制扩散模型的神经网络结构。它提供了一种增强稳定扩散的方法,在文本到图像生成过程中使用条件输入,如涂鸦、边缘映射、分割映射、pose关键点等。可以让生成的图像将更接近输入图像,这比传统的图像到图像生成方法有了很大的改进。

ControlNet 模型可以在使用小数据集进行训练。然后整合任何预训练的稳定扩散模型来增强模型,来达到微调的目的。

  • ControNet 的初始版本带有以下预训练权重:
  • Canny edge — 黑色背景上带有白色边缘的单色图像。
  • Depth/Shallow areas — 灰度图像,黑色代表深区域,白色代表浅区域。
  • Normal map — 法线贴图图像。
  • Semantic segmentation map——ADE20K 的分割图像。
  • HED edge — 黑色背景上带有白色软边缘的单色图像。
  • Scribbles — 黑色背景上带有白色轮廓的手绘单色涂鸦图像。
  • OpenPose (姿势关键点)— OpenPose 骨骼图像。
  • M-LSD — 仅由黑色背景上的白色直线组成的单色图像。

下面我们开始进行整合:

设置

建议在安装包之前创建一个新的虚拟环境。

diffusers

激活虚拟环境,执行以下命令:

 pip install diffusers

ControlNet要求diffusers>=0.14.0

accelerate

 pip install accelerate

本教程包含一些依赖于accelerate>=0.17.0,需要使用下面命令安装最新版本:

 pip install git+https://github.com/huggingface/accelerate

opencv-python

为了简单起见,我们使用canny边缘处理器,所以它需要opencv-python包。

Opencv-python有4个不同的包。官方文档推荐使用opencv-contrib-python包,但也可以使用以下任何包进行:

  • opencv-python主包
  • opencv-contrib-python -完整包(附带contrib/额外模块)
  • opencv-python-headless -没有GUI的主包
  • opencv-contrib-python-headless -没有GUI的完整包

所以我们这里使用完整包:

 pip install opencv-contrib-python

controlnet-aux

OpenPose处理器需要controlnet-aux包。执行如下命令安装:

 pip install controlnet-aux

xformers(可选)

xformers包可以提高了推理速度。最新版本为PyTorch 1.13.1提供了pip wheels支持。

 pip install -U xformers

conda可以安装支持torch1.12.1或torch1.13.1

 conda install xformers

好了,这里的环境就设置完毕了

canny edge图像生成

下面就是利用canny edge ControlNet进行图像生成。它需要一个精细的边缘图像作为输入。

创建一个名为canny_inference.py的新文件,并添加以下导入语句:

 import cv2import numpy as npfrom PIL import Image

然后,继续添加以下代码片段,从现有图像创建一个canny edge图像

 import cv2import numpy as npfrom PIL import Imageimage = Image.open('input.png')image = np.array(image)low_threshold = 100high_threshold = 200image = cv2.Canny(image, low_threshold, high_threshold)image = image[:, :, None]image = np.concatenate([image, image, image], axis=2)canny_image = Image.fromarray(image)canny_image.save('canny.png')

保存文件后执行如下命令将图像转换为canny edge图像。

 python canny_inference.py

看看下面的例子:

下一步是使用刚才生成的canny图像作为条件输入执行推理。

 import cv2import torchimport numpy as npfrom PIL import Imagefrom diffusers import StableDiffusionControlNetPipeline, ControlNetModel, DPMSolverMultistepScheduler

初始化ControlNet和Stable Diffusion管道

 canny_image = Image.fromarray(image)# canny_image.save('canny.png')# for deterministic generationgenerator = torch.Generator(device='cuda').manual_seed(12345)controlnet = ControlNetModel.from_pretrained("lllyasviel/sd-controlnet-canny",torch_dtype=torch.float16)pipe = StableDiffusionControlNetPipeline.from_pretrained("runwayml/stable-diffusion-v1-5",controlnet=controlnet,torch_dtype=torch.float16)# change the schedulerpipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)# enable xformers (optional), requires xformers installationpipe.enable_xformers_memory_efficient_attention()# cpu offload for memory saving, requires accelerate>=0.17.0pipe.enable_model_cpu_offload()

运行推理并保存生成的图像:

 # cpu offload for memory saving, requires accelerate>=0.17.0pipe.enable_model_cpu_offload()image = pipe("a beautiful lady, celebrity, red dress, dslr, colour photo, realistic, high quality",negative_prompt="cropped, out of frame, worst quality, low quality, jpeg artifacts, ugly, blurry, bad anatomy, bad proportions",num_inference_steps=20,generator=generator,image=canny_image,controlnet_conditioning_scale=0.5).images[0]image.save('output.png')

StableDiffusionControlNetPipeline接受以下参数:

controlnet_conditioning_scale -在将controlnet的输出添加到原始unet的剩余部分之前,将它们乘以controlnet_conditioning_scale。默认为1.0,接受0.0-1.0之间的任何值。

运行脚本,可以得到类似下面输出:

让我们用不同的输入图像和设置重新运行脚本:

 image = pipe("a beautiful lady wearing blue yoga pants working out on beach, realistic, high quality",negative_prompt="cropped, out of frame, worst quality, low quality, jpeg artifacts, ugly, blurry, bad anatomy, bad proportions",num_inference_steps=20,generator=generator,image=canny_image,controlnet_conditioning_scale=1.0).images[0]image.save('tmp/output.png')

结果如下:

OpenPose

下面可以尝试使用OpenPose图像作为条件输入:

controlnet-aux 模块支持将图像转换为 OpenPose 骨骼图像。我们创建一个名为 pose_inference.py 的新 Python 文件并添加以下导入:

 import torchfrom PIL import Imagefrom controlnet_aux import OpenposeDetectorfrom diffusers import StableDiffusionControlNetPipeline, ControlNetModel, DPMSolverMultistepScheduler

继续添加以下代码

 image = Image.open('input.png')openpose = OpenposeDetector.from_pretrained('lllyasviel/ControlNet')pose_image = openpose(image)pose_image.save('pose.png')

执行以下图像转换为OpenPose图像:

 python pose_inference.py

结果如下

下面我们开始根据OpenPose生成图像

 # for deterministic generationgenerator = torch.Generator(device='cuda').manual_seed(12345)controlnet = ControlNetModel.from_pretrained("lllyasviel/sd-controlnet-openpose",torch_dtype=torch.float16)pipe = StableDiffusionControlNetPipeline.from_pretrained("runwayml/stable-diffusion-v1-5",controlnet=controlnet,torch_dtype=torch.float16)# change the schedulerpipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)# enable xformers (optional), requires xformers installationpipe.enable_xformers_memory_efficient_attention()# cpu offload for memory saving, requires accelerate>=0.17.0pipe.enable_model_cpu_offload()# cpu offload for memory saving, requires accelerate>=0.17.0pipe.enable_model_cpu_offload()image = pipe("a beautiful hollywood actress wearing black dress attending award winning event, red carpet stairs at background",negative_prompt="cropped, out of frame, worst quality, low quality, jpeg artifacts, ugly, blurry, bad anatomy, bad proportions",num_inference_steps=20,generator=generator,image=pose_image,controlnet_conditioning_scale=1.0).images[0]image.save('output.png')

结果如下:

总结

可以看到ControlNet是一个非常强大的神经网络结构,通过添加额外的条件来控制扩散模型。目前还不支持Multi-ControlNet,开源社区有消息说正在积极开发中。这个新功能提供了可以使用多个控制网络,并将他们的输出一起用于图像生成,允许更好地控制整个图像。

https://avoid.overfit.cn/post/0663779d52484d0da5cc946b8f429f36

作者:Ng Wai Foong


http://www.ppmy.cn/news/39271.html

相关文章

面向对象编程(基础)9:封装性(encapsulation)

目录 9.1 为什么需要封装? 而“高内聚,低耦合”的体现之一: 9.2 何为封装性? 9.3 Java如何实现数据封装 9.4 封装性的体现 9.4.1 成员变量/属性私有化 实现步骤: 成员变量封装的好处: 9.4.2 私有化…

IEArch-卷积神经网络

一、感受 ​ 这次作业的神经网络是比上一次作业复杂的,上一次作业是“多层感知机(MLP)”,这一次的作业是“卷积神经网络(CNN)”。运算从原来的矩阵乘法变成了卷积,网络结构也更加复杂&#xff…

Pod生命周期简洁版

Pod 的生命周期 Pod 的生命周期 官方文档链接 Pod的status字段是一个PodStatus的对象,PodStatus中有一个phase字段。无论是手动创建还是通过Deployment等控制器创建,Pod对象总是应该处于其生命进程中以下几个阶段(phase)之一。 …

koa开发实践2:为koa项目添加路由模块

nodeJS server-side-developkoa开发实践2:为koa项目添加路由模块上一节:《 koa开发实践2:为koa项目添加路由模块 》| 下一节:《 koa开发实践3:在koa项目中使用 swagger 文档 》作者: 李俊才:…

Android 事件分发源码解析(基于API31)

文章目录事件分发从何说起?以一个什么框架去学习?重点关于事件事件是由一系列事件组成的事件流。这里先总览一下这三个方法都要做些什么:View的事件分发先明确一下框架中提到的问题:View 的事件分发源码分析总结ViewGroup的事件分…

@Lookup与@Bean@Scope获取原型实例,谁更胜一筹

那必然是 Lookup 呀 🛼他是谁 | 运行时查找 bean示例 | 谁更好呢作用 | 妙用多多他是谁 | 运行时查找 bean Lookup是Spring框架的一部分,它允许在运行时动态查找bean。使用Lookup注解的方法必须返回一个bean,它将在每次调用该方法时创建一个…

redis实战---乐观锁与悲观锁

乐观锁和悲观锁故事背景概念乐观锁悲观锁乐观锁示例悲观锁示例总结提升故事背景 概念 Redis是一个内存中的键值存储系统,支持多种数据结构,如字符串、哈希、列表等。Redis提供了两种锁机制,即乐观锁和悲观锁。 乐观锁 乐观锁是一种乐观的…

Properties

Properties概述: 是一个Map体系的集合类 Properties可以保存到流中或从流中加载 练习:Properties作为Map集合的使用 package com.aynu13;//练习:Properties作为Map集合的使用import java.util.Properties; import java.util.Set;public cla…