Diffusers documentation

インペインティング

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.42.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

インペインティング

Inpaintingは、画像の特定の領域を置き換えたり編集したりする処理です。これにより、欠陥やアーティファクトの除去といった画像復元、あるいは画像の領域をまったく新しいものに置き換える用途にも有用なツールとなります。Inpaintingはマスクに依存して、画像のどの領域を埋めるかを決定します。埋める対象の領域は白いピクセルで、保持する領域は黒いピクセルで表されます。白いピクセルはプロンプトによって埋められます。

🤗 Diffusers を使用してインペインティングを行う方法をご紹介します。

  1. AutoPipelineForInpainting クラスを使用してインペインティングのチェックポイントをロードします。チェックポイントに基づいて、読み込むべき適切なパイプラインクラスが自動的に検出されます。
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "kandinsky-community/kandinsky-2-2-decoder-inpaint", dtype=torch.float16
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

本ガイドでは、メモリを節約し推論速度を向上させるために、enable_model_cpu_offload() と enable_xformers_memory_efficient_attention() を使用しています。PyTorch 2.0 を使用している場合、パイプラインに対して enable_xformers_memory_efficient_attention() を呼び出す必要はありません。PyTorch 2.0 のネイティブな scaled-dot product attention がすでに使用されているためです。

  1. ベース画像とマスク画像を読み込みます:
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")
  1. インペイントに使用するプロンプトを作成し、ベース画像とマスク画像とともにパイプラインに渡します:
prompt = "a black cat with glowing eyes, cute, adorable, disney, pixar, highly detailed, 8k"
negative_prompt = "bad anatomy, deformed, ugly, disfigured"
image = pipeline(prompt=prompt, negative_prompt=negative_prompt, image=init_image, mask_image=mask_image).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
ベースイメージ
マスク画像
生成された画像

マスク画像を作成する

本ガイドでは、利便性のため、すべてのコード例にマスク画像が用意されています。ご自身の画像でインペイントを行うことも可能ですが、そのためにはマスク画像を作成する必要があります。以下のSpaceを使用して、簡単にマスク画像を作成してください。

インペイントのベース画像をアップロードし、スケッチツールでマスクを描画します。完了したら、Run をクリックしてマスク画像を生成し、ダウンロードします。

マスクのぼかし

blur() メソッドは、元の画像とインペイント領域をブレンドする方法に関するオプションを提供します。ぼかしの量は blur_factor パラメータによって決定されます。blur_factor を大きくすると、マスクの縁に適用されるぼかしが増加し、元の画像とインペイント領域の間の遷移が滑らかになります。一方、blur_factor が低いかゼロの場合、マスクの縁はよりシャープに保たれます。

これを使用するには、image processorでぼかしマスクを作成します。

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image
from PIL import Image

pipeline = AutoPipelineForInpainting.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16).to('cuda')  # or "mps", "xpu", "cpu"

mask = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/seashore_mask.png")
blurred_mask = pipeline.mask_processor.blur(mask, blur_factor=33)
blurred_mask
ぼかしなしのマスク
ぼかしが適用されたマスク

人気モデル

Stable Diffusion Inpainting、Stable Diffusion XL (SDXL) Inpainting、Kandinsky 2.2 Inpaintingは、インペインティングに最も人気のあるモデルの1つです。SDXLは通常、Stable Diffusion v1.5よりも高解像度の画像を生成し、Kandinsky 2.2も高品質な画像を生成できます。

Stable Diffusion Inpainting

Stable Diffusion Inpainting は、インペインティング用に 512x512 の画像でファインチューニングされた潜在拡散モデルです。比較的速く、高品質な画像を生成できるため、良い出発点となります。このモデルをインペインティングに使用するには、プロンプト、ベース画像、マスク画像をパイプラインに渡す必要があります。

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)

Stable Diffusion XL (SDXL) Inpainting

