画像生成 AI 入門: Python による拡散モデルの理論と実践#
Section 07. Play with Diffusion Model#
Stable Diffusion を中心とした拡散モデルを用いて、最先端の画像生成技術を実際に動かして実践していきます。
Lecture 19. Stable Diffusion#
本実習ではテキストからの画像生成 (Text2Image) モデルである Stable Diffusion を更に深掘りします。特に本実習では以下の観点で Stable Diffusion の応用可能性について見ていきます:
Seed Search: 画像生成における乱数の種の探索
Image2Image: 画像 (と文) から画像を生成
Image Inpainting: 画像上のマスクされた領域を再構成
Depth2Image: 画像の深度情報を元に被写体の形状を損なうことなく画像を生成
セットアップ#
GPU が使用できるか確認#
本 Colab ノートブックを実行するために GPU ランタイムを使用していることを確認します。CPU ランタイムと比べて画像生成がより早くなります。以下の nvidia-smi
コマンドが失敗する場合は再度講義資料の GPU 使用設定
のスライド説明や Google Colab の FAQ 等を参考にランタイムタイプが正しく変更されているか確認してください。
!nvidia-smi
Sat Jul 1 08:03:55 2023
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.85.12 Driver Version: 525.85.12 CUDA Version: 12.0 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 Tesla T4 Off | 00000000:00:04.0 Off | 0 |
| N/A 43C P8 9W / 70W | 0MiB / 15360MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
利用する Python ライブラリをインストール#
diffusers ライブラリをインストールすることで拡散モデルを簡単に使用できるようにします。diffusers ライブラリを動かす上で必要となるライブラリも追加でインストールします:
transformers: 拡散モデルにおいて核となる Transformer モデルが定義されているライブラリ
accelerate: transformers と連携してより高速な画像生成をサポートするライブラリ
!pip install diffusers==0.16.1
!pip install transformers accelerate
Collecting diffusers==0.16.1
Downloading diffusers-0.16.1-py3-none-any.whl (934 kB)
?25l ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/934.9 kB ? eta -:--:--
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 934.9/934.9 kB 46.6 MB/s eta 0:00:00
?25hRequirement already satisfied: Pillow in /usr/local/lib/python3.10/dist-packages (from diffusers==0.16.1) (8.4.0)
Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from diffusers==0.16.1) (3.12.2)
Collecting huggingface-hub>=0.13.2 (from diffusers==0.16.1)
Downloading huggingface_hub-0.15.1-py3-none-any.whl (236 kB)
?25l ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/236.8 kB ? eta -:--:--
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 236.8/236.8 kB 19.1 MB/s eta 0:00:00
?25hCollecting importlib-metadata (from diffusers==0.16.1)
Downloading importlib_metadata-6.7.0-py3-none-any.whl (22 kB)
Requirement already satisfied: numpy in /usr/local/lib/python3.10/dist-packages (from diffusers==0.16.1) (1.22.4)
Requirement already satisfied: regex!=2019.12.17 in /usr/local/lib/python3.10/dist-packages (from diffusers==0.16.1) (2022.10.31)
Requirement already satisfied: requests in /usr/local/lib/python3.10/dist-packages (from diffusers==0.16.1) (2.27.1)
Requirement already satisfied: fsspec in /usr/local/lib/python3.10/dist-packages (from huggingface-hub>=0.13.2->diffusers==0.16.1) (2023.6.0)
Requirement already satisfied: tqdm>=4.42.1 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub>=0.13.2->diffusers==0.16.1) (4.65.0)
Requirement already satisfied: pyyaml>=5.1 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub>=0.13.2->diffusers==0.16.1) (6.0)
Requirement already satisfied: typing-extensions>=3.7.4.3 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub>=0.13.2->diffusers==0.16.1) (4.6.3)
Requirement already satisfied: packaging>=20.9 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub>=0.13.2->diffusers==0.16.1) (23.1)
Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.10/dist-packages (from importlib-metadata->diffusers==0.16.1) (3.15.0)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests->diffusers==0.16.1) (1.26.16)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests->diffusers==0.16.1) (2023.5.7)
Requirement already satisfied: charset-normalizer~=2.0.0 in /usr/local/lib/python3.10/dist-packages (from requests->diffusers==0.16.1) (2.0.12)
Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests->diffusers==0.16.1) (3.4)
Installing collected packages: importlib-metadata, huggingface-hub, diffusers
Successfully installed diffusers-0.16.1 huggingface-hub-0.15.1 importlib-metadata-6.7.0
Collecting transformers
Downloading transformers-4.30.2-py3-none-any.whl (7.2 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 7.2/7.2 MB 87.7 MB/s eta 0:00:00
?25hCollecting accelerate
Downloading accelerate-0.20.3-py3-none-any.whl (227 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 227.6/227.6 kB 12.4 MB/s eta 0:00:00
?25hRequirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from transformers) (3.12.2)
Requirement already satisfied: huggingface-hub<1.0,>=0.14.1 in /usr/local/lib/python3.10/dist-packages (from transformers) (0.15.1)
Requirement already satisfied: numpy>=1.17 in /usr/local/lib/python3.10/dist-packages (from transformers) (1.22.4)
Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from transformers) (23.1)
Requirement already satisfied: pyyaml>=5.1 in /usr/local/lib/python3.10/dist-packages (from transformers) (6.0)
Requirement already satisfied: regex!=2019.12.17 in /usr/local/lib/python3.10/dist-packages (from transformers) (2022.10.31)
Requirement already satisfied: requests in /usr/local/lib/python3.10/dist-packages (from transformers) (2.27.1)
Collecting tokenizers!=0.11.3,<0.14,>=0.11.1 (from transformers)
Downloading tokenizers-0.13.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.8 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 7.8/7.8 MB 113.5 MB/s eta 0:00:00
?25hCollecting safetensors>=0.3.1 (from transformers)
Downloading safetensors-0.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.3/1.3 MB 53.9 MB/s eta 0:00:00
?25hRequirement already satisfied: tqdm>=4.27 in /usr/local/lib/python3.10/dist-packages (from transformers) (4.65.0)
Requirement already satisfied: psutil in /usr/local/lib/python3.10/dist-packages (from accelerate) (5.9.5)
Requirement already satisfied: torch>=1.6.0 in /usr/local/lib/python3.10/dist-packages (from accelerate) (2.0.1+cu118)
Requirement already satisfied: fsspec in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.14.1->transformers) (2023.6.0)
Requirement already satisfied: typing-extensions>=3.7.4.3 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.14.1->transformers) (4.6.3)
Requirement already satisfied: sympy in /usr/local/lib/python3.10/dist-packages (from torch>=1.6.0->accelerate) (1.11.1)
Requirement already satisfied: networkx in /usr/local/lib/python3.10/dist-packages (from torch>=1.6.0->accelerate) (3.1)
Requirement already satisfied: jinja2 in /usr/local/lib/python3.10/dist-packages (from torch>=1.6.0->accelerate) (3.1.2)
Requirement already satisfied: triton==2.0.0 in /usr/local/lib/python3.10/dist-packages (from torch>=1.6.0->accelerate) (2.0.0)
Requirement already satisfied: cmake in /usr/local/lib/python3.10/dist-packages (from triton==2.0.0->torch>=1.6.0->accelerate) (3.25.2)
Requirement already satisfied: lit in /usr/local/lib/python3.10/dist-packages (from triton==2.0.0->torch>=1.6.0->accelerate) (16.0.6)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests->transformers) (1.26.16)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests->transformers) (2023.5.7)
Requirement already satisfied: charset-normalizer~=2.0.0 in /usr/local/lib/python3.10/dist-packages (from requests->transformers) (2.0.12)
Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests->transformers) (3.4)
Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from jinja2->torch>=1.6.0->accelerate) (2.1.3)
Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy->torch>=1.6.0->accelerate) (1.3.0)
Installing collected packages: tokenizers, safetensors, transformers, accelerate
Successfully installed accelerate-0.20.3 safetensors-0.3.1 tokenizers-0.13.3 transformers-4.30.2
Stable Diffusion を用いた画像生成における乱数の種の探索#
本セクションでは、Stable Diffusion Pipeline
を使用して、繰り返し使用可能な乱数の種 (seed) を使って生成された画像を元に、自身がイメージした画像を生成する方法を紹介します。
以下、Stable Diffusion with Repeatable Seeds を参考に動作を追っていきます。ここではまず初めに StableDiffusionPipeline
で runwayml/stable-diffusion-v1-5
を読み込みます。
import torch
from diffusers import StableDiffusionPipeline
model_id = "runwayml/stable-diffusion-v1-5"
dtype = torch.float16
pipe = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=dtype)
pipe = pipe.to("cuda")
`text_config_dict` is provided which will be used to initialize `CLIPTextConfig`. The value `text_config["id2label"]` will be overriden.
まずいくつかの画像を生成して、どの画像が好ましいかを確認します。複数生成した画像をグリッド上に表示する関数を以下のように定義します。この関数は 🤗 Hugging Face Stable Diffusion のブログ記事のものを利用しています。
from typing import List
from PIL import Image
from PIL.Image import Image as PilImage
def image_grid(imgs: List[PilImage], rows: int, cols: int) -> PilImage:
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
今回は一度に 4 つの画像を生成して、その結果を確認していきます。生成する画像の枚数は GPU の RAM の容量に応じて自由に変更してください。また、今回 512 x 512 サイズの画像を生成します。
num_images = 4 # 生成する画像の枚数
img_h = 512 # 生成する画像の高さ
img_w = 512 # 生成する画像の幅
あらかじめ用意した潜在変数を pipeline に渡すことで、生成される画像をコントロールしたり、再現可能にすることができます。再現可能な潜在変数を得るためには、乱数の seed を固定して生成したり、その結果を再利用する方法をとります。
diffusers の pipeline では、デフォルトで潜在変数の生成を pipeline の内部で行われます。以下のようにして、自前で潜在変数を生成して pipeline に渡すことで、意図した画像を生成できるようにします。
from diffusers.utils import randn_tensor
# 初期値となる乱数生成器を seed の固定込みで定義
generator = torch.Generator().manual_seed(19950815)
image_latents = []
seeds = []
for _ in range(num_images):
# 上記で定義した乱数生成器で乱数を得る
seed = generator.seed()
seeds.append(seed)
# 得られた乱数を元に乱数生成器の seed を固定
generator = generator.manual_seed(seed)
# 設定した乱数生成器を元に潜在変数を生成
image_latent = randn_tensor(
(1, pipe.unet.config.in_channels, img_h // 8, img_w // 8),
generator=generator,
device=pipe.device,
dtype=dtype,
)
image_latents.append(image_latent)
# List[torch.Tensor] ([latent1, latent2, ..., latent4]) 形式を
# concat することで torch.Tensor 形式に変換
latents = torch.cat(image_latents)
# 生成したい画像の数だけ潜在変数が得られていることを確認
latents.shape
torch.Size([4, 4, 64, 64])
以上で画像を生成する準備ができました。パイプライン pipe
に準備した潜在変数 latents
を渡します。
prompt = "Labrador in the style of Vermeer"
images = pipe([prompt] * num_images, guidance_scale=7.5, latents=latents).images
生成が完了しました。上記で定義した image_grid
関数を使って生成画像を並べて表示しましょう。
image_grid(images, rows=2, cols=2)
Output hidden; open in https://colab.research.google.com to view.
生成結果を眺めてみて、好みの画像を 1 つ選んで深掘りしてみましょう。画像生成時に使用した seed を再利用すれば、同じ結果を再現することができます。
seed = seeds[2]
seed
4413939642087467736
generator = generator.manual_seed(seed)
image_latent = randn_tensor(
(1, pipe.unet.config.in_channels, img_h // 8, img_w // 8),
generator=generator,
device=pipe.device,
dtype=dtype,
)
上記のコードは seed 値から再度 generator
の seed を固定して、潜在変数を生成していますが、単に latents
から以下のように習得することも考えられます:
image_latent = latents[1] # たとえば 2 番目の潜在変数を取得
seed を記録しておくだけで、いつでも好きなときに生成結果を再現できるようになります。これらの latents
と同じプロンプトで (1 枚の画像の) 生成を繰り返せば、以前と同じ画像が得られるはずです:
pipe(prompt, guidance_scale=7.5, latents=image_latent).images[0]
期待したとおりに同様の画像が生成されました。次に同じ潜在変数を保持したまま、プロンプトの内容を変えてみましょう。こうすることで画像の構図は似ているが内容やスタイルが異なる画像が生成できるはずです。
以下がその例です:
prompt = "Terrier in the style of Vermeer"
pipe(prompt, guidance_scale=7.5, latents=image_latent).images[0]
犬種をラブラドール (Labrador) からテリア (Terrier) に変えたところ、同様の構図で変化していることがわかります。
prompt = "Labrador in the style of Van Gogh"
pipe(prompt, guidance_scale=7.5, latents=image_latent).images[0]
次に画風をフェルメールからゴッホにしてみました。確かにゴッホ風の画像が生成されています。
prompt = "Clown in the style of Vermeer"
pipe(prompt, guidance_scale=7.5, latents=image_latent).images[0]
これまでは犬種でしたが、今度はピエロにしてみて画像を生成してみました。同様の構図やスタイルを引き継ぎつつ、画像が生成されているように見えます。
このようにして、乱数の seed やそれを元にした潜在変数を探索しつつプロンプトを調整していくことで、自身のイメージに合った画像を生成することが可能になります。
Image2Image#
本セクションでは、Stable Diffusion Image to Image Pipeline
を使用して、Stable Diffusion モデルによる(テキスト条件付きの)ベースとなる画像からの画像生成技術について説明します。
以下、Image2Image Pipeline for Stable Diffusion using 🧨 Diffusers を参考に動作を追っていきます。ここではまず初めに StableDiffusionImg2ImgPipeline
で runwayml/stable-diffusion-v1-5
を読み込みます。
from diffusers import StableDiffusionImg2ImgPipeline
model_id = "runwayml/stable-diffusion-v1-5"
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(model_id, torch_dtype=dtype)
pipe = pipe.to("cuda")
`text_config_dict` is provided which will be used to initialize `CLIPTextConfig`. The value `text_config["id2label"]` will be overriden.
生成結果を保持するためのリストを用意しておきます。
img2img_results: List[PilImage] = []
オンラインにある画像をダウンロードする関数を定義します。この関数を使って今回使用するセグメンテーションマップを stable diffusion 本家のレポジトリからダウンロードしてきます。
from diffusers.utils import load_image
init_image = load_image("https://raw.githubusercontent.com/CompVis/stable-diffusion/main/assets/stable-samples/img2img/sketch-mountains-input.jpg")
img2img_results.append(init_image)
init_image
では入力するプロンプトを用意して、pipeline を使って画像を生成してみます。
prompt = "A fantasy landscape, trending on artstation"
Image2Image タスクにおいて、pipeline の image
引数に上記でダウンロードした init_image
を渡すことで、その画像を元にした画像を生成可能です。Image2Image pipeline では strength
引数が存在します。このパラメータは 0.0
から 1.0
の間の値で、入力画像に加えるノイズの量を制御するものになっています。1.0
に近い値を設定すると、様々なバリエーションでの画像生成が可能になりますが、入力画像と意味的に一致しない画像を生成する場合もあります。以下は strength
を 0.75
に設定した結果です:
generator = torch.Generator().manual_seed(19950815)
image = pipe(
prompt=prompt, # 条件付け用のプロンプト
image=init_image, # 条件付け用の初期画像
strength=0.75, # strength を 0.75 に設定
guidance_scale=7.5,
generator=generator,
).images[0]
img2img_results.append(image)
image
以下は strength
を 0.5
に設定した結果です:
generator = torch.Generator().manual_seed(19950815)
image = pipe(
prompt=prompt,
image=init_image,
strength=0.5, # strength を 0.5 に設定
guidance_scale=7.5,
generator=generator,
).images[0]
img2img_results.append(image)
image
strength
を小さい値にすると、生成された画像はより元の画像に近くなることがわかりました。
では次に、デフォルトとは異なるノイズスケジューラを使用したときの生成結果を比較してみましょう。今回は LMS スケジューラ を使用してみます。 これまで使用してきた pipeline の設定 (pipe.scheduler.config
) を元に、LMSDiscreteScheduler
を定義し、pipeline にセットします。
from diffusers import LMSDiscreteScheduler
lms_scheduler = LMSDiscreteScheduler.from_config(pipe.scheduler.config)
pipe.scheduler = lms_scheduler
generator = torch.Generator().manual_seed(19950815)
image = pipe(
prompt=prompt,
image=init_image,
strength=0.75,
guidance_scale=7.5,
generator=generator,
).images[0]
img2img_results.append(image)
image
以下は上記で生成した結果を並べたものです。左から順位以下の並びになっています:
オリジナルのセグメンテーションマップ
デフォルトのノイズスケジューラを使用・strength は 0.75
デフォルトのノイズスケジューラを使用・strength は 0.5
LMS ノイズスケジューラを使用・strength は 0.75
image_grid(img2img_results, rows=1, cols=len(img2img_results))
Output hidden; open in https://colab.research.google.com to view.
diffusers では 複数のスケジューラが実装 されています。簡単にスケジューラを変更可能であるため、自身がイメージした画像が生成されるものを比較してみてもよいかもしれません。
Inpainting#
本セクションでは、Stable Diffusion Inpainting Pipeline
を使用して、Stable Diffusion モデルによる、画像上のマスクされた領域を再構成技術について説明します。
以下、In-painting pipeline for Stable Diffusion using 🧨 Diffusers を参考に動作を追っていきます。ここではまず初めに StableDiffusionInpaintPipeline
で runwayml/stable-diffusion-inpainting
を読み込みます。このモデルは上記で使用してきた runwayml/stable-diffusion-v1-5
とは異なり、inpainting 専用のモデルになっています。
from diffusers import StableDiffusionInpaintPipeline
model_id = "runwayml/stable-diffusion-inpainting"
pipe = StableDiffusionInpaintPipeline.from_pretrained(model_id, torch_dtype=dtype)
pipe = pipe.to("cuda")
safety_checker/model.safetensors not found
`text_config_dict` is provided which will be used to initialize `CLIPTextConfig`. The value `text_config["id2label"]` will be overriden.
Inpaint の対象となるサンプル画像を stable diffusion 本家のレポジトリからダウンロードしてきます。
image = load_image("https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo.png")
image = image.resize((512, 512))
image
次に inpaint の際に使用するマスク画像を、同じく stable diffusion 本家のレポジトリからダウンロードしてきます。
mask_image = load_image("https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo_mask.png")
mask_image = mask_image.resize((512, 512))
mask_image
ダンロードしてきた画像を元に inpainting モデルの動作を確認します。pipeline にオリジナルの画像とマスク画像を入れつつ、プロンプトでマスク箇所を描き直す条件を指定します。
prompt = "a mecha robot sitting on a bench"
num_images = 3
generator = torch.Generator().manual_seed(19950815)
images = pipe(
prompt=prompt, # 条件付け用のプロンプトテキスト
image=image, # inpainting 対象の画像
mask_image=mask_image, # inpainting 対象の画像を操作するためのマスク画像
guidance_scale=7.5,
generator=generator,
num_images_per_prompt=num_images,
).images
# 可視化用にオリジナルの画像を先頭に追加
images = [image, mask_image] + images
inpainting の結果を確認します。一番左がオリジナルの画像で、そのとなりがマスク画像、それ以外がマスク画像で指定した箇所をプロンプトの条件に従って描きなおしたものになります。
image_grid(images, rows=1, cols=num_images + 2)
Output hidden; open in https://colab.research.google.com to view.
オリジナルの画像の雰囲気を損なわず、マスクで指定した箇所がプロンプトに従ってオブジェクトが生成されております。ロボットの股下に注目すると、オリジナル画像では見えていなかった椅子の格子部分も補完されているのがすごいですね。
Depth2Image#
本セクションでは、 Stable Diffusion Depth to Image Pipeline
を使用して、Stable Diffusion モデルによる深度を考慮した画像生成技術について説明します。
以下、Text-guided depth-to-image generation を参考に動作を追っていきます。Depth2Image は Stable Diffusion v2 のメイン機能の 1 つなので、以下では stabilityai/stable-diffusion-v2-depth
というモデルを StableDiffusionDepth2ImgPipeline
で読み込みます。
更に今回の depth2image のデモでは Stable Diffusion v2 の特徴である negative prompt
(生成に含まれてほしくないような条件を指定するプロンプト) の機能も使用します。
from diffusers import StableDiffusionDepth2ImgPipeline
model_id = "stabilityai/stable-diffusion-2-depth"
pipe = StableDiffusionDepth2ImgPipeline.from_pretrained(model_id, torch_dtype=dtype)
pipe = pipe.to("cuda")
StableDiffusionDepth2ImgPipeline
では新しい画像の生成条件として、テキストプロンプトと初期画像を渡すことができます。さらに画像構造を保持するために depth_map
を渡すこともできます。 depth_map
を渡さない場合、pipeline は内部的に統合された深度推定モデルによって、自動的に深度を予測して画像生成に使用します。
まず今回サンプルとして利用する画像をダウンロードします:
init_image = load_image("http://images.cocodataset.org/val2017/000000039769.jpg")
init_image
プロンプト (prompt) と、画像中に描画してほしくないものを指定するプロンプト (negative prompt) を指定して画像を生成します。negative prompt は、特定の単語が画像の生成に影響しないように制御するものです:
prompt = "two tigers"
nevative_prompt = "bad, deformed, ugly, bad anotomy"
generator = torch.Generator().manual_seed(19950815)
pipe(
prompt=prompt,
image=init_image,
negative_prompt=nevative_prompt,
strength=0.75,
generator=generator,
).images[0]
上記のように物体の深度を正しく推定し、今回では 2 匹の猫を虎に描画し直すことができました。今回は深度マップを pipeline に渡していませんが、より正しい深度マップを渡すことでよりよい画像生成結果を得ることができます。