Buckets:
| # ControlNet | |
| [ControlNet](https://huggingface.co/papers/2302.05543) guide un modèle de diffusion préentraîné à l’aide d’une image de contrôle structurelle (contours, profondeur ou pose) tout en conservant un prompt texte. Il fige le modèle de base et ajoute un réseau parallèle dont les résidus orientent le débruiteur, offrant ainsi un contrôle de la mise en page sans réentraînement. | |
| Chargez un ControlNet adapté au contrôle dont vous avez besoin (par exemple canny), puis transmettez-le en tant que `controlnet=` à [from_pretrained()](/docs/diffusers/main/fr/api/pipelines/overview#diffusers.DiffusionPipeline.from_pretrained). Utilisez `controlnet_conditioning_scale` pour définir l’intensité avec laquelle le contrôle oriente la génération. | |
| > [!TIP] | |
| > Les ControlNets sont disponibles pour de nombreux modèles tels que [Flux](../api/pipelines/controlnet_flux), [Hunyuan-DiT](../api/pipelines/controlnet_hunyuandit), [Stable Diffusion 3](../api/pipelines/controlnet_sd3), et d'autres. Les exemples de ce guide utilisent Flux et Stable Diffusion XL. Pour T2I-Adapter sur les anciens points de contrôle de la famille Stable Diffusion, consultez [Legacy adapters](./legacy_adapters#t2i-adapter). Privilégiez ControlNet pour les nouveaux travaux de génération contrôlable. | |
| Les onglets ci-dessous présentent ControlNet pour la génération d'images à partir de texte, la transformation d'image en image et l'inpainting. | |
| Générer une image canny avec [opencv-python](https://github.com/opencv/opencv-python). | |
| ```py | |
| import cv2 | |
| import numpy as np | |
| from PIL import Image | |
| from diffusers.utils import load_image | |
| original_image = load_image( | |
| "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/non-enhanced-prompt.png" | |
| ) | |
| image = np.array(original_image) | |
| low_threshold = 100 | |
| high_threshold = 200 | |
| image = cv2.Canny(image, low_threshold, high_threshold) | |
| image = image[:, :, None] | |
| image = np.concatenate([image, image, image], axis=2) | |
| canny_image = Image.fromarray(image) | |
| ``` | |
| Transmettez l’image canny au pipeline. Utilisez le paramètre `controlnet_conditioning_scale` pour déterminer le poids à accorder au contrôle. | |
| ```py | |
| import torch | |
| from diffusers.utils import load_image | |
| from diffusers import FluxControlNetPipeline, FluxControlNetModel | |
| controlnet = FluxControlNetModel.from_pretrained( | |
| "InstantX/FLUX.1-dev-Controlnet-Canny", dtype=torch.bfloat16 | |
| ) | |
| pipeline = FluxControlNetPipeline.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", controlnet=controlnet, dtype=torch.bfloat16 | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| prompt = """ | |
| A photorealistic overhead image of a cat reclining sideways in a flamingo pool floatie holding a margarita. | |
| The cat is floating leisurely in the pool and completely relaxed and happy. | |
| """ | |
| pipeline( | |
| prompt, | |
| control_image=canny_image, | |
| controlnet_conditioning_scale=0.5, | |
| num_inference_steps=50, | |
| guidance_scale=3.5, | |
| ).images[0] | |
| ``` | |
| image d'origine | |
| image canny | |
| image générée | |
| Générer une carte de profondeur avec un pipeline d'estimation de profondeur de Transformers. | |
| ```py | |
| import torch | |
| import numpy as np | |
| from PIL import Image | |
| from transformers import DPTImageProcessor, DPTForDepthEstimation | |
| from diffusers import ControlNetModel, StableDiffusionXLControlNetImg2ImgPipeline, AutoencoderKL | |
| from diffusers.utils import load_image | |
| device = "cuda" # or "mps", "xpu", "cpu" | |
| depth_estimator = DPTForDepthEstimation.from_pretrained("Intel/dpt-hybrid-midas").to(device) | |
| feature_extractor = DPTImageProcessor.from_pretrained("Intel/dpt-hybrid-midas") | |
| def get_depth_map(image): | |
| image = feature_extractor(images=image, return_tensors="pt").pixel_values.to(device) | |
| with torch.no_grad(), torch.autocast(device): | |
| depth_map = depth_estimator(image).predicted_depth | |
| depth_map = torch.nn.functional.interpolate( | |
| depth_map.unsqueeze(1), | |
| size=(1024, 1024), | |
| mode="bicubic", | |
| align_corners=False, | |
| ) | |
| depth_min = torch.amin(depth_map, dim=[1, 2, 3], keepdim=True) | |
| depth_max = torch.amax(depth_map, dim=[1, 2, 3], keepdim=True) | |
| depth_map = (depth_map - depth_min) / (depth_max - depth_min) | |
| image = torch.cat([depth_map] * 3, dim=1) | |
| image = image.permute(0, 2, 3, 1).cpu().numpy()[0] | |
| image = Image.fromarray((image * 255.0).clip(0, 255).astype(np.uint8)) | |
| return image | |
| image = load_image( | |
| "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/non-enhanced-prompt.png" | |
| ).resize((1024, 1024)) | |
| depth_image = get_depth_map(image) | |
| ``` | |
| Transmettez la carte de profondeur au pipeline. Utilisez le paramètre `controlnet_conditioning_scale` pour déterminer le poids à accorder au contrôle. | |
| ```py | |
| controlnet = ControlNetModel.from_pretrained( | |
| "diffusers/controlnet-depth-sdxl-1.0-small", | |
| dtype=torch.float16, | |
| ) | |
| vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", dtype=torch.float16) | |
| pipeline = StableDiffusionXLControlNetImg2ImgPipeline.from_pretrained( | |
| "stabilityai/stable-diffusion-xl-base-1.0", | |
| controlnet=controlnet, | |
| vae=vae, | |
| dtype=torch.float16, | |
| ).to(device) | |
| prompt = """ | |
| A photorealistic overhead image of a cat reclining sideways in a flamingo pool floatie holding a margarita. | |
| The cat is floating leisurely in the pool and completely relaxed and happy. | |
| """ | |
| controlnet_conditioning_scale = 0.5 | |
| pipeline( | |
| prompt, | |
| image=image, | |
| control_image=depth_image, | |
| controlnet_conditioning_scale=controlnet_conditioning_scale, | |
| strength=0.99, | |
| num_inference_steps=100, | |
| ).images[0] | |
| ``` | |
| image d'origine | |
| carte de profondeur | |
| image générée | |
| Générez une image de masque qui indique quels pixels remplacer, puis transmettez-la en tant que `mask_image` avec l'image de contrôle. | |
| ```py | |
| import cv2 | |
| import torch | |
| import numpy as np | |
| from PIL import Image | |
| from diffusers.utils import load_image | |
| from diffusers import StableDiffusionXLControlNetInpaintPipeline, ControlNetModel | |
| init_image = load_image( | |
| "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/non-enhanced-prompt.png" | |
| ) | |
| init_image = init_image.resize((1024, 1024)) | |
| mask_image = load_image( | |
| "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/cat_mask.png" | |
| ) | |
| mask_image = mask_image.resize((1024, 1024)) | |
| def make_canny_condition(image): | |
| image = np.array(image) | |
| image = cv2.Canny(image, 100, 200) | |
| image = image[:, :, None] | |
| image = np.concatenate([image, image, image], axis=2) | |
| image = Image.fromarray(image) | |
| return image | |
| control_image = make_canny_condition(init_image) | |
| ``` | |
| Transmettez le masque et l’image de contrôle au pipeline. Utilisez le paramètre `controlnet_conditioning_scale` pour déterminer le poids à accorder au contrôle. | |
| ```py | |
| controlnet = ControlNetModel.from_pretrained( | |
| "diffusers/controlnet-canny-sdxl-1.0", dtype=torch.float16 | |
| ) | |
| pipeline = StableDiffusionXLControlNetInpaintPipeline.from_pretrained( | |
| "stabilityai/stable-diffusion-xl-base-1.0", controlnet=controlnet, dtype=torch.float16 | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| pipeline( | |
| "a cute and fluffy bunny rabbit", | |
| num_inference_steps=100, | |
| strength=0.99, | |
| controlnet_conditioning_scale=0.5, | |
| image=init_image, | |
| mask_image=mask_image, | |
| control_image=control_image, | |
| ).images[0] | |
| ``` | |
| image d'origine | |
| masque d'image | |
| image générée | |
| ## Multi-ControlNet | |
| Composez plusieurs ControlNets (par exemple canny + depth) en les passant sous forme de liste. Masquez les régions qui se chevauchent lorsque c’est possible, et ajustez chaque `controlnet_conditioning_scale`. Construisez `canny_image` avec OpenCV Canny (comme pour le texte-vers-image) et `depth_image` avec DPT (comme pour l’image-vers-image). Redimensionnez chaque image de contrôle à la taille du pipeline avant d’appeler le pipeline. | |
| ```py | |
| import cv2 | |
| import torch | |
| import numpy as np | |
| from PIL import Image | |
| from transformers import DPTImageProcessor, DPTForDepthEstimation | |
| from diffusers import StableDiffusionXLControlNetPipeline, ControlNetModel, AutoencoderKL | |
| from diffusers.utils import load_image | |
| original_image = load_image( | |
| "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/non-enhanced-prompt.png" | |
| ) | |
| image = np.array(original_image) | |
| canny_image = Image.fromarray( | |
| np.concatenate([cv2.Canny(image, 100, 200)[:, :, None]] * 3, axis=2) | |
| ) | |
| device = "cuda" # or "mps", "xpu", "cpu" | |
| depth_estimator = DPTForDepthEstimation.from_pretrained("Intel/dpt-hybrid-midas").to(device) | |
| feature_extractor = DPTImageProcessor.from_pretrained("Intel/dpt-hybrid-midas") | |
| def get_depth_map(image): | |
| image = feature_extractor(images=image, return_tensors="pt").pixel_values.to(device) | |
| with torch.no_grad(), torch.autocast(device): | |
| depth_map = depth_estimator(image).predicted_depth | |
| depth_map = torch.nn.functional.interpolate( | |
| depth_map.unsqueeze(1), | |
| size=(1024, 1024), | |
| mode="bicubic", | |
| align_corners=False, | |
| ) | |
| depth_min = torch.amin(depth_map, dim=[1, 2, 3], keepdim=True) | |
| depth_max = torch.amax(depth_map, dim=[1, 2, 3], keepdim=True) | |
| depth_map = (depth_map - depth_min) / (depth_max - depth_min) | |
| image = torch.cat([depth_map] * 3, dim=1) | |
| image = image.permute(0, 2, 3, 1).cpu().numpy()[0] | |
| image = Image.fromarray((image * 255.0).clip(0, 255).astype(np.uint8)) | |
| return image | |
| depth_image = get_depth_map(original_image.resize((1024, 1024))) | |
| controlnets = [ | |
| ControlNetModel.from_pretrained( | |
| "diffusers/controlnet-canny-sdxl-1.0", dtype=torch.float16 | |
| ), | |
| ControlNetModel.from_pretrained( | |
| "diffusers/controlnet-depth-sdxl-1.0-small", dtype=torch.float16 | |
| ), | |
| ] | |
| vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", dtype=torch.float16) | |
| pipeline = StableDiffusionXLControlNetPipeline.from_pretrained( | |
| "stabilityai/stable-diffusion-xl-base-1.0", controlnet=controlnets, vae=vae, dtype=torch.float16 | |
| ).to(device) | |
| prompt = """ | |
| a relaxed rabbit sitting on a striped towel next to a pool with a tropical drink nearby, | |
| bright sunny day, vacation scene, 35mm photograph, film, professional, 4k, highly detailed | |
| """ | |
| negative_prompt = "lowres, bad anatomy, worst quality, low quality, deformed, ugly" | |
| images = [canny_image.resize((1024, 1024)), depth_image.resize((1024, 1024))] | |
| pipeline( | |
| prompt, | |
| negative_prompt=negative_prompt, | |
| image=images, | |
| num_inference_steps=100, | |
| controlnet_conditioning_scale=[0.5, 0.5], | |
| ).images[0] | |
| ``` | |
| image canny | |
| carte de profondeur | |
| image générée | |
| ## Mode de devinette | |
| [Mode de devinette](https://github.com/lllyasviel/ControlNet/discussions/188) génère une image à partir d'un seul contrôle lorsque vous n'avez pas (ou ne souhaitez pas) de prompt texte. Il met à l'échelle les résidus de ControlNet en fonction de la profondeur des blocs, passant d'environ `0.1` dans les blocs de descente initiaux jusqu'à `1.0` au bloc intermédiaire. Cela empêche les couches initiales de sur-contraindre, tout en permettant aux blocs plus profonds de porter la structure. | |
| ```py | |
| import torch | |
| from diffusers.utils import load_image | |
| from diffusers import StableDiffusionXLControlNetPipeline, ControlNetModel | |
| controlnet = ControlNetModel.from_pretrained( | |
| "diffusers/controlnet-canny-sdxl-1.0", dtype=torch.float16 | |
| ) | |
| pipeline = StableDiffusionXLControlNetPipeline.from_pretrained( | |
| "stabilityai/stable-diffusion-xl-base-1.0", | |
| controlnet=controlnet, | |
| dtype=torch.float16 | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| canny_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/canny-cat.png") | |
| pipeline( | |
| "", | |
| image=canny_image, | |
| guess_mode=True | |
| ).images[0] | |
| ``` | |
| image canny | |
| image générée | |
Xet Storage Details
- Size:
- 12 kB
- Xet hash:
- c6a26497a5a9febaba3b71db7e91411930959f770201f382fcb16d6aacc814d5
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.