【Stable Diffusion】ローカル環境でInpaintingを動かす

【Stable Diffusion】ローカル環境でInpaintingを動かす 機械学習

「画像の一部を他の画像に置き換えたい」
「Stable DiffusionのInpaintingを試してみたい」

このような場合には、この記事の内容が参考になります。
この記事では、ローカル環境でStable DiffusionのInpaintingを動かす方法を解説しています。

本記事の内容

  • Inpaintingとは?
  • Inpaintingのシステム要件
  • Inpaintingの動作確認

それでは、上記に沿って解説していきます。

Inpaintingとは?

Inpaintingとは、日本語では「修復」を意味します。
画像を対象にする場合は、画像の特定部分を再描画することになります。

「百聞は一見にしかず」です。
次の画像は、Inpaintingによって作成した画像となります。

Stable Diffusionにおいて、Inpaintingで画像を作成するには以下を用意します。

  • 元画像
  • マスク画像

示した事例では、それぞれ次の画像を利用しています。

元画像(base.png)

マスク画像(mask.png)

基本的には、元画像とマスク画像はセットになります。
元画像で変更したい部分をもとにして、マスク画像を作成します。
このとき、画像サイズは同じにしておく方がよいでしょう。

追記 2022年10月3日
マスク画像とか面倒くさいと言う方は、次の記事をご覧ください。
面倒なことをする必要がなく、Inpaintingを実行することができます。

事例では、冷蔵庫を他に置き換えたいということになります。
背景などはそのままにして、冷蔵庫の部分だけを差し替えるということです。

そして、その際に差し替えたいモノをプロンプトに指定します。
事例では、以下のテキストを用いてInpaintingを実行しています。

  • washing machine
  • Eddie Murphy
  • mailbox
  • aquarium

それぞれ、上記のテキストを上手く表現して置き換えていると言えます。
もちろん、パラメータを調整して試行錯誤はしていますけどね。

洗濯機、ポスト、水槽に関しては、まだ理解できます。
しかし、エディ・マーフィに関しては驚きました。

実行前は、エディ・マーフィが立っていることをイメージしていました。
しかし、出来上がった画像ではアート作品として表現されているのです。

おそらく、マスク画像が長方形であることが影響していると思われます。
人型のマスク画像であれば、人物としてのエディ・マーフィが表現されたかもしれません。
ただ、その場合はそのような形のマスク画像を用意する必要があります。

以上、Inpaintingについて説明しました。
次は、Inpaintingのシステム要件を説明します。

Inpaintingのシステム要件

Stable Diffusionには、様々な環境・形式で動くようです。
この記事では、ローカル環境にインストールした状況を想定しています。
具体的には、次の記事通りにインストールした場合です。

ただ、Diffusersのバージョンには注意してください。
Diffusers 0.3.0以降であることを前提に説明を進めます。
(※ Diffusers 0.2.4では未検証)

あと、GPU利用も前提とします。
おそらく、CPUだけではInpaintingがまともに処理されないかもしれません。

なお、GPUメモリ8GBでInpaintingが動くことは確認済みです。

以上、Inpaintingのシステム要件を説明しました。
次は、Inpaintingの動作確認を説明します。

Inpaintingの動作確認

Inpaintingの動作確認を行います。
元画像、マスク画像はすでに紹介したモノを利用します。

呪文となるプロンプトには、「自動販売機」を用います。
冷蔵庫と形が似ているので、スンナリとハマってくれそうです。

動作確認で用いるのは、次のコードになります。

from PIL import Image 
import torch 
from torch import autocast 
from diffusers import ( 
    DDIMScheduler, 
    StableDiffusionInpaintPipeline 
)

MODEL_ID = "CompVis/stable-diffusion-v1-4" 
DEVICE = "cuda" 
YOUR_TOKEN = "コピーしたアクセストークン" 
BASE_IMG = "base.png" 
PROMPT = "vending machine" 
SEED = 10000 
STEP = 100 
SCALE = 7.5 
STRENGTH = 0.8 
WIDTH = 512 
HEIGHT = 512

# mask 
MASK_IMG = "mask.png" 
mask_img = Image.open(MASK_IMG) 
mask_img = mask_img.resize((WIDTH, HEIGHT))

scheduler = DDIMScheduler(beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear", clip_sample=False, 
                          set_alpha_to_one=False) 
pipe = StableDiffusionInpaintPipeline.from_pretrained( 
    MODEL_ID, 
    scheduler=scheduler, 
    revision="fp16", 
    torch_dtype=torch.float16, 
    use_auth_token=YOUR_TOKEN 
).to(DEVICE)

init_img = Image.open(BASE_IMG) 
init_img = init_img.resize((WIDTH, HEIGHT))

generator = torch.Generator(device=DEVICE).manual_seed(SEED) 
with autocast(DEVICE): 
    image = pipe(prompt=PROMPT, init_image=init_img, mask_image=mask_img, strength=STRENGTH, guidance_scale=SCALE, 
                 generator=generator, num_inference_steps=STEP)["sample"][0] 
    image.save(str(SEED) + ".png")

プロンプトやパラメータなどは、定数で指定しています。
また、seedは固定です。

seed固定については、次の記事で説明しています。

システム要件が整っていれば、問題なく動くはずです。
コードを実行した結果、次のような画像が作成されています。

10000.png

やはり、冷蔵庫と自動販売機は似ていますね。
違和感なく、画像に収まってくれました。

以上、Inpaintingの動作確認を説明しました。

タイトルとURLをコピーしました