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

L’inpainting remplace ou modifie des zones spécifiques d’une image. Il s’agit donc d’un outil utile pour la restauration d’images, comme la suppression de défauts et d’artefacts, ou même le remplacement d’une zone d’image par un contenu entièrement nouveau. L’inpainting s’appuie sur un masque pour déterminer quelles régions de l’image doivent être remplies ; la zone à inpainter est représentée par des pixels blancs et la zone à conserver par des pixels noirs. Les pixels blancs sont remplis par le prompt.

Avec 🤗 Diffusers, voici comment effectuer de l'inpainting :

  1. Chargez un point de contrôle d'inpainting avec la classe AutoPipelineForInpainting. Cela détectera automatiquement la classe de pipeline appropriée à charger en fonction du point de contrôle :
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()

Vous remarquerez tout au long du guide que nous utilisons enable_model_cpu_offload() et enable_xformers_memory_efficient_attention() pour économiser de la mémoire et augmenter la vitesse d’inférence. Si vous utilisez PyTorch 2.0, il n’est pas nécessaire d’appeler enable_xformers_memory_efficient_attention() sur votre pipeline, car il utilisera déjà le scaled-dot product attention natif de PyTorch 2.0.

  1. Charger les images de base et de masque :
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. Créez un prompt pour l’image à inpainter et passez-le au pipeline avec les images de base et de masque :
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)
image de base
masque d'image
image générée

Créer une image de masque

Tout au long de ce guide, l’image de masque est fournie dans tous les exemples de code pour plus de commodité. Vous pouvez effectuer de l’inpainting sur vos propres images, mais vous devrez créer une image de masque à cet effet. Utilisez l’espace ci-dessous pour créer facilement une image de masque.

Téléchargez une image de base sur laquelle effectuer l'inpainting et utilisez l'outil de croquis pour dessiner un masque. Une fois terminé, cliquez sur Run pour générer et télécharger l'image du masque.

Flou du masque

La méthode blur() offre une option pour définir la manière de fusionner l'image d'origine et la zone d'inpainting. Le niveau de flou est déterminé par le paramètre blur_factor. Augmenter la valeur de blur_factor augmente le flou appliqué aux bords du masque, adoucissant ainsi la transition entre l'image d'origine et la zone d'inpainting. Une valeur faible ou nulle de blur_factor préserve les bords plus nets du masque.

Pour l'utiliser, créez un masque flou avec le processeur d'images.

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
masque sans flou
masque avec flou appliqué

Modèles populaires

Stable Diffusion Inpainting, Stable Diffusion XL (SDXL) Inpainting et Kandinsky 2.2 Inpainting comptent parmi les modèles les plus populaires pour l'inpainting. SDXL génère généralement des images de résolution supérieure à celles de Stable Diffusion v1.5, et Kandinsky 2.2 est également capable de produire des images de haute qualité.

Stable Diffusion Inpainting

Stable Diffusion Inpainting est un modèle de diffusion latente affiné sur des images de 512x512 pour l'inpainting. C'est un bon point de départ car il est relativement rapide et génère des images de bonne qualité. Pour utiliser ce modèle pour l'inpainting, vous devez passer un prompt, une image de base et un masque à la 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 avec Stable Diffusion XL (SDXL)

SDXL est une version plus grande et plus puissante de Stable Diffusion v1.5. Ce modèle peut suivre un processus de modèle en deux étapes (bien que chaque modèle puisse également être utilisé seul) ; le modèle de base génère une image, et un modèle de raffinement prend cette image pour en améliorer davantage les détails et la qualité. Consultez le guide SDXL pour un guide plus complet sur l’utilisation de SDXL et la configuration de ses paramètres.

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

La famille de modèles Kandinsky est similaire à SDXL car elle utilise également deux modèles ; le modèle d’antécédent d’image crée des embeddings d’image, et le modèle de diffusion génère des images à partir de ceux-ci. Vous pouvez charger le modèle d’antécédent d’image et le modèle de diffusion séparément, mais la façon la plus simple d’utiliser Kandinsky 2.2 est de le charger dans la classe AutoPipelineForInpainting, qui utilise KandinskyV22InpaintCombinedPipeline en interne.

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)
image de base
Stable Diffusion Inpainting
Stable Diffusion XL Inpainting
Kandinsky 2.2 Inpainting

Points de contrôle non spécifiques à l'inpainting

Jusqu’à présent, ce guide a utilisé des points de contrôle spécifiques à l’inpainting, tels que stable-diffusion-v1-5/stable-diffusion-inpainting. Mais vous pouvez également utiliser des points de contrôle classiques comme stable-diffusion-v1-5/stable-diffusion-v1-5. Comparons les résultats des deux points de contrôle.

L’image de gauche est générée à partir d’un point de contrôle standard, tandis que l’image de droite provient d’un point de contrôle d’inpainting. Vous remarquerez immédiatement que l’image de gauche est moins propre et que le contour de la zone que le modèle est censé inpainter reste visible. L’image de droite est beaucoup plus propre et la zone inpaintée apparaît plus naturelle.

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

