ジャコ Lab

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

ドキュメント版 Inpainting に沿って試してみる

zako-lab929.hatenablog.com

前回の記事では リリースノート v0.6.0 に沿って Inpainting を進めました。
このとき使用したモデルは runwayml/stable-diffusion-inpainting ですが、
ドキュメント版 には他のモデルも載っているのでやってみようと思います。

早速試してみる

huggingface.co

そういえば、diffusers で使えるものは Stable Diffusion 系統なのだと思ってましたが、きっと Kandinsky は Stable Diffusion とは別物ですよね?
両方扱える diffusers が凄いってことでいいのかしら...??

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

# 投入画像とマスク画像の用意
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")

# パイプラインの用意
pipe = AutoPipelineForInpainting.from_pretrained(
    "kandinsky-community/kandinsky-2-2-decoder-inpaint",
    torch_dtype=torch.float16
).to("cuda")
pipe.enable_model_cpu_offload()

# パイプラインを実行
prompt = "a black cat with glowing eyes, cute, adorable, disney, pixar, highly detailed, 8k"
negative_prompt = "bad anatomy, deformed, ugly, disfigured"
image = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    image=init_image,
    mask_image=mask_image,
    generator=torch.Generator().manual_seed(67280421310721)
).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)

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

こういう明らかに有り得なそうな合成写真っぽいのいいですねぇ
楽しくなってきます

Seed は載っていなかったのでドキュメントとは異なる画像が生成されていますが、
同じような見た目の絵が生成されてます。
※Seed 値は適当です。

ドキュメントにマスク画像を作るツールまで置いてありました。
ウェブ上だと細かくはできないので、フォトショやクリスタなどで自分でマスク画像作ったほうが余計な範囲をマスクしなくて良さそうです。

マスクブラー

ブラーを付ける機能も最初からついているみたいです

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

pipeline = AutoPipelineForInpainting.from_pretrained("runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16).to('cuda')

mask = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/seashore_mask.png")
blurred_mask_0 = pipeline.mask_processor.blur(mask, blur_factor=0)
blurred_mask_33 = pipeline.mask_processor.blur(mask, blur_factor=33)
blurred_mask_100 = pipeline.mask_processor.blur(mask, blur_factor=100)
make_image_grid([blurred_mask_0 , blurred_mask_33 , blurred_mask_100 ], rows=1, cols=3)

(左) blur_factor=0 | (中) blur_factor=0 | (右) blur_factor=100

ブラーは数値が大きくなるほど強くなるようです。

さっきの猫ちゃんは、ブラーを付けるとどう変わるのでしょうか?

ブラー x 猫

AttributeError: 'KandinskyV22InpaintCombinedPipeline' object has no attribute 'mask_processor'

どうやら、 mask_processor() はモデルよって (使用するパイプラインによって) 生えてたり生えてなかったりするっぽいです

気を取り直して...

Inpaint をする際に Stable Diffusion Inpainting, Stable Diffusion XL (SDXL) Inpainting, Kandinsky 2.2 Inpainting これらの3つはよく使われるモデルとのこと

既に2種類は試し済みで Stable Diffusion Inpainting は、前回ベンチに座ってた犬を猫に修正するときに使いました。Kandinsky 2.2 Inpainting は、上記で山を猫に修正しました。

となると、やるべきことは インプット画像マスク画像プロンプト、を固定し、同じシードでモデルだけ変えて試してみることですね。ドキュメントでもしっかりとやってくれてます。

pipeline = AutoPipelineForInpainting.from_pretrained(
    "runwayml/stable-diffusion-inpainting",
    torch_dtype=torch.float16,
    variant="fp16"
).to("cuda")
pipeline = AutoPipelineForInpainting.from_pretrained(
    "diffusers/stable-diffusion-xl-1.0-inpainting-0.1",
    torch_dtype=torch.float16,
    variant="fp16"
).to("cuda")
pipeline = AutoPipelineForInpainting.from_pretrained(
    "kandinsky-community/kandinsky-2-2-decoder-inpaint",
    torch_dtype=torch.float16
).to("cuda")

このパイプラインを作るところだけを差分に、他の インプット画像マスク画像プロンプト、を固定し、同じシードで試したものが以下の出力結果のようです。

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]
image

(左) SD Inpainting | (中) SDXL Inpainting | (右) Kandinsky 2.2 Inpainting

Inpainting 用モデル専用なのか?

Non-inpaint specific checkpoints
So far, this guide has used inpaint specific checkpoints such as runwayml/stable-diffusion-inpainting. But you can also use regular checkpoints like runwayml/stable-diffusion-v1-5.

という記載がありました。
ずっと気になってたことが、そのまま回答されてます。

どうやら、通常のモデルでも使用可能とのことです。そうなると今度は ControlNet の Inpaint との違い が気になってきますね。概念的には同じだけどアルゴリズムが異なるとかなのかなぁ~?

とりあえず、上記の SD Inpainting, SDXL Inpainting, Kandinsky 2.2 Inpainting の流れで stable-diffusion-v1-5 を使用してみます。

pipeline = AutoPipelineForInpainting.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype=torch.float16, 
    variant="fp16"
).to("cuda")

↑これ

(左) SD Inpainting | (右) SD 1.5

ちゃんとできましたね。

派生モデルもいける?

pipeline = AutoPipelineForInpainting.from_pretrained(
    "dallinmackay/Van-Gogh-diffusion",
    torch_dtype=torch.float16, 
).to("cuda")

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"
prompt = "lvngvncnt, cute cat"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
image

(左) SD 1.5 | (右) Van-Gogh-diffusion

行けてそう感ありますな

パラメータについて

Image-to-Image のときにもあったけど Strength などで調整をするっぽいです。ドキュメント上では以下のパラメータが紹介されてましたが、Image-to-Image とほぼ同じなので、基本パラメータなのでしょう。

パラメータ名 説明
strength 生成された画像がベースイメージにどの程度似ているかに影響する
guide_scale 生成された画像がプロンプトにどの程度影響しているか
padding_mask_crop ユーザー指定のパディングで、イメージとマスク両方がトリミングされてアップスケールされる?らしい

まとめ

zako-lab929.hatenablog.com

前回の記事と比べて、たくさんのパターンが紹介されていて、より理解が深まる感じでした!