InstantStyle:在文本到图像生成中保持风格的免费午餐

instantX-research/InstantStyle

InstantStyle: Free Lunch towards Style-Preserving in Text-to-Image Generation 🔥 instantstyle.github.io/ 1.8k stars 110 forks Branches Tags Activity Star 通知 您必须登录才能更改通知设置

其他导航选项

instantX-research/InstantStyle

main

BranchesTags 转到文件 代码

文件夹和文件

| 名称 | 名称 | 最近提交消息 | 最近提交日期 | | ----------- | ----------- | -------- | -------- | | assets | assets | | | | gradio_demo | gradio_demo | | | | ip_adapter | ip_adapter | | | | notebooks | notebooks | | | | README.md | README.md | | | | attn_blocks.py | attn_blocks.py | | | | attn_blocks_sd15.py | attn_blocks_sd15.py | | | | infer_style.py | infer_style.py | | | | infer_style_controlnet.py | infer_style_controlnet.py | | | | infer_style_inpainting.py | infer_style_inpainting.py | | | | infer_style_plus.py | infer_style_plus.py | | | | infer_style_sd15.py | infer_style_sd15.py | | |

查看所有文件

最新提交

历史记录

84 次提交

仓库文件导航

InstantStyle:在文本到图像生成中保持风格的免费午餐

Haofan Wang * · Matteo Spinelli · Qixun Wang · Xu Bai · Zekui Qin · Anthony Chen InstantX Team *corresponding authors

Hugging Face ModelScope GitHub

InstantStyle 是一个通用框架,它采用了两种简单但功能强大的技术,可实现从参考图像中有效分离风格和内容。

原理

从图像中分离内容。得益于对 CLIP 全局特征的良好表征,从图像特征中减去内容文本特征后,可以显式地解耦风格和内容。虽然简单,但此策略在减轻内容泄漏方面非常有效。

仅注入到风格块中。根据经验,深度网络的每一层都捕获不同的语义信息,我们工作中的关键观察结果是存在两个特定的注意力层来处理风格。具体来说,我们发现 up blocks.0.attentions.1down blocks.2.attentions.1 分别捕获风格(颜色、材质、氛围)和空间布局(结构、构图)。

发布

演示

风格化合成

基于图像的风格化合成

与先前工作的比较

下载

按照 IP-Adapter这里下载预训练的检查点。

git clone https://github.com/InstantStyle/InstantStyle.git
cd InstantStyle
# 下载模型
git lfs install
git clone https://huggingface.co/h94/IP-Adapter
mv IP-Adapter/models models
mv IP-Adapter/sdxl_models sdxl_models

用法

我们的方法与 IP-Adapter 完全兼容。 对于特征减法,它仅适用于全局特征而不是补丁特征。 对于 SD1.5,您可以在 infer_style_sd15.py 中找到演示,但我们发现 SD1.5 对风格信息的感知和理解较弱,因此该演示仅用于实验目的。 所有块名称都可以在 attn_blocks.pyattn_blocks_sd15.py 中找到,分别用于 SDXL 和 SD1.5。

import torch
from diffusers import StableDiffusionXLPipeline
from PIL import Image
from ip_adapter import IPAdapterXL
base_model_path = "stabilityai/stable-diffusion-xl-base-1.0"
image_encoder_path = "sdxl_models/image_encoder"
ip_ckpt = "sdxl_models/ip-adapter_sdxl.bin"
device = "cuda"
# 加载 SDXL pipeline
pipe = StableDiffusionXLPipeline.from_pretrained(
  base_model_path,
  torch_dtype=torch.float16,
  add_watermarker=False,
)
# 减少内存消耗
pipe.enable_vae_tiling()
# 加载 ip-adapter
# target_blocks=["block"] 用于原始 IP-Adapter
# target_blocks=["up_blocks.0.attentions.1"] 仅用于风格块
# target_blocks = ["up_blocks.0.attentions.1", "down_blocks.2.attentions.1"] # 用于风格+布局块
ip_model = IPAdapterXL(pipe, image_encoder_path, ip_ckpt, device, target_blocks=["up_blocks.0.attentions.1"])
image = "./assets/0.jpg"
image = Image.open(image)
image.resize((512, 512))
# 仅使用图像提示生成图像变体
images = ip_model.generate(pil_image=image,
              prompt="a cat, masterpiece, best quality, high quality",
              negative_prompt= "text, watermark, lowres, low quality, worst quality, deformed, glitch, low contrast, noisy, saturation, blurry",
              scale=1.0,
              guidance_scale=5,
              num_samples=1,
              num_inference_steps=30, 
              seed=42,
              #neg_content_prompt="a rabbit",
              #neg_content_scale=0.5,
             )
images[0].save("result.png")

在 diffusers 中使用

InstantStyle 已经集成到 diffusers 中 (请确保您已安装 diffusers>=0.28.0.dev0),从而大大简化了用法。 您现在可以使用 set_ip_adapter_scale() 方法控制每个 IP-Adapter 的 per-transformer 行为,使用如下所示的配置字典:

