Diffusers documentation

Inpainting

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

Inpainting

Inpainting substitui ou edita áreas específicas de uma imagem. Isso o torna uma ferramenta útil para a restauração de imagens, como a remoção de defeitos e artefatos, ou até mesmo a substituição de uma área da imagem por algo completamente novo. O inpainting depende de uma máscara para determinar quais regiões da imagem devem ser preenchidas; a área a ser preenchida é representada por pixels brancos e a área a ser mantida é representada por pixels pretos. Os pixels brancos são preenchidos pelo prompt.

Com o 🤗 Diffusers, é assim que você pode fazer inpainting:

  1. Carregue um checkpoint de inpainting com a classe AutoPipelineForInpainting. Isso detectará automaticamente a classe de pipeline apropriada para carregar com base no checkpoint:
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "kandinsky-community/kandinsky-2-2-decoder-inpaint", dtype=torch.float16
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

Você notará, ao longo do guia, que usamos enable_model_cpu_offload() e enable_xformers_memory_efficient_attention() para economizar memória e aumentar a velocidade de inferência. Se você estiver usando PyTorch 2.0, não é necessário chamar enable_xformers_memory_efficient_attention() no seu pipeline, pois ele já estará usando o scaled-dot product attention nativo do PyTorch 2.0.

  1. Carregue as imagens de base e de máscara:
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")
  1. Crie um prompt para fazer o inpainting da imagem e passe-o para o pipeline junto com as imagens base e de máscara:
prompt = "a black cat with glowing eyes, cute, adorable, disney, pixar, highly detailed, 8k"
negative_prompt = "bad anatomy, deformed, ugly, disfigured"
image = pipeline(prompt=prompt, negative_prompt=negative_prompt, image=init_image, mask_image=mask_image).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
imagem base
imagem de máscara
imagem gerada

Crie uma imagem de máscara

Ao longo deste guia, a imagem de máscara é fornecida em todos os exemplos de código para sua conveniência. Você pode fazer inpainting em suas próprias imagens, mas precisará criar uma imagem de máscara para isso. Use o Space abaixo para criar facilmente uma imagem de máscara.

Envie uma imagem base para fazer o inpainting e use a ferramenta de esboço para desenhar uma máscara. Quando terminar, clique em Run para gerar e baixar a imagem da máscara.

Desfoque da máscara

O método blur() oferece uma opção para definir como mesclar a imagem original e a área de inpainting. A quantidade de desfoque é determinada pelo parâmetro blur_factor. Aumentar o blur_factor aumenta a quantidade de desfoque aplicada às bordas da máscara, suavizando a transição entre a imagem original e a área de inpainting. Um blur_factor baixo ou zero preserva as bordas mais nítidas da máscara.

Para usar isso, crie uma máscara desfocada com o processador de imagem.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image
from PIL import Image

pipeline = AutoPipelineForInpainting.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16).to('cuda')  # or "mps", "xpu", "cpu"

mask = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/seashore_mask.png")
blurred_mask = pipeline.mask_processor.blur(mask, blur_factor=33)
blurred_mask
máscara sem desfoque
máscara com desfoque aplicado

Modelos populares

Stable Diffusion Inpainting, Stable Diffusion XL (SDXL) Inpainting e Kandinsky 2.2 Inpainting estão entre os modelos mais populares para inpainting. O SDXL geralmente produz imagens com resolução mais alta do que o Stable Diffusion v1.5, e o Kandinsky 2.2 também é capaz de gerar imagens de alta qualidade.

Stable Diffusion Inpainting

Stable Diffusion Inpainting é um modelo de difusão latente ajustado em imagens de 512x512 para inpainting. É um bom ponto de partida porque é relativamente rápido e gera imagens de boa qualidade. Para usar este modelo para inpainting, você precisará passar um prompt, uma imagem base e uma imagem de máscara para o pipeline:

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)

Inpainting do Stable Diffusion XL (SDXL)

SDXL é uma versão maior e mais poderosa do Stable Diffusion v1.5. Este modelo pode seguir um processo de modelo em duas etapas (embora cada modelo também possa ser usado isoladamente); o modelo base gera uma imagem, e um modelo refinador recebe essa imagem e aprimora ainda mais seus detalhes e qualidade. Dê uma olhada no guia SDXL para um guia mais abrangente sobre como usar o SDXL e configurar seus parâmetros.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "diffusers/stable-diffusion-xl-1.0-inpainting-0.1", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)

