Buckets:

mishig's picture
|
download
raw
7.76 kB
# Outpainting
Outpainting estende uma imagem além de suas fronteiras originais, permitindo adicionar, substituir ou modificar elementos visuais em uma imagem enquanto preserva a imagem original. Assim como no [inpainting](../using-diffusers/inpaint), o objetivo é preencher a área branca (neste caso, a área fora da imagem original) com novos elementos visuais, mantendo a imagem original (representada por uma máscara de pixels pretos). Existem algumas maneiras de realizar outpainting, como com um [ControlNet](https://hf.co/blog/OzzyGT/outpainting-controlnet) ou com [Differential Diffusion](https://hf.co/blog/OzzyGT/outpainting-differential-diffusion).
Este guia mostrará como fazer outpainting com um modelo de inpainting, ControlNet e um estimador ZoeDepth.
Antes de começar, verifique se a biblioteca [controlnet_aux](https://github.com/huggingface/controlnet_aux) está instalada para que você possa usar o estimador ZoeDepth.
```py
!pip install -q controlnet_aux
```
## Preparação de imagem
Comece escolhendo uma imagem para fazer outpainting e remova o fundo com um Space como [BRIA-RMBG-1.4](https://hf.co/spaces/briaai/BRIA-RMBG-1.4).
<iframe src="https://briaai-bria-rmbg-1-4.hf.space" frameborder="0" width="850" height="450"
>
Por exemplo, remova o fundo desta imagem de um par de sapatos.
imagem original
fundo removido
Os modelos [Stable Diffusion XL (SDXL)](../api/pipelines/stable_diffusion/stable_diffusion_xl) funcionam melhor com imagens de 1024x1024, mas você pode redimensionar a imagem para qualquer tamanho, desde que seu hardware tenha memória suficiente para suportá-lo. O fundo transparente da imagem também deve ser substituído por um fundo branco. Crie uma função (como a abaixo) que escala e cola a imagem sobre um fundo branco.
```py
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)
```
Para evitar a adição de detalhes extras indesejados, use o estimador ZoeDepth para fornecer orientação adicional durante a geração e garantir que os sapatos permaneçam consistentes com a imagem original.
```py
zoe = ZoeDetector.from_pretrained("lllyasviel/Annotators")
image_zoe = zoe(white_bg_image, detect_resolution=512, image_resolution=1024)
image_zoe
```
## Outpaint
Quando sua imagem estiver pronta, você pode gerar conteúdo na área branca ao redor dos sapatos com [controlnet-inpaint-dreamer-sdxl](https://hf.co/destitech/controlnet-inpaint-dreamer-sdxl), um ControlNet SDXL treinado para inpainting.
Carregue o ControlNet de inpainting, o modelo ZoeDepth e o VAE e passe-os para o [StableDiffusionXLControlNetPipeline](/docs/diffusers/main/pt/api/pipelines/controlnet_sdxl#diffusers.StableDiffusionXLControlNetPipeline). Em seguida, você pode criar uma função opcional `generate_image` (para conveniência) para fazer outpainting de uma imagem inicial.
```py
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)
```
Cole a imagem original sobre a imagem inicial expandida. Você melhorará o fundo expandido em uma etapa posterior.
```py
x = (1024 - resized_img.width) // 2
y = (1024 - resized_img.height) // 2
temp_image.paste(resized_img, (x, y), resized_img)
temp_image
```
> [!TIP]
> Agora é um bom momento para liberar memória, caso você esteja com pouco espaço disponível!
>
> ```py
> pipeline=None
> torch.cuda.empty_cache()
> ```
Agora que você tem uma imagem inicial outpainted, carregue o [StableDiffusionXLInpaintPipeline](/docs/diffusers/main/pt/api/pipelines/stable_diffusion/stable_diffusion_xl#diffusers.StableDiffusionXLInpaintPipeline) com o modelo [RealVisXL](https://hf.co/SG161222/RealVisXL_V4.0) para gerar a imagem outpainted final com melhor qualidade.
```py
pipeline = StableDiffusionXLInpaintPipeline.from_pretrained(
"OzzyGT/RealVisXL_V4.0_inpainting",
dtype=torch.float16,
variant="fp16",
vae=vae,
).to("cuda") # or "mps", "xpu", "cpu"
```
Prepare uma máscara para a imagem final outpainted. Para criar uma transição mais natural entre a imagem original e o fundo outpainted, aplique um desfoque na máscara para ajudar a mesclá-la melhor.
```py
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
```
Crie um prompt melhor e passe-o para a função `generate_outpaint` para gerar a imagem final outpainted. Novamente, cole a imagem original sobre o fundo outpainted final.
```py
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
```

Xet Storage Details

Size:
7.76 kB
·
Xet hash:
a9829385d8fde6b17f856e0202e0e2db699c83bbbc3ff9043b612afbf5ad2029

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.