SDXLは、Stable Diffusion v1.5のより大型で高性能なバージョンです。このモデルは2段階のモデル処理に従うことができます(ただし、各モデルは単独でも使用可能です)。ベースモデルが画像を生成し、リファイナーモデルがその画像を受け取って、詳細と品質をさらに向上させます。SDXLの使用方法やパラメータの構成について、より包括的なガイドについては、SDXLガイドをご覧ください。

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "diffusers/stable-diffusion-xl-1.0-inpainting-0.1", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)

Kandinsky 2.2 Inpainting

Kandinskyモデルファミリーは、2つのモデルを使用する点でSDXLに似ています。image priorモデルが画像埋め込みを作成し、diffusionモデルがそれらから画像を生成します。image priorモデルとdiffusionモデルを個別に読み込むことも可能ですが、Kandinsky 2.2を使用する最も簡単な方法は、AutoPipelineForInpaintingクラスに読み込むことです。このクラスは内部でKandinskyV22InpaintCombinedPipelineを使用しています。

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "kandinsky-community/kandinsky-2-2-decoder-inpaint", dtype=torch.float16
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
ベースイメージ
Stable Diffusion Inpainting
Stable Diffusion XL Inpainting
Kandinsky 2.2 Inpainting

インペイント専用ではないチェックポイント

これまでこのガイドでは、stable-diffusion-v1-5/stable-diffusion-inpainting といったインペイント専用のチェックポイントを使用してきました。しかし、stable-diffusion-v1-5/stable-diffusion-v1-5 のような通常のチェックポイントを使用することもできます。ここでは、2つのチェックポイントの結果を比較します。

左の画像は通常のチェックポイントから生成されたもので、右の画像はインペイント用のチェックポイントから生成されたものです。一目でわかるように、左の画像はそれほどクリーンではなく、モデルがインペイントすべき領域の輪郭がまだ見えます。一方、右の画像ははるかにクリーンで、インペイントされた領域もより自然に見えます。

stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpainting
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, image], rows=1, cols=2)
stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpainting

ただし、画像からオブジェクトを消去するといったより基本的なタスク(例えば、道に転がっている岩を消す場合など)では、通常のチェックポイントでもかなり良い結果が得られます。通常のチェックポイントとインペイント用のチェックポイントとの間には、それほど顕著な差はありません。

stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpaint
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/road-mask.png")

image = pipeline(prompt="road", image=init_image, mask_image=mask_image).images[0]
make_image_grid([init_image, image], rows=1, cols=2)
stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpainting

インペイント専用でないチェックポイントを使用するトレードオフは、全体の画像品質が低くなる可能性があることです。ただし、一般的にはマスク領域を保持する傾向があります(そのためマスクの輪郭が見えます)。インペイント専用のチェックポイントは、より高品質なインペイント画像を生成するように意図的に訓練されており、マスク領域とマスクされていない領域の間のより自然な遷移の作成も含まれます。その結果、これらのチェックポイントは、マスクされていない領域を変更する可能性が高くなります。

タスクにおいてマスクされていない領域の保持が重要である場合、VaeImageProcessor.apply_overlay() メソッドを使用することで、マスク領域とマスクされていない領域の間の遷移がやや不自然になることを代償に、画像のマスクされていない領域を元のまま維持できます。

import PIL
import numpy as np
import torch

from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

device = "cuda"  # or "mps", "xpu", "cpu"
pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting",
    dtype=torch.float16,
    variant="fp16"
)
pipeline = pipeline.to(device)

img_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo.png"
mask_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo_mask.png"

init_image = load_image(img_url).resize((512, 512))
mask_image = load_image(mask_url).resize((512, 512))

prompt = "Face of a yellow cat, high resolution, sitting on a park bench"
repainted_image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image).images[0]
repainted_image.save("repainted_image.png")

unmasked_unchanged_image = pipeline.image_processor.apply_overlay(mask_image, init_image, repainted_image)
unmasked_unchanged_image.save("force_unmasked_unchanged.png")
make_image_grid([init_image, mask_image, repainted_image, unmasked_unchanged_image], rows=2, cols=2)

パイプラインのパラメータを設定