Kandinsky 2.2 Inpainting

A família de modelos Kandinsky é semelhante ao SDXL, pois também utiliza dois modelos; o modelo de prior de imagem cria incorporações de imagem e o modelo de difusão gera imagens a partir delas. Você pode carregar o modelo de prior de imagem e o modelo de difusão separadamente, mas a maneira mais fácil de usar o Kandinsky 2.2 é carregá-lo na classe AutoPipelineForInpainting, que usa o KandinskyV22InpaintCombinedPipeline por baixo dos panos.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "kandinsky-community/kandinsky-2-2-decoder-inpaint", dtype=torch.float16
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
imagem base
Stable Diffusion Inpainting
Stable Diffusion XL Inpainting
Kandinsky 2.2 Inpainting

Pontos de verificação específicos não-inpaint

Até agora, este guia utilizou checkpoints específicos para inpainting, como stable-diffusion-v1-5/stable-diffusion-inpainting. Mas você também pode usar checkpoints regulares, como stable-diffusion-v1-5/stable-diffusion-v1-5. Vamos comparar os resultados dos dois checkpoints.

A imagem à esquerda é gerada a partir de um checkpoint regular, e a imagem à direita é de um checkpoint de inpaint. Você notará imediatamente que a imagem à esquerda não é tão limpa, e ainda é possível ver o contorno da área que o modelo deve inpaintar. A imagem à direita é muito mais limpa e a área inpaintada parece mais natural.

stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpainting
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

generator = torch.Generator("cuda").manual_seed(92)
prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, generator=generator).images[0]
make_image_grid([init_image, image], rows=1, cols=2)
stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpainting

No entanto, para tarefas mais básicas, como apagar um objeto de uma imagem (por exemplo, as pedras na estrada), um checkpoint regular produz resultados bastante bons. Não há uma diferença tão perceptível entre o checkpoint regular e o checkpoint de inpaint.

stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpaint
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/road-mask.png")

image = pipeline(prompt="road", image=init_image, mask_image=mask_image).images[0]
make_image_grid([init_image, image], rows=1, cols=2)
stable-diffusion-v1-5/stable-diffusion-v1-5
stable-diffusion-v1-5/stable-diffusion-inpainting

A desvantagem de usar um checkpoint não específico para inpainting é que a qualidade geral da imagem pode ser inferior, mas ele tende a preservar a área da máscara (é por isso que você pode ver o contorno da máscara). Os checkpoints específicos para inpainting são treinados intencionalmente para gerar imagens com inpainting de maior qualidade, o que inclui criar uma transição mais natural entre as áreas mascaradas e não mascaradas. Como resultado, esses checkpoints têm maior probabilidade de alterar sua área não mascarada.

Se preservar a área sem máscara for importante para sua tarefa, você pode usar o método VaeImageProcessor.apply_overlay() para forçar que a área sem máscara de uma imagem permaneça a mesma, em detrimento de transições um pouco menos naturais entre as áreas com e sem máscara.

import PIL
import numpy as np
import torch

from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

device = "cuda"  # or "mps", "xpu", "cpu"
pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting",
    dtype=torch.float16,
    variant="fp16"
)
pipeline = pipeline.to(device)

img_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo.png"
mask_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo_mask.png"

init_image = load_image(img_url).resize((512, 512))
mask_image = load_image(mask_url).resize((512, 512))

prompt = "Face of a yellow cat, high resolution, sitting on a park bench"
repainted_image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image).images[0]
repainted_image.save("repainted_image.png")

unmasked_unchanged_image = pipeline.image_processor.apply_overlay(mask_image, init_image, repainted_image)
unmasked_unchanged_image.save("force_unmasked_unchanged.png")
make_image_grid([init_image, mask_image, repainted_image, unmasked_unchanged_image], rows=2, cols=2)

Configure os parâmetros do pipeline

Os recursos da imagem - como qualidade e “criatividade” - dependem dos parâmetros do pipeline. Saber o que esses parâmetros fazem é importante para obter os resultados desejados. Vamos dar uma olhada nos parâmetros mais importantes e ver como alterá-los afeta a saída.

Força