Cependant, pour des tâches plus basiques comme effacer un objet d’une image (par exemple, les rochers sur la route), un point de contrôle standard donne des résultats assez bons. La différence entre le point de contrôle standard et le point de contrôle d’imputation n’est pas aussi marquée.

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

Le compromis lié à l’utilisation d’un checkpoint non spécifique à l’inpainting est que la qualité globale de l’image peut être inférieure, mais il a généralement tendance à préserver la zone masquée (c’est pourquoi vous pouvez voir le contour du masque). Les checkpoints spécifiques à l’inpainting sont entraînés intentionnellement pour générer des images inpaintées de plus haute qualité, ce qui inclut la création d’une transition plus naturelle entre les zones masquées et non masquées. En conséquence, ces checkpoints sont plus susceptibles de modifier votre zone non masquée.

Si la préservation de la zone non masquée est importante pour votre tâche, vous pouvez utiliser la méthode VaeImageProcessor.apply_overlay() pour forcer la zone non masquée d’une image à rester identique, au prix de transitions légèrement moins naturelles entre les zones masquée et non masquée.

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)

Configurer les paramètres du pipeline

Les caractéristiques de l’image – comme la qualité et la « créativité » – dépendent des paramètres du pipeline. Comprendre le rôle de ces paramètres est essentiel pour obtenir les résultats souhaités. Examinons les paramètres les plus importants et voyons comment leur modification affecte la sortie.

Force

strength est une mesure de la quantité de bruit ajoutée à l'image de base, ce qui influence le degré de ressemblance entre l'image de sortie et l'image de base.

  • 📈 une valeur de strength élevée signifie qu'un plus grand niveau de bruit est ajouté à l'image et que le processus de débruitage prend plus de temps, mais vous obtiendrez des images de meilleure qualité, plus différentes de l'image de base
  • 📉 une valeur de strength faible signifie qu'un niveau de bruit plus faible est ajouté à l'image et que le processus de débruitage est plus rapide, mais la qualité de l'image peut être moindre et l'image générée ressemble davantage à l'image de 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

Échelle de guidage

guidance_scale influence le degré d’alignement entre le prompt texte et l’image générée.

  • 📈 une valeur élevée de guidance_scale signifie que le prompt et l'image générée sont étroitement alignés, de sorte que la sortie est une interprétation plus stricte du prompt
  • 📉 une valeur faible de guidance_scale signifie que l'alignement entre le prompt et l'image générée est plus lâche, ce qui peut rendre la sortie plus variée par rapport au prompt

Vous pouvez utiliser strength et guidance_scale ensemble pour un meilleur contrôle sur l'expressivité du modèle. Par exemple, une combinaison de valeurs élevées de strength et de guidance_scale accorde au modèle la plus grande liberté créative.

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 négatif

Un prompt négatif joue le rôle inverse d’un prompt ; il guide le modèle pour l’empêcher de générer certains éléments dans une image. Cela est utile pour améliorer rapidement la qualité de l’image et empêcher le modèle de générer des éléments indésirables.

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"

Recadrage du masque de bourrage

Une méthode pour améliorer la qualité de l'image en inpainting consiste à utiliser le paramètre padding_mask_crop. Une fois activée, cette option recadre la zone masquée avec un certain padding spécifié par l'utilisateur et recadre également la même zone sur l'image d'origine. L'image et le masque sont ensuite mis à l'échelle vers une résolution plus élevée pour l'inpainting, puis superposés sur l'image d'origine. C'est une méthode rapide et simple pour améliorer la qualité de l'image sans utiliser un pipeline distinct comme StableDiffusionUpscalePipeline.

Ajoutez le paramètre padding_mask_crop à l'appel du pipeline et définissez-le sur la valeur de bourrage souhaitée.

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
image inpaint par défaut
inpaint image avec `padding_mask_crop` activé

Pipelines d'inpainting en chaîne

AutoPipelineForInpainting peut être enchaîné avec d’autres pipelines 🤗 Diffusers pour modifier leurs sorties. Cela est souvent utile pour améliorer la qualité des sorties de vos autres pipelines de diffusion, et si vous utilisez plusieurs pipelines, il peut être plus efficace en mémoire de les enchaîner afin de conserver les sorties dans l’espace latent et de réutiliser les mêmes composants de pipeline.

Texte-vers-image-vers-inpaint

Enchaîner un pipeline de génération d’image à partir de texte et un pipeline d’inpainting permet de retoucher l’image générée, sans avoir à fournir d’image de base au départ. Cela facilite la modification de vos sorties préférées de génération d’image à partir de texte, sans avoir à générer une image entièrement nouvelle.

Commencez par le pipeline texte-vers-image pour créer un château :

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]

