Diffusers documentation

IP-Adapter

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.43.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

IP-Adapter

IP-Adapter управляет предобученной диффузионной моделью с помощью опорного изображения, при этом текстовый промпт сохраняется. Базовая модель замораживается, а добавляется небольшой набор слоёв кросс-внимания для изображений, что делает метод практичным для соответствия объекту или стилю с фотографии без дообучения.

text prompt                         reference image
    |                                     |
 text encoder                        image encoder
    |                                     |
    v                                     v
 text cross-attn  (frozen)          IP-Adapter cross-attn
    \                                     /
     \                                   /
      +-------->  denoiser  <-----------+
                  (frozen base)

Чекпоинты IP-Adapter обычно занимают ~100 МБ, так как хранят веса адаптера, а не полную модель. Сначала загрузите базовый пайплайн, затем загрузите адаптер с помощью load_ip_adapter().

IP-Adapters доступны для многих моделей, таких как Flux и Stable Diffusion 3, и других. В примерах этого руководства используются Stable Diffusion и Stable Diffusion XL.

Используйте set_ip_adapter_scale(), чтобы управлять силой воздействия IP-Adapter на генерацию. Значение 1.0 применяет адаптер на полную силу; 0.5 обычно обеспечивает баланс между текстовым и изображением-промптом.

Приведённые ниже примеры демонстрируют работу IP-Adapter на типовых задачах.

text-to-image
image-to-image
inpainting
video
import torch
from diffusers import AutoPipelineForText2Image
from diffusers.utils import load_image

