HuggingFace Diffusers 0.12 : ノートブック : ControlNet

HuggingFace Diffusers 0.12 : ノートブック : ControlNet (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 03/27/2023 (v0.14.0)

* 本ページは、HuggingFace Diffusers の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

クラスキャット 人工知能 研究開発支援サービス

クラスキャット は人工知能・テレワークに関する各種サービスを提供しています。お気軽にご相談ください :

◆ 人工知能とビジネスをテーマに WEB セミナーを定期的に開催しています。スケジュール
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

  • 株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
  • sales-info@classcat.com  ;  Web: www.classcat.com  ;   ClassCatJP

 

 

HuggingFace Diffusers 0.12 : ノートブック : ControlNet

Stable Diffusion が一世を風靡して以来、人々は生成過程の結果に対してより制御を持つ方法を模索してきました。ControlNet はユーザが生成過程をかなりカスタマイズすることを可能にする最小限のインターフェイスを提供します。ControlNet を使用して、ユーザは、深度マップ, セグメンテーション・マップ, 走り描き, キー・ポイント, 等々のような様々な空間的コンテキストにより生成を簡単に条件付けることができます!

漫画の絵を信じられないほど一貫性のある realistic な写真に変えることができます。

Realistic Lofi Girl

Or even use it as your interior designer.

Before

After

貴方のスケッチの走り描きをアーティスティックな絵に変換することができます。

Before

After

また、有名なロゴの幾つかを活動的にします。

Before

After

With ControlNet, the sky is the limit 🌠

このノートブックでは、最初に StableDiffusionControlNetPipeline を紹介してから、様々な制御条件に対してそれをどのように適用できるかを示します。Let’s get controlling!

 

ControlNet: TL;DR

ControlNet は Lvmin Zhang と Maneesh Agrawala による Adding Conditional Control to Text-to-Image Diffusion Models (テキスト-to-画像変換拡散モデルへの条件付き制御の追加) で紹介されました。それは、Stable Diffusion のような拡散モデルへの追加の条件付けとして機能できる、様々な空間的コンテキストをサポートすることを可能にするフレームワークを導入しています。

ControlNet の訓練は以下のステップから構成されます :

  1. Stable Diffusion の潜在的 UNet のような拡散モデルの事前訓練済みパラメータを複製し (「訓練可能なコピー」(trainable copy) と呼称)、一方でまた事前訓練済みパラメータを別々に保持します (「locked コピー」(locked copy))。それは、locked パラメータ・コピーは大規模データセットから学習された膨大な知識を保存できるように、一方で訓練可能コピーはタスク固有な様相を学習するために使用されるようにします。

  2. パラメータの訓練可能なそして locked コピーは「ゼロ畳み込み」層 (詳細は こちら を参照) を通して接続され、これは ControlNet フレームワークの一部として最適化されます。これは、新しい条件が訓練されているとき、凍結モデルにより既に学習されたセマンティクスを保存する訓練トリックです。

Pictorially, training a ControlNet looks like so:

The diagram is taken from here.

 
ControlNet のような訓練のための訓練セットからのサンプルはこのようなものです (追加条件はエッジマップによります) :

プロンプト

元画像

条件付け
“bird”

同様に、ControlNet をセマンティック・セグメンテーション・マップで条件付けするならば、訓練サンプルはこのようなものになります :

プロンプト

元画像

条件付け
“big house”

新しいタイプの条件付けはすべて ControlNet 重みの新しいコピーを訓練する必要があります。論文は 8 つの異なる条件付けモデルを提案していて、それらはすべて Diffusers でサポートされます!

推論について、訓練済み拡散モデルの重みと訓練済み ControlNet 重みの両方が必要です。例えば、Stable Diffusion v1-5 を ControlNet チェック・ポイントと一緒に使用すると、単にオリジナルの Stable Diffusion モデルを使用する場合と比べておよそ 7 億のより多くのパラメータを必要とし、これは推論について ControlNet のメモリ消費量を少し多くします。

事前訓練済み拡散モデルは訓練の間に参照されますので、別の条件付けを使用するとき ControlNet パラメータを切り替える必要があるだけです。これは、以下で見るように、一つのアプリケーションで複数の ControlNet 重みを配置することを非常に簡単にします。

 

StableDiffusionControlNetPipeline

Before we begin, we want to give a huge shout-out to the community contributor Takuma Mori for having led the integration of ControlNet into Diffusers ❤️ .

ControlNet で実験するため、Diffusers は 他の Diffusers パイプライン に類似した StableDiffusionControlNetPipeline を公開しています。StableDiffusionControlNetPipeline の中心は controlnet 引数で、これは事前訓練済み拡散モデルの重みは同じままに、特定の訓練済み ControlNetModel インスタンスを提供することを可能にします。

このブログ投稿では、StableDiffusionControlNetPipeline で様々なユースケースを探求します。ウォークスルーしていく最初の ControlNet モデルは Canny モデルです – これは最もポピュラーなモデルの一つで、インターネットで見られる素晴らしい画像の幾つかを生成しました。

この Colab ノートブック で以下のセクションで示されるコードスニペットを自由に実行してください。

始める前に、必要なライブラリのすべてがインストールされていることを確認しましょう :

!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

この例のために有名な絵画 “Girl With A Pearl” (「真珠の耳飾りの少女」) を使用します。So, let’s download the image and take a look:

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

Next, we will put the image through the canny pre-processor:

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

As we can see, it is essentially edge detection.

そして、canny エッジ用の ControlNet モデル に加えて runwaylml/stable-diffusion-v1-5 をロードします。

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
)