画像の特徴(品質や「創造性」など)は、パイプラインのパラメータに依存します。これらのパラメータが何をするものかを理解することは、望む結果を得るために重要です。最も重要なパラメータを確認し、それらを変更した際に出力がどのように変化するのかを見ていきましょう。

強さ

strengthは、ベース画像に追加されるノイズの量を表す指標であり、出力がベース画像とどれだけ類似しているかを左右します。

  • 📈 strength の値が高いほど、画像に追加されるノイズが増え、デノイジング処理に時間がかかりますが、ベースの画像とより大きく異なる高品質な画像が得られます。
  • 📉 strength の値が低い場合、画像に追加されるノイズが少なくなり、デノイジング処理は速くなりますが、画像の品質はそれほど高くならず、生成された画像はベース画像に似通ったものになります
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, strength=0.6).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
strength = 0.6
strength = 0.8
strength = 1.0

ガイダンススケール

guidance_scale は、テキストプロンプトと生成された画像の一致度合いに影響します。

  • 📈 guidance_scale の値が高い場合、プロンプトと生成された画像が密接に一致することを意味し、出力はプロンプトのより厳密な解釈となります
  • 📉 guidance_scale の値が低い場合、プロンプトと生成された画像の整合性が緩やかになるため、プロンプトからの出力のばらつきが大きくなる可能性があります

strengthとguidance_scaleを組み合わせることで、モデルの表現力に対してより詳細な制御を行うことができます。例えば、strengthとguidance_scaleの値をともに高く設定すると、モデルに最大の創造的な自由度を与えることができます。

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, guidance_scale=2.5).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
guidance_scale = 2.5
guidance_scale = 7.5
guidance_scale = 12.5

ネガティブプロンプト

ネガティブプロンプトは、プロンプトとは逆の役割を担います。画像生成において特定の要素を生成しないようモデルを誘導します。これにより、画像の品質を素早く向上させ、望ましくない要素の生成を防ぐことができます。

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
negative_prompt = "bad architecture, unstable, poor details, blurry"
image = pipeline(prompt=prompt, negative_prompt=negative_prompt, image=init_image, mask_image=mask_image).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
negative_prompt = "bad architecture, unstable, poor details, blurry"

パディングマスクの切り取り

インペインティングの画像品質を向上させる方法として、padding_mask_crop パラメータを使用できます。このオプションを有効にすると、ユーザーが指定したパディング付きでマスク領域をクロップし、元の画像からも同じ領域をクロップします。その後、画像とマスクの両方をインペインティング用に高解像度にアップスケールし、元の画像に重ね合わせます。StableDiffusionUpscalePipeline のような別のパイプラインを使用せずに、画像品質を簡単に向上させるための迅速な方法です。

パイプラインの呼び出しにpadding_mask_cropパラメータを追加し、希望するパディング値に設定します。

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image
from PIL import Image

generator = torch.Generator(device='cuda').manual_seed(0)  # or "mps", "xpu", "cpu"
pipeline = AutoPipelineForInpainting.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16).to('cuda')

base = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/seashore.png")
mask = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/seashore_mask.png")

image = pipeline("boat", image=base, mask_image=mask, strength=0.75, generator=generator, padding_mask_crop=32).images[0]
image
デフォルトのインペイント画像
padding_mask_cropを有効にして画像をインペイント

チェーンされたインペインティングパイプライン

AutoPipelineForInpainting は、他の 🤗 Diffusers パイプラインと組み合わせることで、それらの出力を編集できます。これは他の拡散パイプラインからの出力品質を向上させる際に頻繁に役立ちます。また、複数のパイプラインを使用している場合、それらをチェーン化して出力を潜在空間に保持し、同じパイプラインコンポーネントを再利用することで、メモリ効率を高めることができます。

テキストから画像へ、さらにインペイントへ

テキストから画像を生成するパイプラインとインペインティングパイプラインをチェーン(連結)することで、生成された画像をインペインティングできます。そのため、最初にベース画像を用意する必要はありません。これにより、完全に新しい画像を生成しなくても、お気に入りのテキストから画像を生成した出力を編集できるため、便利です。

城を生成するために、テキストから画像へのパイプラインから始めます:

