前回の記事で T2I-Adapter というものを使ってみました。この記事では、ControlNet と比較しながらもっと色々な T2I-Adapter を使ってみようと思います。
ControlNet のときは1つ1つ丁寧に書いたけど、また1つ1つやるのは面倒なので一気にやりました!でも、SD 1.4 のやつだけで結構たいへんだったので SD 1.5 向けは次回がんばります。
- Color Adapter (SD 1.4)
- Canny Adapter (SD 1.4)
- Sketch Adapter (SD 1.4)
- Depth Adapter (SD 1.4)
- OpenPose Adapter (SD 1.4)
- KeyPose Adapter (SD 1.4)
- Seg Adapter (SD 1.4)
Color Adapter (SD 1.4)
これは前回の記事でやったやつですが、まとめ記事ということで掲載しておきます。
スクリプト全体
スクリプト全体 (折りたたみ)
投入画像の準備
from diffusers.utils import load_image from PIL import Image # 元画像 init_image_url = "https://huggingface.co/datasets/diffusers/docs-images/resolve/main/t2i-adapter/color_ref.png" init_image = load_image(init_image_url) # カラーパレット画像 input_image = init_image.resize((8, 8)) input_image = input_image.resize((512, 512), resample=Image.Resampling.NEAREST)
Adapter, Pipeline の準備
import torch from diffusers import StableDiffusionAdapterPipeline, T2IAdapter adapter = T2IAdapter.from_pretrained( "TencentARC/t2iadapter_color_sd14v1", torch_dtype=torch.float16 ) pipe = StableDiffusionAdapterPipeline.from_pretrained( "CompVis/stable-diffusion-v1-4", adapter=adapter, torch_dtype=torch.float16, ).to("cuda")
パイプラインの実行
from diffusers.utils import make_image_grid image = pipe( "At night, glowing cubes in front of the beach", image=input_image, generator=torch.Generator("cuda").manual_seed(7), ).images[0] make_image_grid([init_image, input_image, image], rows=1, cols=3)
実行結果
Canny Adapter (SD 1.4)
スクリプト全体
スクリプト全体 (折りたたみ)
事前定義
# Canny Edge を抽出するメソッド def make_canny_condition(image, low_threshold, high_threshold): image = np.array(image) image = cv2.Canny(image, low_threshold, high_threshold) # image = image[:, :, None] # image = np.concatenate([image, image, image], axis=2) return Image.fromarray(image)
投入画像の準備
import cv2 import numpy as np from diffusers.utils import load_image from PIL import Image # 元画像の準備 init_image_url = "https://huggingface.co/TencentARC/t2iadapter_canny_sd14v1/resolve/main/images/canny_input.png" init_image = load_image(init_image_url) # Canny Edge 画像 canny_image = make_canny_condition(init_image, 100, 200)
Adapter, Pipeline の準備
import torch from diffusers import T2IAdapter, StableDiffusionAdapterPipeline # アダプターの準備 adapter = T2IAdapter.from_pretrained( "TencentARC/t2iadapter_canny_sd14v1", torch_dtype=torch.float16 ) # パイプラインの準備 pipe = StableDiffusionAdapterPipeline.from_pretrained( "CompVis/stable-diffusion-v1-4", adapter=adapter, torch_dtype=torch.float16, ).to("cuda")
パイプラインの実行
from diffusers.utils import make_image_grid # パイプラインの実行 prompt = "a rabbit wearing glasses" image = pipe( prompt, image=canny_image, generator=torch.Generator("cuda").manual_seed(0), ).images[0] # 出力結果 make_image_grid([init_image, canny_image, image], rows=1, cols=3)
実行結果
T2I-Adapter vs ControlNet
T2I-Adapter | ControlNet |
---|---|
50/50 [00:13<00:00, 4.00it/s] | 50/50 [00:20<00:00, 2.90it/s] |
※T2I-Adapter は SD 1.4、ControlNet は SD 1.5 です。
Sketch Adapter (SD 1.4)
Sketch Adapter は、インプット画像を作成するために PidiNetDetector を使用しているので、 ControlNet で言うところの SoftEdge に該当しそうです。
スクリプト全体
スクリプト全体 (折りたたみ)
投入画像の準備
from controlnet_aux import PidiNetDetector from diffusers.utils import load_image # 元画像の準備 init_image_url = "https://huggingface.co/TencentARC/t2iadapter_sketch_sd14v1/resolve/main/images/sketch_in.png" init_image = load_image(init_image_url) # Sketch 画像 detector = PidiNetDetector.from_pretrained('lllyasviel/Annotators') sketch_image = detector(init_image)
Adapter, Pipeline の準備
import torch from diffusers import T2IAdapter, StableDiffusionAdapterPipeline # アダプターの準備 adapter = T2IAdapter.from_pretrained( "TencentARC/t2iadapter_zoedepth_sd15v1", torch_dtype=torch.float16 ) # パイプラインの準備 pipe = StableDiffusionAdapterPipeline.from_pretrained( "CompVis/stable-diffusion-v1-4", adapter=adapter, safety_checker=None, torch_dtype=torch.float16, variant="fp16" ).to('cuda')
パイプラインの実行
import torch from diffusers.utils import make_image_grid # パイプラインの実行 prompt = "royal chamber with fancy bed" image = pipe( prompt, image=sketch_image, generator=torch.Generator().manual_seed(0) ).images[0] # 出力結果 make_image_grid([init_image, sketch_image, image], rows=1, cols=3)
実行結果
T2I-Adapter vs ControlNet
T2I-Adapter | ControlNet |
---|---|
50/50 [00:10<00:00, 5.08it/s] | 50/50 [00:15<00:00, 3.68it/s] |
※T2I-Adapter は SD 1.4、ControlNet は SD 1.5 です。
Depth Adapter (SD 1.4)
スクリプト全体
スクリプト全体 (折りたたみ)
投入画像の準備
from controlnet_aux import MidasDetector from diffusers.utils import load_image # 元画像の準備 init_image_url = "https://huggingface.co/TencentARC/t2iadapter_depth_sd14v1/resolve/main/images/depth_input.png" init_image = load_image(init_image_url) # Depth 画像 detector = MidasDetector.from_pretrained("lllyasviel/Annotators") depth_image = detector(init_image)
Adapter, Pipeline の準備
import torch from diffusers import T2IAdapter, StableDiffusionAdapterPipeline # アダプターの準備 adapter = T2IAdapter.from_pretrained( "TencentARC/t2iadapter_depth_sd14v1", torch_dtype=torch.float16 ) # パイプラインの準備 pipe = StableDiffusionAdapterPipeline.from_pretrained( "CompVis/stable-diffusion-v1-4", adapter=adapter, safety_checker=None, torch_dtype=torch.float16, variant="fp16" ).to('cuda')
パイプラインの実行
import torch from diffusers.utils import make_image_grid # パイプラインの実行 prompt = "storm trooper giving a speech" image = pipe( prompt, image=depth_image, generator=torch.Generator().manual_seed(1) ).images[0] # 出力結果 make_image_grid([init_image, depth_image, image], rows=1, cols=3)
実行結果
T2I-Adapter vs ControlNet
T2I-Adapter | ControlNet |
---|---|
50/50 [00:07<00:00, 7.36it/s] | 50/50 [00:12<00:00, 4.99it/s] |
※T2I-Adapter は SD 1.4、ControlNet は SD 1.5 です。
OpenPose Adapter (SD 1.4)
スクリプト全体
スクリプト全体 (折りたたみ)
投入画像の準備
from controlnet_aux import OpenposeDetector from diffusers.utils import load_image # 元画像の準備 init_image_url = "https://huggingface.co/TencentARC/t2iadapter_openpose_sd14v1/resolve/main/images/openpose_input.png" init_image = load_image(init_image_url) # OpenPose 画像 detector = OpenposeDetector.from_pretrained('lllyasviel/ControlNet') openpose_image = detector(init_image)
Adapter, Pipeline の準備
import torch from diffusers import T2IAdapter, StableDiffusionAdapterPipeline # アダプターの準備 adapter = T2IAdapter.from_pretrained( "TencentARC/t2iadapter_openpose_sd14v1", torch_dtype=torch.float16 ) # パイプラインの準備 pipe = StableDiffusionAdapterPipeline.from_pretrained( "CompVis/stable-diffusion-v1-4", adapter=adapter, safety_checker=None, torch_dtype=torch.float16, variant="fp16" ).to('cuda')
パイプラインの実行
import torch from diffusers.utils import make_image_grid # パイプラインの実行 prompt="iron man flying" image = pipe( prompt, image=openpose_image, generator=torch.Generator().manual_seed(1) ).images[0] # 出力結果 make_image_grid([init_image, openpose_image, image], rows=1, cols=3)
実行結果
T2I-Adapter vs ControlNet
T2I-Adapter | ControlNet |
---|---|
50/50 [00:12<00:00, 4.52it/s] | 50/50 [00:18<00:00, 3.10it/s] |
※T2I-Adapter は SD 1.4、ControlNet は SD 1.5 です。
KeyPose Adapter (SD 1.4)
KeyPose Adapter というものもあるらしいですが、モデルカードが空っぽだったので詳細は不明です
Seg Adapter (SD 1.4)
スクリプト全体
スクリプト全体 (折りたたみ)
事前定義
import torch import numpy as np from transformers import AutoImageProcessor, UperNetForSemanticSegmentation from PIL import Image ada_palette = np.asarray([ [0, 0, 0], [120, 120, 120], [180, 120, 120], [6, 230, 230], [80, 50, 50], [4, 200, 3], [120, 120, 80], [140, 140, 140], [204, 5, 255], [230, 230, 230], [4, 250, 7], [224, 5, 255], [235, 255, 7], [150, 5, 61], [120, 120, 70], [8, 255, 51], [255, 6, 82], [143, 255, 140], [204, 255, 4], [255, 51, 7], [204, 70, 3], [0, 102, 200], [61, 230, 250], [255, 6, 51], [11, 102, 255], [255, 7, 71], [255, 9, 224], [9, 7, 230], [220, 220, 220], [255, 9, 92], [112, 9, 255], [8, 255, 214], [7, 255, 224], [255, 184, 6], [10, 255, 71], [255, 41, 10], [7, 255, 255], [224, 255, 8], [102, 8, 255], [255, 61, 6], [255, 194, 7], [255, 122, 8], [0, 255, 20], [255, 8, 41], [255, 5, 153], [6, 51, 255], [235, 12, 255], [160, 150, 20], [0, 163, 255], [140, 140, 140], [250, 10, 15], [20, 255, 0], [31, 255, 0], [255, 31, 0], [255, 224, 0], [153, 255, 0], [0, 0, 255], [255, 71, 0], [0, 235, 255], [0, 173, 255], [31, 0, 255], [11, 200, 200], [255, 82, 0], [0, 255, 245], [0, 61, 255], [0, 255, 112], [0, 255, 133], [255, 0, 0], [255, 163, 0], [255, 102, 0], [194, 255, 0], [0, 143, 255], [51, 255, 0], [0, 82, 255], [0, 255, 41], [0, 255, 173], [10, 0, 255], [173, 255, 0], [0, 255, 153], [255, 92, 0], [255, 0, 255], [255, 0, 245], [255, 0, 102], [255, 173, 0], [255, 0, 20], [255, 184, 184], [0, 31, 255], [0, 255, 61], [0, 71, 255], [255, 0, 204], [0, 255, 194], [0, 255, 82], [0, 10, 255], [0, 112, 255], [51, 0, 255], [0, 194, 255], [0, 122, 255], [0, 255, 163], [255, 153, 0], [0, 255, 10], [255, 112, 0], [143, 255, 0], [82, 0, 255], [163, 255, 0], [255, 235, 0], [8, 184, 170], [133, 0, 255], [0, 255, 92], [184, 0, 255], [255, 0, 31], [0, 184, 255], [0, 214, 255], [255, 0, 112], [92, 255, 0], [0, 224, 255], [112, 224, 255], [70, 184, 160], [163, 0, 255], [153, 0, 255], [71, 255, 0], [255, 0, 163], [255, 204, 0], [255, 0, 143], [0, 255, 235], [133, 255, 0], [255, 0, 235], [245, 0, 255], [255, 0, 122], [255, 245, 0], [10, 190, 212], [214, 255, 0], [0, 204, 255], [20, 0, 255], [255, 255, 0], [0, 153, 255], [0, 41, 255], [0, 255, 204], [41, 0, 255], [41, 255, 0], [173, 0, 255], [0, 245, 255], [71, 0, 255], [122, 0, 255], [0, 255, 184], [0, 92, 255], [184, 255, 0], [0, 133, 255], [255, 214, 0], [25, 194, 194], [102, 255, 0], [92, 0, 255], ]) # Seg を抽出するメソッド def make_seg_condition(image): image_processor = AutoImageProcessor.from_pretrained("openmmlab/upernet-convnext-small") pixel_values = image_processor(init_image, return_tensors="pt").pixel_values with torch.no_grad(): image_segmentor = UperNetForSemanticSegmentation.from_pretrained("openmmlab/upernet-convnext-small") outputs = image_segmentor(pixel_values) seg = image_processor.post_process_semantic_segmentation(outputs, target_sizes=[image.size[::-1]])[0] color_seg = np.zeros((seg.shape[0], seg.shape[1], 3), dtype=np.uint8) # height, width, 3 for label, color in enumerate(ada_palette): color_seg[seg == label, :] = color color_seg = color_seg.astype(np.uint8) return Image.fromarray(color_seg)
投入画像の準備
from diffusers.utils import load_image # 元画像の準備 init_image_url = "https://huggingface.co/TencentARC/t2iadapter_seg_sd14v1/resolve/main/images/seg_input.jpeg" init_image = load_image(init_image_url) # Seg 画像 seg_image = make_seg_condition(init_image)
Adapter, Pipeline の準備
import torch from diffusers import T2IAdapter, StableDiffusionAdapterPipeline # アダプターの準備 adapter = T2IAdapter.from_pretrained( "TencentARC/t2iadapter_seg_sd14v1", torch_dtype=torch.float16 ) # パイプラインの準備 pipe = StableDiffusionAdapterPipeline.from_pretrained( "CompVis/stable-diffusion-v1-4", adapter=adapter, safety_checker=None, torch_dtype=torch.float16, variant="fp16" ).to('cuda')
パイプラインの実行
import torch from diffusers.utils import make_image_grid prompt = "motorcycles driving" image = pipe( prompt, image=seg_image, generator=torch.Generator().manual_seed(0) ).images[0] # 出力結果 make_image_grid([init_image, seg_image, image], rows=1, cols=3)
実行結果
T2I-Adapter vs ControlNet
T2I-Adapter | ControlNet |
---|---|
50/50 [00:08<00:00, 6.19it/s] | 50/50 [00:14<00:00, 4.16it/s] |
※T2I-Adapter は SD 1.4、ControlNet は SD 1.5 です。