はじめに
Inpaintは画像の一部修正をすることです。Inpaint専用モデルもありますが、今回は通常のText2Imageモデルを使用してInpaintを行います。「yabalMixTrue25D_v5」というモデルを使用しました。使い方が2通りあるので、両方を実行して比較してみました。用意した画像
こちらの画像を使用しました。この画像の作り方はこちらを見てください。
今回やること
スカートをデニムに変えてみます。用意したマスク画像
画像のどの部分を変更するかを指定するための画像です。こちらの画像を用意しました。女性の下半身の部分を白く塗りつぶした画像です。
こちらのスクリプトで作成しました。
結果
「StableDiffusionInpaintPipeline」を使う方法と「MaskedStableDiffusionImg2ImgPipeline」を使う方法の2通りで実行しました。StableDiffusionInpaintPipeline
左から「strength」を0.7 → 0.75 → 0.8 → 0.85と変化させています。マスクされていない部分を変更しないようにVaeImageProcessor.apply_overlay methodというのを使用しています。
「strength」の値が小さいと元の白いスカートが残ってしまっています。
MaskedStableDiffusionImg2ImgPipeline
左から「strength」を0.7 → 0.75 → 0.8 → 0.85と変化させています。ネガティブプロンプトに「bag」と書いておきましたがカバンが描写されてしまいました。
ベストショット
「StableDiffusionInpaintPipeline」を使って、「strength」を0.8に設定した時の結果を今回のベストショットとしました。使用したPythonスクリプト
StableDiffusionInpaintPipeline
from diffusers import AutoPipelineForInpainting, EulerAncestralDiscreteScheduler import torch from diffusers.utils import load_image pipeline = AutoPipelineForInpainting.from_pretrained( "model/yabalMixTrue25D_v5", safety_checker=None ) pipeline.scheduler = EulerAncestralDiscreteScheduler.from_config(pipeline.scheduler.config) pipeline.to("cuda") init_image = load_image("girl.png").resize((512, 768)) mask_image = load_image("girl_mask.png").resize((512, 768)) blurred_mask = pipeline.image_processor.blur(mask_image, blur_factor=8) strength_list = [0.7, 0.75, 0.8, 0.85] for strength in strength_list: generator = torch.manual_seed(2024) images = pipeline( prompt="masterpiece, absurdres, best quality, blue denim, full body, outdoors, day, countryside, hand on hip", image = init_image, mask_image = blurred_mask, negative_prompt="bag, porch, monochrome, lowres, bad anatomy, worst quality, low quality", num_images_per_prompt=1, num_inference_steps=50, generator=generator, strength=strength, cfg_scale=9.0, width=512, height=768 ).images unmasked_unchanged_image = pipeline.image_processor.apply_overlay( blurred_mask, init_image, images[0] ) unmasked_unchanged_image.save(f"inpaint_normal_{strength}.png")
MaskedStableDiffusionImg2ImgPipeline
from diffusers import DiffusionPipeline, EulerAncestralDiscreteScheduler import torch from diffusers.utils import load_image pipeline = DiffusionPipeline.from_pretrained( "model/yabalMixTrue25D_v5", safety_checker=None, custom_pipeline="masked_stable_diffusion_img2img" ) pipeline.scheduler = EulerAncestralDiscreteScheduler.from_config(pipeline.scheduler.config) pipeline.to("cuda") init_image = load_image("girl.png").resize((512, 768)) mask_image = load_image("girl_mask.png").resize((512, 768)) blurred_mask = pipeline.image_processor.blur(mask_image, blur_factor=8) strength_list = [0.7, 0.75, 0.8, 0.85] for strength in strength_list: generator = torch.manual_seed(2024) images = pipeline( prompt="masterpiece, absurdres, best quality, blue denim, full body, outdoors, day, countryside, hand on hip", image = init_image, mask = blurred_mask, negative_prompt="bag, porch, monochrome, lowres, bad anatomy, worst quality, low quality", num_images_per_prompt=1, num_inference_steps=50, strength=strength, generator=generator ).images unmasked_unchanged_image = pipeline.image_processor.apply_overlay( blurred_mask, init_image, images[0] ) unmasked_unchanged_image.save(f"inpaint_masked_{strength}.png")