pipeline = AutoPipelineForText2Image.from_pretrained(
  "stabilityai/stable-diffusion-xl-base-1.0",
  dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_ip_adapter(
  "h94/IP-Adapter",
  subfolder="sdxl_models",
  weight_name="ip-adapter_sdxl.bin"
)
pipeline.set_ip_adapter_scale(0.8)

Передайте изображение в ip_adapter_image вместе с текстовым запросом, чтобы сгенерировать изображение.

image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/ip_adapter_diner.png")
pipeline(
    prompt="a polar bear sitting in a chair drinking a milkshake",
    ip_adapter_image=image,
    negative_prompt="deformed, ugly, wrong proportion, low res, bad anatomy, worst quality, low quality",
).images[0]
IP-Adapter image
Изображение IP-Adapter
generated image
сгенерированное изображение

Варианты контрольных точек

Загружайте Plus, когда детали с референсного изображения имеют наибольшее значение. Загружайте FaceID, когда вам нужны эмбеддинги идентичности InsightFace, а не эмбеддинги изображений CLIP.

IP-Adapter Plus
IP-Adapter FaceID
import torch
from transformers import CLIPVisionModelWithProjection
from diffusers import AutoPipelineForText2Image

image_encoder = CLIPVisionModelWithProjection.from_pretrained(
    "h94/IP-Adapter",
    subfolder="models/image_encoder",
    dtype=torch.float16
)

pipeline = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    image_encoder=image_encoder,
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"

pipeline.load_ip_adapter(
  "h94/IP-Adapter",
  subfolder="sdxl_models",
  weight_name="ip-adapter-plus_sdxl_vit-h.safetensors"
)

Встраивания изображений

prepare_ip_adapter_image_embeds() кодирует изображения IP-Adapter в эмбеддинги, которые можно сохранить и переиспользовать. Вычислите их один раз, вместо того чтобы каждый запуск пайплайна загружать и кодировать одни и те же изображения заново.

import torch
from diffusers import AutoPipelineForText2Image
from diffusers.utils import load_image

pipeline = AutoPipelineForText2Image.from_pretrained(
  "stabilityai/stable-diffusion-xl-base-1.0",
  dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_ip_adapter(
  "h94/IP-Adapter",
  subfolder="sdxl_models",
  weight_name="ip-adapter_sdxl.bin"
)

image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/ip_adapter_bear_1.png")
image_embeds = pipeline.prepare_ip_adapter_image_embeds(
    ip_adapter_image=image,
    ip_adapter_image_embeds=None,
    device="cuda",
    num_images_per_prompt=1,
    do_classifier_free_guidance=True,
)

torch.save(image_embeds, "image_embeds.ipadpt")

Перезагрузите эмбеддинги изображений, передав их в параметр ip_adapter_image_embeds. Установите image_encoder_folder в None, так как для генерации эмбеддингов изображений кодировщик изображений больше не требуется.

Вы также можете загружать эмбеддинги изображений из других источников, таких как ComfyUI.

pipeline = AutoPipelineForText2Image.from_pretrained(
  "stabilityai/stable-diffusion-xl-base-1.0",
  dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_ip_adapter(
  "h94/IP-Adapter",
  subfolder="sdxl_models",
  image_encoder_folder=None,
  weight_name="ip-adapter_sdxl.bin"
)
pipeline.set_ip_adapter_scale(0.8)
image_embeds = torch.load("image_embeds.ipadpt")
pipeline(
    prompt="a polar bear sitting in a chair drinking a milkshake",
    ip_adapter_image_embeds=image_embeds,
    negative_prompt="deformed, ugly, wrong proportion, low res, bad anatomy, worst quality, low quality",
    num_inference_steps=100,
).images[0]

Маскирование

Двоичное маскирование позволяет назначить изображение IP-Adapter на конкретную область выходного изображения, что делает его полезным для композиции нескольких изображений IP-Adapter. Каждое изображение IP-Adapter требует двоичной маски.

Загрузите IPAdapterMaskProcessor для предварительной обработки масок изображений. Для получения наилучших результатов укажите выходные значения height и width, чтобы маски с различными соотношениями сторон были корректно масштабированы. Если входные маски уже соответствуют соотношению сторон генерируемого изображения, задавать height и width не требуется.

import torch
from diffusers import AutoPipelineForText2Image
from diffusers.image_processor import IPAdapterMaskProcessor
from diffusers.utils import load_image

pipeline = AutoPipelineForText2Image.from_pretrained(
  "stabilityai/stable-diffusion-xl-base-1.0",
  dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"

mask1 = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/ip_mask_mask1.png")
mask2 = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/ip_mask_mask2.png")

processor = IPAdapterMaskProcessor()
masks = processor.preprocess([mask1, mask2], height=1024, width=1024)
mask 1
mask 1
mask 2
mask 2

Передавайте изображения IP-Adapter и их масштабы в виде списка. Передайте предобработанные маски в cross_attention_kwargs в пайплайне.

face_image1 = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/ip_mask_girl1.png")
face_image2 = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/ip_mask_girl2.png")

pipeline.load_ip_adapter(
  "h94/IP-Adapter",
  subfolder="sdxl_models",
  weight_name=["ip-adapter-plus-face_sdxl_vit-h.safetensors"]
)
pipeline.set_ip_adapter_scale([[0.7, 0.7]])

ip_images = [[face_image1, face_image2]]
masks = [masks.reshape(1, masks.shape[0], masks.shape[2], masks.shape[3])]

pipeline(
  prompt="2 girls",
  ip_adapter_image=ip_images,
  negative_prompt="monochrome, lowres, bad anatomy, worst quality, low quality",
  cross_attention_kwargs={"ip_adapter_masks": masks}
).images[0]
IP-Adapter image 1
Изображение 1 IP-Adapter
IP-Adapter image 2
Изображение 2 IP-Adapter
Generated image with mask
сгенерировано с маской
Generated image without mask
сгенерировано без маски

Рецепты

Сочетайте IP-Adapter с другими адаптерами или конвейерами, например с несколькими адаптерами, ControlNet, InstantStyle или few-step LCM, когда одного референсного изображения недостаточно.

Несколько IP-адаптеров

Соединяйте несколько IP-Adapters, чтобы генерировать изображения в более разнообразных стилях. Например, вы можете использовать IP-Adapter Face для создания согласованных лиц и персонажей, а IP-Adapter Plus — для генерации этих лиц в конкретных стилях.

Загрузите кодировщик изображений с помощью CLIPVisionModelWithProjection.

import torch
from diffusers import AutoPipelineForText2Image, DDIMScheduler
from transformers import CLIPVisionModelWithProjection
from diffusers.utils import load_image

image_encoder = CLIPVisionModelWithProjection.from_pretrained(
    "h94/IP-Adapter",
    subfolder="models/image_encoder",
    dtype=torch.float16,
)

Загрузите базовую модель, планировщик и следующие IP-адаптеры.

  • ip-adapter-plus_sdxl_vit-h использует патч-эмбеддинги и ViT-H-кодировщик изображений
  • ip-adapter-plus-face_sdxl_vit-h использует patch embeddings и ViT-H image encoder, но работает с изображениями обрезанных лиц
pipeline = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16,
    image_encoder=image_encoder,
)
pipeline.scheduler = DDIMScheduler.from_config(pipeline.scheduler.config)
pipeline.load_ip_adapter(
  "h94/IP-Adapter",
  subfolder="sdxl_models",
  weight_name=["ip-adapter-plus_sdxl_vit-h.safetensors", "ip-adapter-plus-face_sdxl_vit-h.safetensors"]
)
pipeline.set_ip_adapter_scale([0.7, 0.3])
# enable_model_cpu_offload to reduce memory usage
pipeline.enable_model_cpu_offload()

Загрузите изображение и папку с изображениями в определённом стиле, который нужно применить.

face_image = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/women_input.png")
style_folder = "https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/style_ziggy"
style_images = [load_image(f"{style_folder}/img{i}.png") for i in range(10)]
Face image
изображение лица
Style images
style images

Передавайте изображения стиля и лица в виде списка в ip_adapter_image.

generator = torch.Generator(device="cpu").manual_seed(0)

pipeline(
    prompt="wonderwoman",
    ip_adapter_image=[style_images, face_image],
    negative_prompt="monochrome, lowres, bad anatomy, worst quality, low quality",
).images[0]
Generated image
сгенерированное изображение

Структурное управление

Для структурного управления комбинируйте IP-Adapter с ControlNet, использующим карты глубины, карты контуров, оценки позы и другие условия.

Пример ниже загружает чекпоинт ControlNetModel, использующий карты глубины в качестве условия, и объединяет его с IP-Adapter.

import torch
from diffusers.utils import load_image
from diffusers import StableDiffusionControlNetPipeline, ControlNetModel

controlnet = ControlNetModel.from_pretrained(
  "lllyasviel/control_v11f1p_sd15_depth",
  dtype=torch.float16
)

pipeline = StableDiffusionControlNetPipeline.from_pretrained(
    "stable-diffusion-v1-5/stable-diffusion-v1-5",
    controlnet=controlnet,
    dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_ip_adapter(
  "h94/IP-Adapter",
  subfolder="models",
  weight_name="ip-adapter_sd15.bin"
)

Передайте карту глубины и изображение IP-Adapter в конвейер.

depth_map = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/depth.png")
ip_adapter_image = load_image("https://huggingface.co/datasets/YiYiXu/testing-images/resolve/main/statue.png")
pipeline(
  prompt="best quality, high quality",
  image=depth_map,
  ip_adapter_image=ip_adapter_image,
  negative_prompt="monochrome, lowres, bad anatomy, worst quality, low quality",
).images[0]
IP-Adapter image
Изображение IP-Adapter
Depth map
карта глубины
Generated image
сгенерированное изображение

Управление стилем и макетом

Для управления стилем и компоновкой комбинируйте IP-Adapter с InstantStyle. InstantStyle разделяет стиль (цвет, текстуру, общее ощущение) и содержание, применяя стиль только в блоках, специфичных для стиля, чтобы области с содержанием оставались нетронутыми. Это обеспечивает более высокую согласованность стиля и более чёткий контроль над компоновкой.

Активируйте IP-Adapter только в выбранных слоях с помощью set_ip_adapter_scale(). В примере ниже он включается в нижнем блоке block_2 (layout) и верхнем блоке block_0 (style) модели.

import torch
from diffusers import AutoPipelineForText2Image
from diffusers.utils import load_image

pipeline = AutoPipelineForText2Image.from_pretrained(
  "stabilityai/stable-diffusion-xl-base-1.0",
  dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_ip_adapter(
  "h94/IP-Adapter",
  subfolder="sdxl_models",
  weight_name="ip-adapter_sdxl.bin"
)

scale = {
    "down": {"block_2": [0.0, 1.0]},
    "up": {"block_0": [0.0, 1.0, 0.0]},
}
pipeline.set_ip_adapter_scale(scale)

Загрузите изображение стиля и сгенерируйте изображение.

style_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/0052a70beed5bf71b92610a43a52df6d286cd5f3/diffusers/rabbit.jpg")

pipeline(
    prompt="a cat, masterpiece, best quality, high quality",
    ip_adapter_image=style_image,
    negative_prompt="text, watermark, lowres, low quality, worst quality, deformed, glitch, low contrast, noisy, saturation, blurry",
    guidance_scale=5,
).images[0]
Style image
style image
Generated image
сгенерированное изображение

На рисунках ниже сравнивается активация только стиля в InstantStyle (до block_0) с включением IP-Adapter во всех слоях. Режим со всеми слоями обычно сильнее следует изображению-промпту и может снижать разнообразие. Предпочитайте масштаб только стиля, если вам нужно поведение InstantStyle, сохраняющее компоновку.

Не обязательно указывать все слои в словаре scale. Слои, которые не включены, получают значение 0, что означает отключение IP-Adapter.

scale = {
    "up": {"block_0": [0.0, 1.0, 0.0]},
}
pipeline.set_ip_adapter_scale(scale)

pipeline(
    prompt="a cat, masterpiece, best quality, high quality",
    ip_adapter_image=style_image,
    negative_prompt="text, watermark, lowres, low quality, worst quality, deformed, glitch, low contrast, noisy, saturation, blurry",
    guidance_scale=5,
).images[0]
Generated image (style only)
только стиль (up block_0)
Generated image (all layers)
все слои

Мгновенная генерация

Сочетайте IP-Adapter с LoRA LCM для генерации за несколько шагов.

import torch
from diffusers import DiffusionPipeline, LCMScheduler
from diffusers.utils import load_image

pipeline = DiffusionPipeline.from_pretrained(
  "sd-dreambooth-library/herge-style",
  dtype=torch.float16
)
pipeline.load_ip_adapter(
  "h94/IP-Adapter",
  subfolder="models",
  weight_name="ip-adapter_sd15.bin"
)
pipeline.load_lora_weights("latent-consistency/lcm-lora-sdv1-5")
pipeline.scheduler = LCMScheduler.from_config(pipeline.scheduler.config)
pipeline.enable_model_cpu_offload()

pipeline.set_ip_adapter_scale(0.4)
ip_adapter_image = load_image("https://user-images.githubusercontent.com/24734142/266492875-2d50d223-8475-44f0-a7c6-08b51cb53572.png")
pipeline(
    prompt="herge_style woman in armor, best quality, high quality",
    ip_adapter_image=ip_adapter_image,
    num_inference_steps=4,
    guidance_scale=1,
).images[0]
Generated image
сгенерированное изображение
Update on GitHub