はじめに
今回は前回記事の続きとして,画像の背景部分をStableDiffusionを用いて変更してみたいと思います,
StableDiffusionのモデルの中身に関してはこちらでわかりやすく解説してくれていますので,参考にしてみてください.
まずは,前回のおさらいですが,前準備を進めます.
- Google Colaboratoryのランタイムの設定をGPUに変更する.
- 入力となる画像をアップロードする.
- StableDiffusionを動かすのに必要なライブラリをインストールする.
!pip install diffusers transformers accelerate scipy safetensors
上記で準備が完了したので,早速背景の変更に取り組んでいきます.
Promptによる背景の変更
まずは,前回実施したimg2imgのpromptをいじることで元画像の背景を修正していきたいと思います.
入力画像は背景が雪景色でその中で丸くなっている狐の画像です.
これの背景を緑豊かな森の中というような状況にしたいと思います.
せっかくなので,promptもchatGPTに生成してもらいましょう.
chatGPTが生成したpromptの一部を用いて画像変換を試してみましょう.
下記のような形式で複数のpromptを試してみました.
import torch
from PIL import Image
from torch import autocast
from diffusers import StableDiffusionImg2ImgPipeline
model_id = "stabilityai/stable-diffusion-2-1"
# StableDiffusionImg2Imgパイプラインの準備
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(
model_id,
revision="fp16",
torch_dtype=torch.float16,
).to("cuda")
#画像の生成
init_image = Image.open("input.png").convert("RGB")
init_image = init_image.resize((768, 512))
prompt = "Generate an image where the snowy mountain background is replaced with a picturesque forest scene, while keeping the fox unchanged."
with autocast("cuda"):
images = pipe(
prompt=prompt, # プロンプト
image=init_image, # 入力画像
strength=0.45, # 入力と出力の相違度
guidance_scale=10, # プロンプトと出力の類似度
num_inference_steps=100, # 画像生成に費やすステップ数
).images
images[0].save("output.png")
上記を実行した結果です.
strengthやguidance_scaleはいい感じになるまで複数の値を試しながら出力画像を生成しています.
プロンプトもchatGPTから受け取ったものを複数試しています.
画像をよくみてみると背景部分の木が若干緑掛かっているように見えます.
しかし,元々の入力画像の雪景色の背景から新緑感ある背景にしたいという意図からは逸れています.
プロンプトやモデル生成時のパラメータ調整だけでは大きな画像の変更は難しそうです.
パラメータ次第で緑豊かな背景にすることはできますが,元の画像から大きく乖離してしまい,狐の画像が改変されてしまいます.
これを改善するために,StableDiffusionが用意している別のモデルを使ってみたいと思います.
Stable Diffusion Inpainting
次に,画像修復モデルを試しみたいと思います.
Inpaintingモデルではマスク画像とプロンプトを用いて画像の特定の部分を変更・修正することができます.
Hugging Faceのサイトに使い方に関しては記載されているので詳細を確認したい方はこちらをご参照ください.
使い方に倣い,まずは,マスク画像を作成します.
今回は背景部分を変更したいので,背景を白塗りした画像を用意します.
下記,入力画像とマスク画像になります.
背景を緑にするプロンプトはchatGPTに再度生成してもらいました.
では,これらを元に背景の画像を変更していきたいと思います.
背景を変更するために用いたinpaintモデル利用コードは下記になります.
import torch
from PIL import Image
from torch import autocast
from diffusers import StableDiffusionInpaintPipeline
# StableDiffusionI Inpaint パイプラインの準備
pipe = StableDiffusionInpaintPipeline.from_pretrained(
"runwayml/stable-diffusion-inpainting",
torch_dtype=torch.float16,
)
pipe = pipe.to("cuda")
#画像生成
init_image = Image.open("input.png").convert("RGB")
mask_image = Image.open("input_mask.png").convert("RGB")
#入力画像を512x512のサイズに変更するために,画像の一部をトリミング
init_image = init_image.crop((int(init_image.width/2) - 256, int(init_image.height/2) - 256, int(init_image.width/2) + 256, int(init_image.height/2) + 256))
mask_image = mask_image.crop((int(mask_image.width/2) - 256, int(mask_image.height/2) - 256, int(mask_image.width/2) + 256, int(mask_image.height/2) + 256))
prompt = "Transform the image into an artwork set in a lush and vibrant forest environment."
with autocast("cuda"):
images = pipe(
prompt=prompt, # プロンプト
image=init_image, # 入力画像
mask_image = mask_image, #マスク画像
num_inference_steps=300, # 画像生成に費やすステップ数
).images
images[0].save("output.png")
実行結果が下記になります.
雑にマスク画像を作ってしまったので,若干違和感はありますが,しっかりと背景を森の中のような形にしてくれました.
マスク画像で細かく設定すれば,狐の周りの白い部分も抑えられるようになるはずです.
また,狐が大きく見えてしまう形になっていますが,こちらも画像のリサイズやトリミングをうまくすることで理想の大きさに変更することができるかと思います.
対象のオブジェクト部分だけ切り抜くなどは別の画像処理技術と組み合わせれば実現可能なので,よりリアリティのある画像が生成できそうです.
終わりに
今回は,StableDiffusionを使って画像の背景変更を試みました.
想像以上にうまく対象部位だけを画像修正してくれるので,画像生成の幅が広がりそうです.
次回は今回までの内容を元にもう少しStable Diffusionで遊んでみたいと思います.
コメント