Stable Diffusion のデフォルト PNDMScheduler を使用する代わりに、UniPCMultistepScheduler と呼ばれる、現在最速の拡散モデルスケジューラの一つを使用します。改良されたスケジューラの選択は推論時間を劇的に短縮できます – 私たちのケースでは、だいたい同じ画像生成品質を維持しながら、推論ステップ数を 50 から 20 に減じることができます。スケジューラに関する詳細は ここ で見つけられます。

from diffusers import UniPCMultistepScheduler

pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)

パイプラインを直接 GPU にロードする代わりに、enable_model_cpu_offload で実現できる、スマート CPU オフローディングを有効にします。

Stable Diffusion のような拡散モデルは推論中に一つだけではなく (逐次的に実行される) 複数のモデルコンポーネントを必要とすることを忘れないでください。Stable Diffusion with ControlNet の場合には、最初に CLIP テキストエンコーダを使用してから、拡散モデル unet と control ネット、そして VAE デコーダを使用し、最後に安全性チェッカーを実行します。殆どのコンポーネントは拡散過程の間に一度だけ実行され、従って常時 GPU メモリを専有する必要はありません。スマートモデル・オフローディングを有効にすることで、各コンポーネントはそれが必要なときだけ GPU にロードされることを確実にし、推論を大幅に遅くすることなくメモリ消費を大幅に節約できます。

Note : enable_model_cpu_offload を実行しているとき、パイプラインを GPU に .to(“cuda”) で手動で移動しないでください – ひとたび CPU オフローディングが有効になれば、パイプラインが GPU メモリ管理を自動的に処理します。

pipe.enable_model_cpu_offload()

最後に、素晴らしい FlashAttention/xformers アテンション層アクセラレーションをフル活用することを望みますので、これを有効にしましょう!もしこのコマンドが動作しない場合、xformers が正しくインストールされていないかもしれません。この場合には、次のコードの行を単にスキップすることができます。

pipe.enable_xformers_memory_efficient_attention()

Now we are ready to run the ControlNet pipeline!

