ジャコ Lab

プログラミング関連のメモ帳的ブログです

ControlNet の Canny を使ってみる

前回の記事、ControlNet を使い始めました。
今回は、ControlNet の Canny を使ってみようと思います。

huggingface.co

Canny Edge を条件とする ControlNet とのことです

Canny

Canny Edge Detection は、画像処理においてエッジを検出するためのアルゴリズムの一つです

インプット画像からエッジを検出したものを使う ControlNet のようです

OpenCV をインストール

Canny Edge を検出する際に OpenCV を使用するため pip module をインストールしておきます

!pip install -U opencv-contrib-python

投入画像の準備

# 投入画像の準備
init_image_url = "https://huggingface.co/lllyasviel/control_v11p_sd15_canny/resolve/main/images/input.png"
init_image = load_image(init_image_url)

# コントロールイメージを作成するメソッド
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)

control_image = make_canny_condition(image, 100, 200)

投入画像を OpenCV を使って Canny Edge を検出します。
make_canny_condition() メソッドは、サンプルコードにはなかったメソッドですが、前回の make_inpaint_condition() を真似て作りました。

(左) 投入画像 | (右) Canny Edge 検出した画像

ControlNetModel, Pipeline の準備

import torch
from diffusers import ControlNetModel, StableDiffusionControlNetPipeline, UniPCMultistepScheduler

# ControlNet の準備
controlnet = ControlNetModel.from_pretrained(
    "lllyasviel/control_v11p_sd15_canny",
    torch_dtype=torch.float16
)

# パイプラインの準備
pipe = StableDiffusionControlNetPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype=torch.float16,
    controlnet=controlnet,
).to("cuda")
pipe.enable_model_cpu_offload()

# スケジューラの設定
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
  • ControlNet: "lllyasviel/control_v11p_sd15_canny" のモデルを使用
  • Pipeline: StableDiffusionControlNetPipeline
  • Model: "runwayml/stable-diffusion-v1-5"
  • Scheduler: UniPCMultistepScheduler

パイプライン実行

# パイプライン実行
prompt = "a blue paradise bird in the jungle"
image = pipe(
    prompt,
    num_inference_steps=20,
    generator=torch.Generator(device="cuda").manual_seed(33),
    image=control_image,
).images[0]

image=control_image なところが注意です。自分は Inpaint からの流れで control_image=control_image にしていてエラーになって少しハマってました。

ControlNet の Canny で生成した画像

まとめ

こうやって、元の画像に寄せた画像を出力していくんですね。。。
これなら、狙った画像が早めに出てきそうです。