import torch
from diffusers import AutoPipelineForText2Image, AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForText2Image.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16, variant="fp16", use_safetensors=True
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

text2image = pipeline("concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k").images[0]

上記の出力のマスク画像を読み込みます:

mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_text-chain-mask.png")

では、マスクされた領域に滝をインペイントしてみましょう:

pipeline = AutoPipelineForInpainting.from_pretrained(
    "kandinsky-community/kandinsky-2-2-decoder-inpaint", dtype=torch.float16
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

prompt = "digital painting of a fantasy waterfall, cloudy"
image = pipeline(prompt=prompt, image=text2image, mask_image=mask_image).images[0]
make_image_grid([text2image, mask_image, image], rows=1, cols=3)
テキストから画像
inpaint

インペイントから画像へ画像へ

インペインティングパイプラインを、image-to-imageやアップスケーラーなどの別のパイプラインの前にチェーンすることで、品質を向上させることもできます。

画像のインペインティングから始めます:

import torch
from diffusers import AutoPipelineForInpainting, AutoPipelineForImage2Image
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image_inpainting = pipeline(prompt=prompt, image=init_image, mask_image=mask_image).images[0]

# resize image to 1024x1024 for SDXL
image_inpainting = image_inpainting.resize((1024, 1024))

では、SDXLのrefinerモデルを備えた別のinpaintingパイプラインに画像を渡し、画像の詳細と品質を向上させましょう:

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stabilityai/stable-diffusion-xl-refiner-1.0", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

image = pipeline(prompt=prompt, image=image_inpainting, mask_image=mask_image, output_type="latent").images[0]

パイプライン内でoutput_type="latent"を指定し、すべての出力を潜在空間に保つことが重要です。これにより、不要なデコード・エンコードのステップを回避できます。この機能は、チェーンされたパイプラインが同じVAEを使用している場合にのみ動作します。例えば、Text-to-image-to-inpaintのセクションでは、Kandinsky 2.2はStable Diffusionモデルとは異なるVAEクラスを使用しているため、この方法は機能しません。しかし、両方のパイプラインにStable Diffusion v1.5を使用すれば、どちらもAutoencoderKLを使用しているため、すべてを潜在空間に保つことができます。

最後に、この画像をimage-to-imageパイプラインに渡して仕上げを行います。既存のパイプラインのコンポーネントを再利用し、パイプラインのコンポーネントをすべてメモリに再度読み込むのを避けるため、from_pipe()メソッドを使用する方が効率的です。

pipeline = AutoPipelineForImage2Image.from_pipe(pipeline)
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

image = pipeline(prompt=prompt, image=image).images[0]
make_image_grid([init_image, mask_image, image_inpainting, image], rows=2, cols=2)
初期画像
inpaint
image-to-image

Image-to-image and inpainting are actually very similar tasks. Image-to-image generates a new image that resembles the existing provided image. Inpainting does the same thing, but it only transforms the image area defined by the mask and the rest of the image is unchanged. You can think of inpainting as a more precise tool for making specific changes and image-to-image has a broader scope for making more sweeping changes.

画像生成の制御

negative_promptなどのパラメータを設定することで生成の特定の側面を制御することはできますが、デノイジングプロセスはランダムであるため、イメージを完全に意図した通りに見せることは困難です。イメージ生成を制御するための、より優れたかつ効率的な方法があります。

プロンプトの重み付け

Prompt weighting(プロンプト重み付け)は、プロンプト内の概念の表現を定量的にスケーリングする方法を提供します。これにより、プロンプト内の各概念のテキスト埋め込みベクトルの大きさを増減させることができ、その結果として各概念がどの程度生成されるかが決定されます。Compelライブラリは、プロンプトの重みをスケーリングし、埋め込みを生成するための直感的な構文を提供します。埋め込みの作成方法については、Prompt weightingガイドを参照してください。

埋め込みを生成したら、AutoPipelineForInpainting の prompt_embeds パラメータ(ネガティブプロンプトを使用している場合は negative_prompt_embeds も)に渡します。埋め込みは prompt パラメータに置き換わります。

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16,
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

image = pipeline(prompt_embeds=prompt_embeds, # generated from Compel
    negative_prompt_embeds=negative_prompt_embeds, # generated from Compel
    image=init_image,
    mask_image=mask_image
).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)