strength é uma medida de quanta ruído é adicionada à imagem base, o que influencia o quão semelhante a saída é à imagem base.

  • 📈 um valor de strength alto significa que mais ruído é adicionado à imagem e o processo de remoção de ruído leva mais tempo, mas você obterá imagens de maior qualidade que são mais diferentes da imagem base
  • 📉 um valor baixo de strength significa que menos ruído é adicionado à imagem e o processo de remoção de ruído é mais rápido, mas a qualidade da imagem pode não ser tão boa e a imagem gerada se assemelha mais à imagem base
import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, strength=0.6).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
strength = 0.6
strength = 0.8
strength = 1.0

Escala de orientação

guidance_scale afeta o quão alinhados estão o prompt de texto e a imagem gerada.

  • 📈 um valor alto de guidance_scale significa que o prompt e a imagem gerada estão estreitamente alinhados, portanto, a saída é uma interpretação mais rigorosa do prompt
  • 📉 um valor baixo de guidance_scale significa que o prompt e a imagem gerada estão mais frouxamente alinhados, portanto, a saída pode ser mais variada em relação ao prompt

Você pode usar strength e guidance_scale juntos para ter mais controle sobre o quão expressivo o modelo é. Por exemplo, uma combinação de valores altos de strength e guidance_scale dá ao modelo a maior liberdade criativa.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, guidance_scale=2.5).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
guidance_scale = 2.5
guidance_scale = 7.5
guidance_scale = 12.5

Prompt negativo

Um prompt negativo assume o papel oposto ao de um prompt; ele orienta o modelo a evitar a geração de certos elementos em uma imagem. Isso é útil para melhorar rapidamente a qualidade da imagem e impedir que o modelo gere coisas que você não deseja.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
negative_prompt = "bad architecture, unstable, poor details, blurry"
image = pipeline(prompt=prompt, negative_prompt=negative_prompt, image=init_image, mask_image=mask_image).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)
negative_prompt = "bad architecture, unstable, poor details, blurry"

Corte da máscara de preenchimento

Um método para aumentar a qualidade da imagem de inpainting é usar o parâmetro padding_mask_crop. Quando habilitado, essa opção recorta a área mascarada com algum padding especificado pelo usuário e também recorta a mesma área da imagem original. Tanto a imagem quanto a máscara são ampliadas para uma resolução mais alta para o inpainting e, em seguida, sobrepostas à imagem original. Esta é uma maneira rápida e fácil de melhorar a qualidade da imagem sem usar um pipeline separado como StableDiffusionUpscalePipeline.

Adicione o parâmetro padding_mask_crop à chamada do pipeline e defina-o com o valor de padding desejado.

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import load_image
from PIL import Image

generator = torch.Generator(device='cuda').manual_seed(0)  # or "mps", "xpu", "cpu"
pipeline = AutoPipelineForInpainting.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16).to('cuda')

base = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/seashore.png")
mask = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/seashore_mask.png")

image = pipeline("boat", image=base, mask_image=mask, strength=0.75, generator=generator, padding_mask_crop=32).images[0]
image
imagem padrão de inpaint
inpaint image com `padding_mask_crop` habilitado

Pipelines de inpainting encadeados

AutoPipelineForInpainting pode ser encadeado com outros pipelines do 🤗 Diffusers para editar suas saídas. Isso é frequentemente útil para melhorar a qualidade da saída dos seus outros pipelines de difusão, e, se você estiver usando vários pipelines, pode ser mais eficiente em termos de memória encadeá-los para manter as saídas no espaço latente e reutilizar os mesmos componentes do pipeline.

Texto-para-imagem-para-inpaint

Encadear um pipeline de texto para imagem e um pipeline de inpainting permite que você faça o inpainting da imagem gerada, sem precisar fornecer uma imagem base inicialmente. Isso facilita a edição dos seus resultados favoritos de texto para imagem sem ter que gerar uma imagem totalmente nova.

Comece com o pipeline de texto para imagem para criar um castelo:

import torch
from diffusers import AutoPipelineForText2Image, AutoPipelineForInpainting
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForText2Image.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16, variant="fp16", use_safetensors=True
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

text2image = pipeline("concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k").images[0]

Carregue a imagem de máscara da saída acima:

mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_text-chain-mask.png")

E vamos preencher a área mascarada com uma cachoeira:

