ジャコ Lab

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

Inpaint を使ってみる

さて、この記事では diffusers v0.6.0 を参考に Inpainting を使ってみます。 公式ドキュメント にも Inpainting のページがありますが、今回は v0.6.0 当時のリリースノートを読みながら進めます。更に Inpainting は ControlNet にもあるようですが、今回は v0.6.0 当時のリリースノートを読みながら進めます

前回は v0.7.0 の Long Prompt Weighting Stable Diffusion を使い、それよりも前は LoRA を使って遊び、そして v0.6.0 に戻ってくるという時系列的にはグチャグチャです。
何もわからないところから始めているのである程度よく使われているネットに転がっているキーワードから調べている感じですね。少しずつ理解が深まっているのか、ちゃんと公式ドキュメントを読んだり、リリースノートを見てみたりするようになりました。

Inpainting とは?

Inpainting は 修正したい画像修正したい箇所(マスク画像) を用意して、Image-to-Image の要領で実行します

StableDiffusionInpaintPipeline を使ってみる

ドキュメント では AutoPipelineForInpainting を使用していますが、まずは v0.6.0 の StableDiffusionInpaintPipeline を使ってみます。きっと AutoPipeline を使っても内部では StableDiffusionInpaintPipeline を使っているのではないでしょうか?後で調べてみようと思います。

from diffusers.utils import load_image

init_image_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo.png"
mask_image_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo_mask.png"
init_image = load_image(init_image_url )
mask_image = load_image(mask_image_url )

print(init_image.size)
print(mask_image.size)

diffusers v0.6.0 を見ると、自分で download_image のメソッドを用意していますが、今は utilsload_image があるのでそれを使わせてもらいましょう。更に resize((512, 512)) を実行していますが、確認してみたところ最初から 512x512 でした。resize しなくていいか!

あとは Pipeline を用意して実行です。

import torch
from diffusers import StableDiffusionInpaintPipeline

pipe = StableDiffusionInpaintPipeline.from_pretrained(
    "runwayml/stable-diffusion-inpainting",
    revision="fp16",
    torch_dtype=torch.float16,
).to("cuda")

prompt = "Face of a yellow cat, high resolution, sitting on a park bench"
image = pipe(
    prompt=prompt,
    image=init_image,
    mask_image=mask_image,
    generator=torch.Generator(device="cuda").manual_seed(67280421310721),
).images[0]

(左) 投入画像 | (中) マスク画像 | (右) 生成画像

なかなか良き感じですね!

AutoPipeline 版を使ってみる

import torch
from diffusers import AutoPipelineForInpainting

pipe = AutoPipelineForInpainting.from_pretrained(
    "runwayml/stable-diffusion-inpainting",
    revision="fp16",
    torch_dtype=torch.float16,
).to("cuda")

prompt = "Face of a yellow cat, high resolution, sitting on a park bench"
image = pipe(
    prompt=prompt,
    image=init_image,
    mask_image=mask_image,
    generator=torch.Generator(device="cuda").manual_seed(67280421310721),
).images[0]

コードとしては、 StableDiffusionInpaintPipelineAutoPipelineForInpainting に変えただけです。
Seed を固定しているので、全く同じものが生成されました。

AutoPipelineForInpainting は何をしているのか?

AutoPipelineForInpaintingfrom_pretrained() の内部では、
inpainting_cls.from_pretrained() を使っていそうです。inpainting_cls インスタンス_get_task_class() から得ていますが、 こちらのマッピング定数 から選んでいるように見えますので、きっと同じものが使われているのでしょう!

まとめ

Inpainting も簡単に使えました!