??從上圖可以看出,ControlNet的基本結構由一個對應的原先網絡的神經網絡模塊和兩個”零卷積“層組成。在訓練過程中,會”鎖死“原先網絡的權重,只更新ControlNet基本結構中的網絡”副本“和零卷積層的權重。這些可訓練的網絡”副本“將學會如何讓模型按照新的控制條件來生成結果,而被”鎖死“的網絡會保留原先網絡已經學會的所有知識。零卷積層是一些權重和偏置被初始化為0的1X1卷積層。訓練剛開始的時候,無論新添加的控制條件是什么,這些零卷積層都只輸出0,ControlNet不會對擴散模型的生成結果造成任何影響。隨著訓練過程的深入,ControlNet將逐漸調整擴展模型原先的生成過程,使得生成的圖像逐漸向新添加的控制條件靠近。

二、ControlNet訓練

? ? ? 將上面描述的ControlNet block堆疊14次就得到完整的ControlNet,如下圖所示:

 訓練一個附加到某個Stable Diffusion模型上的ControlNet的過程大致如下所示:

  1. 收集想要對其附加控制條件的數據集和對應的Prompt。假如想訓練一個通過人體關鍵點來對擴散模型的人體進行姿態控制的ControlNet,則首先需要收集一批人物圖片,并標注好這批人物圖片的Prompt以及對應的人體關鍵點的位置;
  2. 將Prompt輸入被”鎖死“的Stable Diffusion模型,并將標注好的圖像控制條件(如人體關鍵點的標注結果)輸入ControlNet,然后按照Stable Diffusion模型的訓練過程迭代ControlNet block權重;
  3. 在訓練過程中,隨機將50%的文本Prompt替換為空白字符串,這樣做的目的是”強制“網絡從圖像控制條件中學習更多的語義信息;
  4. 訓練結束后,便可以使用ControlNet對應的圖像控制條件(如輸入的人體關鍵點)來控制擴散模型生成符合條件的圖像

三、ControlNet示例

    本小節將介紹一些已經訓練好的ControlNet示例,都來自Huggingface。

3.1 ControlNet與Canny Edge

? ? ? ?Canny Edege是一種多階段的邊緣檢測算法,該算法可以從不同的視覺對象中提取有用的結構信息,從而顯著降低圖像處理過程中的數據處理量,ControlNet與Canny Edge結合使用的效果如下圖所示:

3.2 ControlNet與M-LSD Lines

? ? ? ?M-LSD Lines是另一種輕量化的邊緣檢測算法,擅長提取圖像中的直線線條。訓練在M-LSD Lines上的ControlNet適合室內環境方面的圖片。ControlNet與M-LSD Lines結合使用的效果,如下圖所示:

3.3 ControlNet與HED Boundary

? ? ? ?HED?Boundary可以保持輸入圖像更多信息,訓練在HED Boundary上的ControlNet適合用來重新上色和進行風格重構。ControlNet與HED Boundary結合使用的效果,如下圖所示:

 四、ControlNet實戰

    下面以Canny Edge為例,展示如何在Diffusers中使用StableDiffusionControlNetPipeline生成圖像。

安裝需要使用的庫

!pip install -q diffusers==0.14.0 transformers xformers git+https://
github.com/huggingface/accelerate.git

為了對應選擇ControlNet,需要安裝兩個依賴庫對圖像進行處理,以提取不同的圖像控制條件

!pip install -q opencv-contrib-python
!pip install -q controlnet_aux

以知名畫作《戴珍珠耳環的少女》為例進行展示ControlNet效果

from diffusers import StableDiffusionControlNetPipeline
from diffusers.utils import load_image
 
image = load_image(
"https://hf.co/datasets/huggingface/documentation-images/
resolve/main/diffusers/input_image_vermeer.png"
)
image

首先將這張圖片交給Canny?Edge邊緣提取器進行預處理

import cv2
from PIL import Image
import numpy as np
 
image = np.array(image)
 
low_threshold = 100
high_threshold = 200
 
image = 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

邊緣提取效果,如下圖所示:

