Phase 08 - Lesson 09
Inpainting, Outpainting & Edição de Imagens
Text-to-image cria coisas novas. Inpainting corrige as antigas. Em produção, 70% do trabalho faturável com imagens é edição — trocar um fundo, remover um logotipo, estender a tela, regenerar uma mão. O inpainting é onde a difusão mostra o seu valor.
Tipo: Build Linguagens: Python Pré-requisitos: Phase 8 · 07 (Latent Diffusion), Phase 8 · 08 (ControlNet & LoRA) Tempo: ~75 minutos
O Problema
Um cliente envia uma foto perfeita de um produto, mas com uma placa que chama a atenção no fundo. Você quer apagar a placa e deixar todo o resto idêntico pixel a pixel. Não é possível executar o text-to-image do zero — o resultado terá uma cor diferente, iluminação diferente, ângulo diferente do produto. Você quer regenerar apenas a região mascarada, e quer que a regeneração respeite o contexto ao redor.
Isso é inpainting. Variantes:
- Inpainting. Regenerar dentro de uma máscara, mantendo os pixels externos.
- Outpainting. Regenerar fora de uma máscara (ou além da tela), mantendo o interior.
- Edição de imagens. Regenerar a imagem inteira, mas mantendo a fidelidade semântica ou estrutural com a original (SDEdit, InstructPix2Pix).
Todo pipeline de difusão em 2026 vem com um modo de inpainting. Flux.1-Fill, Stable Diffusion Inpaint, SDXL-Inpaint, DALL-E 3 Edit. Eles funcionam sob o mesmo princípio.
O Conceito
The naive approach (and why it's wrong)
Executar o text-to-image padrão com uma máscara. Em cada etapa de amostragem, substituir a região não mascarada do latente ruidoso pela imagem limpa com difusão direta (forward-diffused). Funciona... mal. Artefatos de borda vazam porque o modelo não tem informação sobre o que está na região mascarada.
O modelo de inpainting adequado
Treinar uma U-Net modificada que recebe 9 canais de entrada em vez de 4:
input = concat([ noisy_latent (4ch), encoded_image (4ch), mask (1ch) ], dim=channel)
Os canais extras são uma cópia da imagem de origem codificada por VAE mais uma máscara de canal único. No momento do treino, você mascara aleatoriamente regiões da imagem e treina o modelo para remover o ruído apenas da região mascarada, enquanto a região não mascarada é fornecida como um sinal de condicionamento limpo. Na inferência, o modelo consegue "ver" o que envolve a região mascarada e produz conclusões coerentes.
SD-Inpaint, SDXL-Inpaint, Flux-Fill utilizam essa entrada de 9 canais (ou similar). Diffusers StableDiffusionInpaintPipeline, FluxFillPipeline.
SDEdit (Meng et al., 2022) — edição livre
Adicionar ruído à imagem de origem até um t intermediário, depois executar a cadeia reversa de t até 0 com um novo prompt. Sem necessidade de retreino. A escolha do t inicial equilibra fidelidade e liberdade criativa:
t/T = 0.3→ quase idêntico à origem, pequenas alterações de estilot/T = 0.6→ edições moderadas, preserva a estrutura geralt/T = 0.9→ gerado a partir de quase puro ruído, preservação mínima da origem
InstructPix2Pix (Brooks et al., 2023)
Ajustar um modelo de difusão em trios de (input_image, instruction, output_image). Na inferência, condicionar tanto na imagem de entrada quanto em uma instrução de texto ("deixe como pôr do sol", "adicione um dragão"). Duas escalas CFG: escala de imagem e escala de texto.
RePaint (Lugmayr et al., 2022)
Manter um modelo de difusão incondicional padrão. A cada etapa reversa, realizar uma nova amostragem — voltar ocasionalmente para um estado com mais ruído e regenerar. Evita artefatos de borda. Usado quando você não tem um modelo de inpainting treinado.
Build It
O arquivo code/main.py implementa um esquema de inpainting didático 1-D em dados de 5 dimensões. Treinamos um DDPM em dados mistos 5-D onde cada amostra consiste em 5 números de ponto flutuante de um dos dois clusters. Na inferência, nós "mascaramos" 2 das 5 dimensões, injetamos a versão ruidosa direta (forward) das três dimensões não mascaradas em cada etapa e regeneramos apenas as dimensões mascaradas.
Passo 1: Dados do DDPM 5-D
def sample_data(rng):
cluster = rng.choice([0, 1])
center = [-1.0] * 5 if cluster == 0 else [1.0] * 5
return [c + rng.gauss(0, 0.2) for c in center], cluster
Passo 2: Treinar o denoiser em todas as 5 dimensões
DDPM padrão. A rede gera uma previsão de ruído 5-D para uma entrada ruidosa 5-D.
Passo 3: Na inferência, processo reverso ciente da máscara
def inpaint_step(x_t, mask, clean_image, alpha_bars, t, rng):
# replace unmasked dims with a freshly noised version of the clean source
a_bar = alpha_bars[t]
for i in range(len(x_t)):
if not mask[i]:
x_t[i] = math.sqrt(a_bar) * clean_image[i] + math.sqrt(1 - a_bar) * rng.gauss(0, 1)
# ...then run the normal reverse step on x_t
Esta é a abordagem ingênua e funciona em dados didáticos 1-D. O inpainting de imagens reais usa a entrada de 9 canais porque a coerência da textura é mais importante.
Passo 4: Outpainting
O outpainting é o inpainting com a máscara invertida: mascara-se a nova tela (que antes não existia) e preenche-se o restante com a original. O objetivo de treino é idêntico.
Armadilhas
- Costuras (seams). A abordagem ingênua deixa limites visíveis porque as informações de gradiente não fluem através da máscara. Solução: dilatar a máscara em 8-16 pixels ou usar um modelo de inpainting adequado.
- Vazamento da máscara (mask leakage). Se a região não mascarada da imagem de condicionamento for de baixa qualidade ou ruidosa, ela polui a geração dentro da máscara. Remova o ruído ou desfoque levemente.
- Interação do CFG com o tamanho da máscara. CFG alto em uma máscara pequena = região saturada. Reduza o CFG para edições pequenas.
- Queda abrupta de fidelidade no SDEdit (fidelity cliff). Ir de
t/T = 0.5parat/T = 0.6pode fazer com que a identidade do sujeito seja perdida. Faça varreduras (sweeps) e salve checkpoints. - Incompatibilidade de prompt (prompt mismatch). O prompt deve descrever a imagem inteira, não apenas o novo conteúdo. "A cat sitting on a chair" em vez de apenas "a cat".
Use It
| Tarefa | Pipeline |
|---|---|
| Remover objeto, máscara pequena | SD-Inpaint ou Flux-Fill, prompt padrão |
| Substituir céu | SD-Inpaint + "blue sky at sunset" |
| Estender tela | Modo outpaint do SDXL (suavização/feather de 8px) ou Flux-Fill com máscara de outpaint |
| Regenerar mão / rosto | SD-Inpaint com prompt redescrevendo o sujeito + ControlNet-Openpose |
| Alterar o estilo de uma região | SDEdit em t/T=0.5 na região mascarada |
| "Make it sunset" | InstructPix2Pix ou Flux-Kontext |
| Substituição de fundo | Máscara SAM → SD-Inpaint |
| Fidelidade ultra-alta | Flux-Fill ou GPT-Image (hospedado) para os casos mais difíceis |
O SAM (Segment Anything da Meta, 2023) + inpaint por difusão é o pipeline de remoção de fundo em 2026. O SAM 2 (2024) funciona em vídeo.
Ship It
Salve outputs/skill-editing-pipeline.md. A Skill recebe uma imagem original + descrição da edição + máscara opcional (or prompt do SAM) e gera: abordagem de geração de máscara, modelo base, escalas CFG (imagem + texto), SDEdit-t ou modo de inpainting, e um checklist de garantia de qualidade (QA).
Exercícios
- Fácil. Em
code/main.py, varie a fração de dimensões mascaradas de 0.2 a 0.8. Em qual fração a qualidade do inpaint (resíduo nas dimensões mascaradas) se iguala à geração incondicional? - Médio. Implemente o RePaint: a cada 10ª etapa reversa, volte 5 etapas (adicione ruído) e remova o ruído novamente. Meça se isso reduz o resíduo de borda no limite da máscara.
- Difícil. Use os diffusers do Hugging Face para comparar: SD 1.5 Inpaint + ControlNet-Openpose vs Flux.1-Fill em 20 tarefas de regeneração facial. Pontue a aderência à pose e a preservação da identidade separadamente.
Termos-Chave
| Termo | O que as pessoas dizem | O que realmente significa |
|---|---|---|
| Inpainting | "Preencher o buraco" | Regenerar dentro de uma máscara; manter os pixels externos. |
| Outpainting | "Estender a tela" | Regenerar fora da tela; manter o interior. |
| U-Net de 9 canais | "Modelo de inpainting adequado" | U-Net com noisy | encoded-source | mask como entrada. |
| SDEdit | "Img2img com nível de ruído" | Ruído até o tempo t, denoising com novo prompt. |
| InstructPix2Pix | "Edições apenas por texto" | Difusão ajustada (fine-tuned) em trios de (imagem, instrução, saída). |
| RePaint | "Sem retreino" | Adicionar ruído periodicamente durante o processo reverso para reduzir as costuras (seams). |
| SAM | "Segment Anything" | Gerador de máscara por cliques ou caixas de seleção; faz par com inpaint. |
| Flux-Kontext | "Editar com contexto" | Variante do Flux que aceita uma imagem de referência + instrução para edições. |
Nota de produção: pipelines de edição são sensíveis à latência
Usuários que editam uma imagem esperam tempos de resposta (round trips) inferiores a 5 segundos. Um SDXL-Inpaint de 30 etapas em 1024² leva 3-4 segundos em uma L4, mais a geração de máscara com SAM (200 ms) e codificação/decodificação VAE (500 ms combinados). No contexto de produção, isso é limitado pelo TTFT (Time to First Token) em vez de throughput — lote (batch) de tamanho 1, baixa concorrência, minimize cada etapa:
- O SAM-H é a parte lenta. O SAM-H em 1024² leva ~200 ms; o SAM-ViT-B leva ~40 ms com pequena perda de qualidade. O SAM 2 (vídeo) adiciona sobrecarga temporal; não o use para edições de imagens únicas.
- Pule a codificação quando possível.
pipe.image_processor.preprocess(img)codifica para latentes. Se você já tiver os latentes da geração anterior (típico em UIs de edição iterativa), passe-os diretamente vialatents=...para pular uma codificação VAE. - A dilatação da máscara também afeta o throughput. Uma máscara pequena significa que a maior parte da passada direta (forward pass) da U-Net é desperdiçada (os pixels não mascarados são fixados/clamped de qualquer forma). A
StableDiffusionInpaintPipelineda bibliotecadiffusersexecuta toda a U-Net de qualquer maneira; apenas as variantes adequadas de inpainting com 9 canais aproveitam a computação mascarada. - O Flux-Kontext é a resposta em 2025. Uma única passada direta sobre
(source_image, instruction)— sem máscara separada, sem varredura de ruído SDEdit. Em uma H100, ele entrega uma edição em ~1.5 s. A lição de arquitetura: simplifique e unifique as etapas.
Leitura Adicional
- Lugmayr et al. (2022). RePaint: Inpainting using Denoising Diffusion Probabilistic Models — inpainting livre de treinamento.
- Meng et al. (2022). SDEdit: Guided Image Synthesis and Editing with Stochastic Differential Equations — SDEdit.
- Brooks, Holynski, Efros (2023). InstructPix2Pix — edição por instrução de texto.
- Kirillov et al. (2023). Segment Anything — SAM, a origem da máscara.
- Ravi et al. (2024). SAM 2: Segment Anything in Images and Videos — SAM para vídeo.
- Hertz et al. (2022). Prompt-to-Prompt Image Editing with Cross-Attention Control — edição em nível de atenção.
- Black Forest Labs (2024). Flux.1-Fill and Flux.1-Kontext — ferramentas de 2024.