pipeline = AutoPipelineForInpainting.from_pretrained(
    "kandinsky-community/kandinsky-2-2-decoder-inpaint", dtype=torch.float16
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

prompt = "digital painting of a fantasy waterfall, cloudy"
image = pipeline(prompt=prompt, image=text2image, mask_image=mask_image).images[0]
make_image_grid([text2image, mask_image, image], rows=1, cols=3)
texto-para-imagem
inpaint

Inpaint-to-image-to-image

Você também pode encadear um pipeline de inpainting antes de outro pipeline, como image-to-image ou um upscaler, para melhorar a qualidade.

Comece fazendo inpainting de uma imagem:

import torch
from diffusers import AutoPipelineForInpainting, AutoPipelineForImage2Image
from diffusers.utils import load_image, make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image_inpainting = pipeline(prompt=prompt, image=init_image, mask_image=mask_image).images[0]

# resize image to 1024x1024 for SDXL
image_inpainting = image_inpainting.resize((1024, 1024))

Agora, vamos passar a imagem para outro pipeline de inpainting com o modelo refiner do SDXL para aprimorar os detalhes e a qualidade da imagem:

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stabilityai/stable-diffusion-xl-refiner-1.0", dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

image = pipeline(prompt=prompt, image=image_inpainting, mask_image=mask_image, output_type="latent").images[0]

É importante especificar output_type="latent" no pipeline para manter todas as saídas no espaço latente e evitar uma etapa desnecessária de decodificação-encodificação. Isso só funciona se os pipelines encadeados estiverem usando o mesmo VAE. Por exemplo, na seção Text-to-image-to-inpaint, o Kandinsky 2.2 usa uma classe de VAE diferente da do modelo Stable Diffusion, então não funcionará. Mas, se você usar o Stable Diffusion v1.5 para ambos os pipelines, poderá manter tudo no espaço latente, pois ambos usam AutoencoderKL.

Por fim, você pode passar essa imagem para um pipeline de imagem-para-imagem para dar os toques finais. É mais eficiente usar o método from_pipe() para reutilizar os componentes existentes do pipeline e evitar carregar novamente todos os componentes do pipeline na memória desnecessariamente.

pipeline = AutoPipelineForImage2Image.from_pipe(pipeline)
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

image = pipeline(prompt=prompt, image=image).images[0]
make_image_grid([init_image, mask_image, image_inpainting, image], rows=2, cols=2)
imagem inicial
inpaint
imagem-para-imagem

Image-to-image e inpainting são, na verdade, tarefas muito semelhantes. O image-to-image gera uma nova imagem que se assemelha à imagem existente fornecida. O inpainting faz a mesma coisa, mas transforma apenas a área da imagem definida pela máscara, enquanto o restante da imagem permanece inalterado. Você pode pensar no inpainting como uma ferramenta mais precisa para fazer alterações específicas, enquanto o image-to-image tem um escopo mais amplo para fazer mudanças mais abrangentes.

Controlar a geração de imagens

Obter uma imagem exatamente como você deseja é desafiador porque o processo de remoção de ruído é aleatório. Embora você possa controlar certos aspectos da geração configurando parâmetros como negative_prompt, existem métodos melhores e mais eficientes para controlar a geração de imagens.

Ponderação de prompts

O ponderamento de prompts oferece uma maneira quantificável de escalar a representação de conceitos em um prompt. Você pode usá-lo para aumentar ou diminuir a magnitude do vetor de incorporação de texto para cada conceito no prompt, o que, em seguida, determina quanto de cada conceito é gerado. A biblioteca Compel oferece uma sintaxe intuitiva para escalar os pesos do prompt e gerar as incorporações. Saiba como criar as incorporações no guia Ponderamento de prompts.

Depois de gerar os embeddings, passe-os para o parâmetro prompt_embeds (e negative_prompt_embeds, se estiver usando um prompt negativo) no AutoPipelineForInpainting. Os embeddings substituem o parâmetro prompt:

import torch
from diffusers import AutoPipelineForInpainting
from diffusers.utils import make_image_grid

pipeline = AutoPipelineForInpainting.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", dtype=torch.float16,
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

image = pipeline(prompt_embeds=prompt_embeds, # generated from Compel
    negative_prompt_embeds=negative_prompt_embeds, # generated from Compel
    image=init_image,
    mask_image=mask_image
).images[0]
make_image_grid([init_image, mask_image, image], rows=1, cols=3)

ControlNet

Os modelos ControlNet são usados em conjunto com outros modelos de difusão, como o Stable Diffusion, e oferecem uma maneira ainda mais flexível e precisa de controlar como uma imagem é gerada. Um ControlNet aceita uma imagem de condicionamento adicional como entrada, que orienta o modelo de difusão a preservar as características presentes nela.

Por exemplo, vamos condicionar uma imagem com um ControlNet pré-treinado em imagens de inpaint:

import torch
import numpy as np
from diffusers import ControlNetModel, StableDiffusionControlNetInpaintPipeline
from diffusers.utils import load_image, make_image_grid

# load ControlNet
controlnet = ControlNetModel.from_pretrained("lllyasviel/control_v11p_sd15_inpaint", dtype=torch.float16, variant="fp16")

# pass ControlNet to the pipeline
pipeline = StableDiffusionControlNetInpaintPipeline.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-inpainting", controlnet=controlnet, dtype=torch.float16, variant="fp16"
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

# load base and mask image
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint.png")
mask_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/inpaint_mask.png")

# prepare control image
def make_inpaint_condition(init_image, mask_image):
    init_image = np.array(init_image.convert("RGB")).astype(np.float32) / 255.0
    mask_image = np.array(mask_image.convert("L")).astype(np.float32) / 255.0

    assert init_image.shape[0:1] == mask_image.shape[0:1], "image and image_mask must have the same image size"
    init_image[mask_image > 0.5] = -1.0  # set as masked pixel
    init_image = np.expand_dims(init_image, 0).transpose(0, 3, 1, 2)
    init_image = torch.from_numpy(init_image)
    return init_image

control_image = make_inpaint_condition(init_image, mask_image)

Agora, gere uma imagem a partir das imagens base, máscara e de controle. Você notará que as características da imagem base são fortemente preservadas na imagem gerada.

prompt = "concept art digital painting of an elven castle, inspired by lord of the rings, highly detailed, 8k"
image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image, control_image=control_image).images[0]
make_image_grid([init_image, mask_image, PIL.Image.fromarray(np.uint8(control_image[0][0])).convert('RGB'), image], rows=2, cols=2)