ControlNet

ControlNetモデルは、Stable Diffusionなどの他の拡散モデルと組み合わせて使用され、画像の生成方法をより柔軟かつ正確に制御するための方法を提供します。ControlNetは、追加の条件付け画像入力を受け取り、拡散モデルがその中の特徴を保持するように導きます。

例えば、インペイント画像で事前学習されたControlNetで画像を条件付けます:

import torch
import numpy as np
from diffusers import ControlNetModel, StableDiffusionControlNetInpaintPipeline
from diffusers.utils import load_image, make_image_grid

# load ControlNet
controlnet = ControlNetModel.from_pretrained("lllyasviel/control_v11p_sd15_inpaint", dtype=torch.float16, variant="fp16")

# pass ControlNet to the pipeline
pipeline = StableDiffusionControlNetInpaintPipeline.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", controlnet=controlnet, dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

# prepare control image
def make_inpaint_condition(init_image, mask_image):
    init_image = np.array(init_image.convert("RGB")).astype(np.float32) / 255.0
    mask_image = np.array(mask_image.convert("L")).astype(np.float32) / 255.0

    assert init_image.shape[0:1] == mask_image.shape[0:1], "image and image_mask must have the same image size"
    init_image[mask_image > 0.5] = -1.0  # set as masked pixel
    init_image = np.expand_dims(init_image, 0).transpose(0, 3, 1, 2)
    init_image = torch.from_numpy(init_image)
    return init_image

control_image = make_inpaint_condition(init_image, mask_image)

次に、ベース画像、マスク画像、コントロール画像から画像を生成します。生成された画像では、ベース画像の特徴が強く保持されていることがわかります。

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, control_image=control_image).images[0]
make_image_grid([init_image, mask_image, PIL.Image.fromarray(np.uint8(control_image[0][0])).convert('RGB'), image], rows=2, cols=2)

さらに一歩進めて、スタイルを適用するために、image-to-image パイプラインとチェーンさせることもできます。

from diffusers import AutoPipelineForImage2Image

pipeline = AutoPipelineForImage2Image.from_pretrained(
    "nitrosocke/elden-ring-diffusion", dtype=torch.float16,
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

prompt = "elden ring style castle" # include the token "elden ring style" in the prompt
negative_prompt = "bad architecture, deformed, disfigured, poor details"

image_elden_ring = pipeline(prompt, negative_prompt=negative_prompt, image=image).images[0]
make_image_grid([init_image, mask_image, image, image_elden_ring], rows=2, cols=2)
初期画像
ControlNet inpaint
image-to-image

最適化

リソースが限られている環境では、拡散モデルの実行が困難かつ低速になる場合がありますが、いくつかの最適化テクニックを活用すれば、必ずしもそうである必要はありません。有効化できる最適化の中でも、最も効果が高く(かつ最も簡単な)ものの一つが、メモリ効率の高いアテンションへの切り替えです。PyTorch 2.0 を使用している場合、scaled-dot product attention は自動的に有効化されるため、その他の操作は不要です。PyTorch 2.0 以外の環境では、xFormers によるメモリ効率の高いアテンションの実装をインストールして利用できます。どちらのオプションも、メモリ使用量を削減し、推論を高速化します。

メモリをさらに節約するために、モデルをCPUにオフロードすることもできます。

+ pipeline.enable_xformers_memory_efficient_attention()
+ pipeline.enable_model_cpu_offload()

推論コードをさらに高速化するには、torch_compileを使用してください。パイプラインの中で最も計算負荷の高いコンポーネント、通常はUNetをtorch.compileでラップする必要があります。

pipeline.unet = torch.compile(pipeline.unet, mode="reduce-overhead", fullgraph=True)

メモリ使用量の削減および推論の高速化のガイドで詳細を確認してください。

Update on GitHub