Diffusers documentation

IP-Adapter

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