Diffusers documentation

Outpainting

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.42.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

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.

gambar asli
latar belakang dihapus

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
Update on GitHub