Você pode ir um passo além e encadear isso com um pipeline de imagem-para-imagem para aplicar um novo estilo:

from diffusers import AutoPipelineForImage2Image

pipeline = AutoPipelineForImage2Image.from_pretrained(
    "nitrosocke/elden-ring-diffusion", dtype=torch.float16,
)
pipeline.enable_model_cpu_offload()
# remove following line if xFormers is not installed or you have PyTorch 2.0 or higher installed
pipeline.enable_xformers_memory_efficient_attention()

prompt = "elden ring style castle" # include the token "elden ring style" in the prompt
negative_prompt = "bad architecture, deformed, disfigured, poor details"

image_elden_ring = pipeline(prompt, negative_prompt=negative_prompt, image=image).images[0]
make_image_grid([init_image, mask_image, image, image_elden_ring], rows=2, cols=2)
imagem inicial
ControlNet inpaint
imagem-para-imagem

Otimizar

Executar modelos de difusão pode ser difícil e lento se você tiver recursos limitados, mas não precisa ser assim com alguns truques de otimização. Uma das otimizações mais importantes (e fáceis) que você pode habilitar é alternar para a atenção de eficiência de memória. Se você estiver usando PyTorch 2.0, a atenção de produto escalar é habilitada automaticamente e você não precisa fazer mais nada. Para usuários que não usam PyTorch 2.0, você pode instalar e usar a implementação de atenção de eficiência de memória do xFormers. Ambas as opções reduzem o uso de memória e aceleram a inferência.

Você também pode transferir o modelo para a CPU para economizar ainda mais memória:

+ pipeline.enable_xformers_memory_efficient_attention()
+ pipeline.enable_model_cpu_offload()

Para acelerar ainda mais seu código de inferência, use torch_compile. Você deve envolver torch.compile ao redor do componente mais intenso do pipeline, que tipicamente é o UNet:

pipeline.unet = torch.compile(pipeline.unet, mode="reduce-overhead", fullgraph=True)

Saiba mais nos guias Reduzir o uso de memória e Acelerar a inferência.

Update on GitHub