Stable Diffusion 画像-to-画像変換パイプラインを使用して通常行なうように、依然として画像生成過程を誘導するためにプロンプトを提供します。しかし、ControlNet は生成画像に対してより多くの制御を可能にします、何故ならば作成したばかりの canny エッジ画像を使用して正確な合成 (composition) を制御することができるからです。

現代の有名人が 17 世紀のこの正確に同じ絵画のためにポーズを取っている幾つかの画像を見ることは楽しいでしょう。そしてそれを ControlNet で行なうことは本当に簡単です、プロンプトでこれらのセレブの名前を含めるだけです!

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)

Controlnet を再調整と組み合わせることも容易にできます!例えば、モデルを DreamBooth で再調整して、それを異なるシーンに私たち自身をレンダリングすることができます。

このブロク記事では、Controlnet を DreamBooth と共にどのように使用するかを示すために例として愛しの Mr Potato Head を使用していきます。

同じ Controlnet を使用できますが、Stable Diffusion 1.5 を使用する代わりに、Mr Potato Head モデル をパイプラインにロードしていきます – Mr Potato Head は Dreambooth 🥔 を使用して Mr Potato Head コンセプトで再調整された Stable Diffusion モデルです。

Let’s run the above commands again, keeping the same controlnet though!

model_id = "sd-dreambooth-library/mr-potato-head"
pipe = StableDiffusionControlNetPipeline.from_pretrained(
    model_id,
    controlnet=controlnet,
    torch_dtype=torch.float16,
)
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
pipe.enable_model_cpu_offload()
pipe.enable_xformers_memory_efficient_attention()

Now let’s make Mr Potato posing for Johannes Vermeer !

generator = torch.manual_seed(2)
prompt = "a photo of sks mr potato head, best quality, extremely detailed"
output = pipe(
    prompt,
    canny_image,
    negative_prompt="monochrome, lowres, bad anatomy, worst quality, low quality",
    generator=generator,
    num_inference_steps=20,
)
output.images[0]

It is noticeable that Mr Potato Head is not the best candidate but he tried his best and did a pretty good job in capture some of the essence 🍟

 
ControlNet のもう一つの唯一の (exclusive) 応用は、一つの画像からポーズを取り、正確に同じポーズを持つ別の画像を生成するためにそれを再利用できることです。そこでこの次の例では、Open Pose ControlNet を使用してヨガを行なう方法をスーパーヒーローに教えていきます!

First, we will need to get some images of people doing yoga:

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)

次に、controlnet_aux を通して簡単に利用可能な OpenPose プリプロセッサを使用してヨガのポーズを抽出しましょう。

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 を作成しましょう。幾つかのスーパーヒーロー画像を生成していきますが、上で示されたヨガのポーズでです。Let’s go 🚀

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_offload()
pipe.enable_xformers_memory_efficient_attention()

Now it’s yoga time!

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)

例題を通して、StableDiffusionControlNetPipeline の複数の様相 (facets) を探求して、Diffusers を通して ControlNet で遊ぶことがどれほど簡単で直感的であるかを示しました。しかしながら、ControlNet によってサポートされるすべてのタイプの条件付けをカバーしていません。To know more about those, we encourage you to check out the respective model documentation pages:

We welcome you to combine these different elements and share your results with @diffuserslib. Be sure to check out the Colab Notebook to take some of the above examples for a spin!

We also showed some techniques to make the generation process faster and memory-friendly by using a fast scheduler, smart model offloading and xformers. With these techniques combined the generation process should take only ~3 seconds on a V100 GPU and consumes just ~4 GBs of VRAM for a single image ⚡️

 

終わりに

We have been playing a lot with StableDiffusionControlNetPipeline, and our experience has been fun so far! We’re excited to see what the community builds on top of this pipeline. If you want to check out other pipelines and techniques supported in Diffusers that allow for controlled generation, check out our official documentation.

If you cannot wait to try out ControlNet directly, we got you covered as well! Simply click on one of the following spaces to play around with ControlNet:

 

以上