from diffusers import StableDiffusionXLPipeline
from PIL import Image
import torch
# 加载 SDXL pipeline
pipe = StableDiffusionXLPipeline.from_pretrained(
  "stabilityai/stable-diffusion-xl-base-1.0",
  torch_dtype=torch.float16,
  add_watermarker=False,
)
# 加载 ip-adapter
pipe.load_ip_adapter("h94/IP-Adapter", subfolder="sdxl_models", weight_name="ip-adapter_sdxl.bin")
pipe.enable_vae_tiling()
# 配置 ip-adapter 缩放。
scale = {
  "down": {"block_2": [0.0, 1.0]},
  "up": {"block_0": [0.0, 1.0, 0.0]},
}
pipeline.set_ip_adapter_scale(scale)

在此示例中。 我们在 down-part 的第二个 transformer,block 2 和 up-part 的第二个,block 0 中为 IP-Adapter 设置了 scale=1.0。 请注意,down-part block 2 中有 2 个 transformer,因此列表的长度为 2,up-part block 0 也是如此。 其余的 IP-Adapter 将具有零缩放,这意味着在所有其他层中禁用它们。

借助 set_ip_adapter_scale(),我们现在可以配置 IP-Adapter,而无需每次想要测试 IP-Adapter 行为时都重新加载它们。

# 用于原始 IP-Adapter
scale = 1.0
pipeline.set_ip_adapter_scale(scale)
# 仅用于风格块
scale = {
  "up": {"block_0": [0.0, 1.0, 0.0]},
}
pipeline.set_ip_adapter_scale(scale)

带有掩码的多个 IP-Adapter 图像

您还可以加载多个 IP-Adapter,以及带有掩码的多个 IP-Adapter 图像,以更精确地控制布局,就像 IP-Adapter 中那样。

from diffusers import StableDiffusionXLPipeline
from diffusers.image_processor import IPAdapterMaskProcessor
from transformers import CLIPVisionModelWithProjection
from PIL import Image
import torch
image_encoder = CLIPVisionModelWithProjection.from_pretrained(
  "h94/IP-Adapter", subfolder="models/image_encoder", torch_dtype=torch.float16
).to("cuda")
pipe = StableDiffusionXLPipeline.from_pretrained(
  "RunDiffusion/Juggernaut-XL-v9", torch_dtype=torch.float16, image_encoder=image_encoder, variant="fp16"
).to("cuda")
pipe.load_ip_adapter(
  ["ostris/ip-composition-adapter", "h94/IP-Adapter"],
  subfolder=["", "sdxl_models"],
  weight_name=[
    "ip_plus_composition_sdxl.safetensors",
    "ip-adapter_sdxl_vit-h.safetensors",
  ],
  image_encoder_folder=None,
)
scale_1 = {
  "down": [[0.0, 0.0, 1.0]],
  "mid": [[0.0, 0.0, 1.0]],
  "up": {"block_0": [[0.0, 0.0, 1.0], [1.0, 1.0, 1.0], [0.0, 0.0, 1.0]], "block_1": [[0.0, 0.0, 1.0]]},
}
# 在模型的每个地方激活第一个 IP-Adapter,
# 为每个屏蔽的输入配置第二个,以进行精确的风格控制。
pipe.set_ip_adapter_scale([1.0, scale_1])
processor = IPAdapterMaskProcessor()
female_mask = Image.open("./assets/female_mask.png")
male_mask = Image.open("./assets/male_mask.png")
background_mask = Image.open("./assets/background_mask.png")
composition_mask = Image.open("./assets/composition_mask.png")
mask1 = processor.preprocess([composition_mask], height=1024, width=1024)
mask2 = processor.preprocess([female_mask, male_mask, background_mask], height=1024, width=1024)
mask2 = mask2.reshape(1, mask2.shape[0], mask2.shape[2], mask2.shape[3])  # output -> (1, 3, 1024, 1024)
ip_female_style = Image.open("./assets/ip_female_style.png")
ip_male_style = Image.open("./assets/ip_male_style.png")
ip_background = Image.open("./assets/ip_background.png")
ip_composition_image = Image.open("./assets/ip_composition_image.png")
image = pipe(
  prompt="high quality, cinematic photo, cinemascope, 35mm, film grain, highly detailed",
  negative_prompt="",
  ip_adapter_image=[ip_composition_image, [ip_female_style, ip_male_style, ip_background]],
  cross_attention_kwargs={"ip_adapter_masks": [mask1, mask2]},
  guidance_scale=6.5,
  num_inference_steps=25,
).images[0]
image

高分辨率生成

我们使用 HiDiffusion 无缝生成高分辨率图像,您可以通过 pip install hidiffusion 安装。

from hidiffusion import apply_hidiffusion, remove_hidiffusion
# 减少内存消耗
pipe.enable_vae_tiling()
# 通过单行代码应用 hidiffusion。
apply_hidiffusion(pipe)
...
# 以更高的分辨率生成图像
images = ip_model.generate(pil_image=image,
              prompt="a cat, masterpiece, best quality, high quality",
              negative_prompt= "text, watermark, lowres, low quality, worst quality, deformed, glitch, low contrast, noisy, saturation, blurry",
              scale=1.0,
              guidance_scale=5,
              num_samples=1,
              num_inference_steps=30, 
              seed=42,
              height=2048,
              width=2048
             )

分布式推理

在分布式设置中,您可以使用 🤗 Accelerate 或 PyTorch Distributed 在多个 GPU 上运行推理,这对于并行生成多个提示非常有用,以防每个 GPU 上的 VRAM 有限。 更多