可以看到Canny Edge能夠識別出圖像中物體的邊緣線條。接下來,需要導入runwaylml/stable-diffusion-v1-5模型以及能夠處理Canny Edge的ControlNet模型。為了加快推理速度,采用半精度(float16)。

from diffusers import StableDiffusionControlNetPipeline,ControlNetModel
import torch
 
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
)

使用當前速度最快的擴散模型調度器-UniPCMultistepScheduler,迭代20次就可以達到之前默認調度器50次迭代的效果。

from diffusers import UniPCMultistepScheduler
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.
config)

使用Canny Edge來控制所生成圖像中物體的確切位置和邊緣輪廓。下面代碼旨在生成一些人物的肖像,這些人物鈞擺出與《戴珍珠耳環的少女》相同的姿勢。在ControlNet和Canny Edge下,我們只需要在Prompt中提到這些人的姓名就可以了,代碼如下:

def image_grid(imgs, rows, cols):
assert len(imgs) == rows * cols
 
w, h = imgs[0].size
grid = Image.new("RGB", size=(cols * w, rows * h))
grid_w, grid_h = grid.size
 
for i, img in enumerate(imgs):
grid.paste(img, box=(i % cols * w, i // cols * h))
return grid
 
prompt = ", best quality, extremely detailed"
prompt = [t + prompt for t in ["Sandra Oh", "Kim Kardashian",
"rihanna", "taylor swift"]]
generator = [torch.Generator(device="cpu").manual_seed(2) for i
in range(len(prompt))]
 
output = pipe(
prompt,
canny_image,
negative_prompt=["monochrome, lowres, bad anatomy, worst
quality, low quality"] * len (prompt),
generator=generator,
num_inference_steps=20,
)
 
image_grid(output.images, 2, 2)

? 生成的人物肖像,如下圖所示:

?? ?還可以從一張圖片中提取身體姿態,然后用它生成具有完全相同的身體姿態的另一張圖片,代碼如下:

urls = "yoga1.jpeg", "yoga2.jpeg", "yoga3.jpeg", "yoga4.jpeg"
imgs = [
load_image("https://hf.co/datasets/YiYiXu/controlnet-testing/
resolve/main/" + url)
for url in urls
]
 
image_grid(imgs, 2, 2)

?? ?原始圖片如下圖所示:

提取瑜伽的身體姿態,代碼如下:

from controlnet_aux import OpenposeDetector
 
model = OpenposeDetector.from_pretrained("lllyasviel/ControlNet")
 
poses = [model(img) for img in imgs]
image_grid(poses, 2, 2)

提取效果,如下圖所示:

使用Open Pose ControlNet生成一些正在做瑜伽的超級英雄圖片,代碼如下:

controlnet = ControlNetModel.from_pretrained(
"fusing/stable-diffusion-v1-5-controlnet-openpose",
torch_dtype=torch.float16
)
 
model_id = "runwayml/stable-diffusion-v1-5"
pipe = StableDiffusionControlNetPipeline.from_pretrained(
model_id,
controlnet=controlnet,
torch_dtype=torch.float16,
)
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.
config)
pipe.enable_model_cpu_of f load()
pipe.enable_xformers_memory_efficient_attention()
 
generator = [torch.Generator(device="cpu").manual_seed(2) for i
in range(4)]
prompt = "super-hero character, best quality, extremely detailed"
output = pipe(
[prompt] * 4,
poses,
negative_prompt=["monochrome, lowres, bad anatomy, worst
quality, low quality"] * 4,
generator=generator,
num_inference_steps=20,
)
image_grid(output.images, 2, 2)

生成的效果,如下圖所示:

關于ControlNet更多的使用方法,可以參考如下:

lllyasviel/sd-controlnet-depth

lllyasviel/sd-controlnet-hed

lllyasviel/sd-controlnet-normal

lllyasviel/sd-controlnet-scribbl

lllyasviel/sd-controlnet-seg

lllyasviel/sd-controlnet-openpose

lllyasviel/sd-controlnet-mlsd

文章轉自微信公眾號@ArronAI

上一篇:

擴散模型實戰(十二):使用調度器DDIM反轉來優化圖像編輯

下一篇:

擴散模型實戰(十四):擴散模型生成音頻
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費