Diffusers documentation
Outpainting
Outpainting
Outpainting memperluas gambar melampaui batas aslinya, memungkinkan Anda menambahkan, mengganti, atau memodifikasi elemen visual dalam gambar sambil mempertahankan gambar aslinya. Seperti inpainting, Anda ingin mengisi area putih (dalam hal ini, area di luar gambar asli) dengan elemen visual baru sambil mempertahankan gambar asli (direpresentasikan oleh maskel piksel hitam). Ada beberapa cara untuk melakukan outpainting, seperti dengan ControlNet atau dengan Differential Diffusion.
Panduan ini akan menunjukkan cara melakukan outpainting dengan model inpainting, ControlNet, dan estimator ZoeDepth.
Sebelum memulai, pastikan Anda telah menginstal pustaka controlnet_aux agar dapat menggunakan estimator ZoeDepth.
!pip install -q controlnet_aux
Persiapan gambar
Mulai dengan memilih gambar untuk di-outpaint dan hapus latar belakangnya menggunakan Space seperti BRIA-RMBG-1.4.
Sebagai contoh, hapus latar belakang dari gambar sepasang sepatu ini.
Model Stable Diffusion XL (SDXL) bekerja paling baik dengan gambar berukuran 1024x1024, tetapi Anda dapat mengubah ukuran gambar ke ukuran apa pun selama perangkat keras Anda memiliki memori yang cukup untuk mendukungnya. Latar belakang transparan pada gambar juga harus diganti dengan latar belakang putih. Buatlah fungsi (seperti di bawah ini) yang memperbesar dan menempelkan gambar ke latar belakang putih.
import random
import requests
import torch
from controlnet_aux import ZoeDetector
from PIL import Image, ImageOps
from diffusers import (
AutoencoderKL,
ControlNetModel,
StableDiffusionXLControlNetPipeline,
StableDiffusionXLInpaintPipeline,
)
def scale_and_paste(original_image):
aspect_ratio = original_image.width / original_image.height
if original_image.width > original_image.height:
new_width = 1024
new_height = round(new_width / aspect_ratio)
else:
new_height = 1024
new_width = round(new_height * aspect_ratio)
resized_original = original_image.resize((new_width, new_height), Image.LANCZOS)
white_background = Image.new("RGBA", (1024, 1024), "white")
x = (1024 - new_width) // 2
y = (1024 - new_height) // 2
white_background.paste(resized_original, (x, y), resized_original)
return resized_original, white_background
original_image = Image.open(
requests.get(
"https://huggingface.co/datasets/stevhliu/testing-images/resolve/main/no-background-jordan.png",
stream=True,
).raw
).convert("RGBA")
resized_img, white_bg_image = scale_and_paste(original_image)Untuk menghindari penambahan detail tambahan yang tidak diinginkan, gunakan estimator ZoeDepth untuk memberikan panduan tambahan selama proses generasi dan untuk memastikan sepatu tetap konsisten dengan gambar asli.
zoe = ZoeDetector.from_pretrained("lllyasviel/Annotators")
image_zoe = zoe(white_bg_image, detect_resolution=512, image_resolution=1024)
image_zoe
Outpaint
Setelah gambar Anda siap, Anda dapat menghasilkan konten di area putih di sekitar sepatu dengan controlnet-inpaint-dreamer-sdxl, yaitu SDXL ControlNet yang dilatih untuk inpainting.
Muat ControlNet inpainting, model ZoeDepth, dan VAE, lalu teruskan semuanya ke StableDiffusionXLControlNetPipeline. Setelah itu, Anda dapat membuat fungsi generate_image opsional (untuk kenyamanan) guna melakukan outpainting pada gambar awal.
controlnets = [
ControlNetModel.from_pretrained(
"destitech/controlnet-inpaint-dreamer-sdxl", dtype=torch.float16, variant="fp16"
),
ControlNetModel.from_pretrained(
"diffusers/controlnet-zoe-depth-sdxl-1.0", dtype=torch.float16
),
]
vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", dtype=torch.float16).to("cuda") # or "mps", "xpu", "cpu"
pipeline = StableDiffusionXLControlNetPipeline.from_pretrained(
"SG161222/RealVisXL_V4.0", dtype=torch.float16, variant="fp16", controlnet=controlnets, vae=vae
).to("cuda")
def generate_image(prompt, negative_prompt, inpaint_image, zoe_image, seed: int = None):
if seed is None:
seed = random.randint(0, 2**32 - 1)
generator = torch.Generator(device="cpu").manual_seed(seed)
image = pipeline(
prompt,
negative_prompt=negative_prompt,
image=[inpaint_image, zoe_image],
guidance_scale=6.5,
num_inference_steps=25,
generator=generator,
controlnet_conditioning_scale=[0.5, 0.8],
control_guidance_end=[0.9, 0.6],
).images[0]
return image
prompt = "nike air jordans on a basketball court"
negative_prompt = ""
temp_image = generate_image(prompt, negative_prompt, white_bg_image, image_zoe, 908097)Tempelkan gambar asli di atas gambar hasil outpainting awal. Anda akan memperbaiki latar belakang hasil outpainting pada langkah selanjutnya.
x = (1024 - resized_img.width) // 2
y = (1024 - resized_img.height) // 2
temp_image.paste(resized_img, (x, y), resized_img)
temp_image
Sekarang adalah waktu yang tepat untuk membebaskan sebagian memori jika Anda kekurangan ruang!
pipeline=None torch.cuda.empty_cache()
Sekarang bahwa Anda memiliki gambar outpaint awal, muat StableDiffusionXLInpaintPipeline dengan model RealVisXL untuk menghasilkan gambar outpaint final dengan kualitas yang lebih baik.
pipeline = StableDiffusionXLInpaintPipeline.from_pretrained(
"OzzyGT/RealVisXL_V4.0_inpainting",
dtype=torch.float16,
variant="fp16",
vae=vae,
).to("cuda") # or "mps", "xpu", "cpu"Siapkan mask untuk gambar hasil outpainting akhir. Untuk menciptakan transisi yang lebih alami antara gambar asli dan latar belakang hasil outpainting, blur mask agar lebih menyatu.
mask = Image.new("L", temp_image.size)
mask.paste(resized_img.split()[3], (x, y))
mask = ImageOps.invert(mask)
final_mask = mask.point(lambda p: p > 128 and 255)
mask_blurred = pipeline.mask_processor.blur(final_mask, blur_factor=20)
mask_blurred
Buat prompt yang lebih baik dan teruskan ke fungsi generate_outpaint untuk menghasilkan gambar outpainting akhir. Sekali lagi, tempelkan gambar asli di atas latar belakang outpainting akhir.
def generate_outpaint(prompt, negative_prompt, image, mask, seed: int = None):
if seed is None:
seed = random.randint(0, 2**32 - 1)
generator = torch.Generator(device="cpu").manual_seed(seed)
image = pipeline(
prompt,
negative_prompt=negative_prompt,
image=image,
mask_image=mask,
guidance_scale=10.0,
strength=0.8,
num_inference_steps=30,
generator=generator,
).images[0]
return image
prompt = "high quality photo of nike air jordans on a basketball court, highly detailed"
negative_prompt = ""
final_image = generate_outpaint(prompt, negative_prompt, temp_image, mask_blurred, 7688778)
x = (1024 - resized_img.width) // 2
y = (1024 - resized_img.height) // 2
final_image.paste(resized_img, (x, y), resized_img)
final_image