Charger l’image du masque de la sortie ci-dessus :

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

Et procédons à l’inpainting de la zone masquée avec une cascade :

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)
texte-vers-image
inpaint

Inpaint-to-image-to-image

Vous pouvez également enchaîner un pipeline d'inpainting avant un autre pipeline, comme image-to-image ou un upscaler, afin d'améliorer la qualité.

Commencez par retoucher une image :

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))

Passons maintenant l’image à un autre pipeline d’inpainting avec le modèle refiner de SDXL pour améliorer les détails et la qualité de l’image :

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]

Il est important de spécifier output_type="latent" dans le pipeline pour conserver toutes les sorties dans l'espace latent et éviter une étape de décodage-encodage inutile. Cela ne fonctionne que si les pipelines enchaînés utilisent le même VAE. Par exemple, dans la section Text-to-image-to-inpaint, Kandinsky 2.2 utilise une classe de VAE différente de celle du modèle Stable Diffusion, ce qui l'empêche de fonctionner. En revanche, si vous utilisez Stable Diffusion v1.5 pour les deux pipelines, vous pouvez tout conserver dans l'espace latent car ils utilisent tous deux AutoencoderKL.

Enfin, vous pouvez passer cette image à un pipeline image-vers-image pour lui apporter les finitions. Il est plus efficace d’utiliser la méthode from_pipe() pour réutiliser les composants existants du pipeline et éviter de recharger inutilement tous les composants du pipeline en mémoire.

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)
image initiale
inpaint
image-vers-image

La génération d’image à partir d’image et l’inpainting sont en réalité des tâches très similaires. La génération d’image à partir d’image produit une nouvelle image qui ressemble à l’image fournie. L’inpainting fait la même chose, mais ne transforme que la zone de l’image définie par le masque, le reste de l’image restant inchangé. On peut considérer l’inpainting comme un outil plus précis pour effectuer des modifications spécifiques, tandis que la génération d’image à partir d’image offre un champ d’action plus large pour des modifications plus globales.

Contrôler la génération d'images

Obtenir une image qui correspond exactement à vos attentes est un défi, car le processus de débruitage est aléatoire. Bien que vous puissiez contrôler certains aspects de la génération en configurant des paramètres tels que negative_prompt, il existe des méthodes plus efficaces pour contrôler la génération d’images.

Pondération des prompts

Le pondération des prompts (prompt weighting) offre une méthode quantifiable pour ajuster la représentation des concepts dans un prompt. Vous pouvez l’utiliser pour augmenter ou diminuer l’amplitude du vecteur d’embedding de texte pour chaque concept du prompt, ce qui détermine ensuite la proportion de chaque concept généré. La bibliothèque Compel propose une syntaxe intuitive pour ajuster les poids des prompts et générer les embeddings. Découvrez comment créer les embeddings dans le guide Pondération des prompts.

Une fois que vous avez généré les embeddings, transmettez-les au paramètre prompt_embeds (et negative_prompt_embeds si vous utilisez un prompt négatif) dans AutoPipelineForInpainting. Les embeddings remplacent le paramètre 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

Les modèles ControlNet sont utilisés avec d'autres modèles de diffusion tels que Stable Diffusion, et ils offrent une méthode encore plus flexible et précise pour contrôler la génération d'une image. Un ControlNet accepte une image de conditionnement supplémentaire en entrée qui guide le modèle de diffusion afin de préserver les caractéristiques qu'elle contient.

Par exemple, conditionnons une image avec un ControlNet pré-entraîné sur des images d'inpainting :

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)

Générez maintenant une image à partir des images de base, de masque et de contrôle. Vous remarquerez que les caractéristiques de l'image de base sont fortement préservées dans l'image générée.

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)

Vous pouvez aller plus loin et l’enchaîner avec un pipeline image-vers-image pour appliquer un nouveau style :

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)
image initiale
ControlNet inpaint
image-vers-image

Optimiser

Exécuter des modèles de diffusion peut être difficile et lent si vos ressources sont limitées, mais quelques astuces d’optimisation peuvent y remédier. L’une des optimisations les plus importantes (et les plus simples) à activer consiste à passer à une attention efficace en mémoire. Si vous utilisez PyTorch 2.0, scaled-dot product attention est activée automatiquement et vous n’avez rien d’autre à faire. Pour les utilisateurs non-PyTorch 2.0, vous pouvez installer et utiliser l’implémentation d’attention efficace en mémoire de xFormers. Les deux options réduisent l’utilisation de la mémoire et accélèrent l’inférence.

Vous pouvez également décharger le modèle sur le CPU pour économiser encore plus de mémoire :

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

Pour accélérer encore davantage votre code d’inférence, utilisez torch_compile. Vous devez envelopper torch.compile autour du composant le plus intensif du pipeline, qui est généralement le UNet :

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

En savoir plus dans les guides Réduire l'utilisation de la mémoire et Accélérer l'inférence.

Update on GitHub