ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

使用 Diffusers 中的 T2I-Adapter 实现可控图像生成:单控制与多控制组合实战指南

使用 Diffusers 中的 T2I-Adapter 实现可控图像生成:单控制与多控制组合实战指南 使用 Diffusers 中的 T2I-Adapter 实现可控图像生成单控制与多控制组合实战指南【免费下载链接】diffusers Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers导读本文以 Diffusers 官方文档 t2i_adapter.md 为核心系统讲解 T2I-AdapterText-to-Image Adapter这一轻量级可控生成方案如何在 Stable Diffusion XLSDXL之上接入 Canny 边缘、深度图等控制信号实现像 ControlNet 一样的可控生成以及如何使用MultiAdapter将多个控制信号如 Canny 边缘 深度图组合使用并通过adapter_conditioning_scale精细调节每个控制的权重。读完本文你将掌握从控制图预处理、Adapter 加载、Pipeline 装配到多控制加权调参的完整实战能力并了解其底层 ResNet 特征提取架构与注入 UNet 的原理。T2I-Adapter 是什么与 ControlNet 并列的轻量可控方案T2I-Adapter论文 T2I-Adapter: Learning Adapters to Dig out More Controllable Ability for Text-to-Image Diffusion Models 类似的、为扩散模型带来可控生成能力的适配器。它的核心思路是学习一个控制信号例如深度图 depth map与预训练模型内部知识之间的映射mapping。这个 Adapter 以插件方式插入基础模型在生成过程中依据控制信号额外提供引导从而约束生成结果的空间结构、边缘轮廓等几何属性而无需重新训练庞大的基础模型。从实现层面看两者在 UNet 内部的注入方式是一致的无论是 T2I-Adapter 还是 ControlNet最终都以down_block_additional_residuals的形式把额外残差特征传入 UNet 的每个下采样块。这一注入点可以在 unet_2d_condition.py 的forward中看到该文件同时兼容两种机制并对过时的传参方式给出了弃用警告。区别在于ControlNet额外维护一个可训练的 UNet 副本作为条件编码器参数规模大T2I-Adapter采用一个轻量的 ResNet 风格网络见 adapter.py 中的FullAdapter/FullAdapterXL/LightAdapter参数量小、内存占用低适合在移动端、低显存设备上运行。从代码结构看T2I-Adapter 在 Diffusers 仓库中的核心实现位于 adapter.py相关 Pipeline 位于 pipelines/t2i_adapter 目录。快速上手Canny 边缘控制的端到端示例第 1 步加载 T2I-Adapter针对某种特定控制信号如 Canny 边缘用T2IAdapter.from_pretrained加载对应的预训练 Adapter并传入dtypetorch.float16以半精度加载降低显存占用import torch from diffusers import T2IAdapter, StableDiffusionXLAdapterPipeline, AutoencoderKL t2i_adapter T2IAdapter.from_pretrained( TencentARC/t2i-adapter-canny-sdxl-1.0, dtypetorch.float16, )说明T2IAdapter继承自ModelMixin与ConfigMixin见 adapter.py 第 220 行因此支持from_pretrained/save_pretrained等标准接口。加载时会根据模型配置自动选择full_adapter、full_adapter_xl或light_adapter三种架构之一若需显式指定例如加载 sketch 类 SDXL 适配器也可在from_pretrained中传入adapter_typefull_adapter_xl。第 2 步用 OpenCV 生成 Canny 控制图使用 opencv-python 从原始图片提取边缘得到 Canny 图作为控制信号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], axis2) canny_image Image.fromarray(image)要点说明low_threshold/high_threshold示例取值 100 / 200是 Canny 算法的双阈值低于low_threshold的梯度一律丢弃高于high_threshold的梯度确定为边缘介于两者之间且与强边缘相连的梯度也会保留。调低阈值会得到更多、更细碎的边缘调高则只保留显著轮廓。Canny 输出是单通道灰度图需先扩成 3 通道image[:, :, None]后沿通道轴拼接 3 次以匹配 Adapter 默认的in_channels3输入。第 3 步装配 Pipeline 并生成图像将 Adapter 与一个 FP16 优化的 VAE 一起传入StableDiffusionXLAdapterPipeline.from_pretrainedvae AutoencoderKL.from_pretrained(madebyollin/sdxl-vae-fp16-fix, dtypetorch.float16) pipeline StableDiffusionXLAdapterPipeline.from_pretrained( stabilityai/stable-diffusion-xl-base-1.0, adaptert2i_adapter, vaevae, dtypetorch.float16, ).to(cuda) # or mps, xpu, cpu随后把 Canny 图通过image参数传入执行生成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, imagecanny_image, num_inference_steps100, guidance_scale10, ).images[0]关键参数参考来自 pipeline_stable_diffusion_xl_adapter.py 的__call__签名参数默认值作用num_inference_steps50去噪步数越多质量越高但更慢示例用 100 追求更精细的纹理guidance_scale5.0无分类器引导CFG强度1 生效越大越贴合文本提示但过大会牺牲画质adapter_conditioning_scale1.0Adapter 输出的加权系数控制信号强度后文详解adapter_conditioning_factor1.0可传 0~1 的小数在去噪早期逐步淡出控制信号的强度negative_promptNone负向提示词配合 CFG 使用以规避不良内容height/widthUNet 采样尺寸 × VAE 缩放系数输出分辨率SDXL 建议不低于 512denoising_endNone提前终止去噪的比例0~1用于多模型接力精修场景output_typepil输出格式可选pil或np.arraygeneratorNone传入torch.manual_seed的生成器可使结果可复现设备支持Pipeline 支持.to(cuda)、.to(mps)、.to(xpu)、.to(cpu)等多种后端示例注释中已列出。SDXL 体量较大CPU 推理会很慢生产环境建议使用 GPU。理解 T2I-Adapter 的底层工作原理T2I-Adapter 本质是一个多尺度特征提取器输入控制图后输出一组不同尺度的特征图feature maps列表供UNet2DConditionModel作为额外的条件输入使用。这在 adapter.py 的类文档中有明确描述。三种网络架构adapter_typeT2IAdapter.__init__依据adapter_type分派到不同子网络架构默认channels默认num_res_blocks默认downscale_factor特点full_adapter[320, 640, 1280, 1280]284 个下采样块标准版full_adapter_xl[320, 640, 1280, 1280]216仅 1 个下采样块专为 SDXL 设计light_adapter[320, 640, 1280]48轻量版通道更窄瓶颈mid_channels out_channels // 4适合低算力场景前向流程与关键组件以FullAdapterXL为例前向过程adapter.py 第 386-400 行为PixelUnshuffle 下采样nn.PixelUnshuffle(downscale_factor)把输入图像的空间像素重排到通道维度输入通道数变为in_channels * downscale_factor**2如 3×16²768。这正是源码属性downscale_factor注释所强调的输入图像尺寸必须能被downscale_factor整除否则会报异常。输入卷积nn.Conv2d将高通道数压缩到首个channels[0]。堆叠AdapterBlock每个AdapterBlock内部可选AvgPool2d下采样、可选1×1通道对齐卷积以及一串AdapterResnetBlock3×3 conv → ReLU → 1×1 conv的残差块输出与输入相加。输出多尺度特征列表每个 block 的输出被收集进features列表并返回列表长度等于下采样块个数。这些特征最终在 Pipeline 的__call__中按adapter_conditioning_scale加权后作为down_block_additional_residuals注入 UNet 的各个下采样阶段。total_downscale_factor计算规则源码可见full_adapter为downscale_factor × 2^(len(channels)-1)full_adapter_xl为downscale_factor × 2light_adapter为downscale_factor × 2^len(channels)。在 Pipeline 中的注入逻辑在 pipeline_stable_diffusion_xl_adapter.py 的__call__中控制图先经_preprocess_adapter_image统一缩放为(height, width)并归一化到[0, 1]单 Adapter 场景adapter_state self.adapter(adapter_input)然后逐尺度乘以adapter_conditioning_scalenum_images_per_prompt 1时特征沿 batch 维重复CFG 开启时特征沿 batch 维拼接两份正向/负向各一份最终特征以down_block_additional_residuals传入 UNet 的forward见 unet_2d_condition.py。进阶用 MultiAdapter 组合多个控制信号现实中常需要同时约束多个属性例如既保持 Canny 边缘轮廓、又符合深度结构。MultiAdapter正是为此设计它是一个包装模型内含多个 T2I-Adapter并把各 Adapter 的输出按权重加权求和后合并为一个多尺度特征列表。加载多个 Adapter 与多个控制图import torch from diffusers.utils import load_image from diffusers import StableDiffusionXLAdapterPipeline, AutoencoderKL, MultiAdapter, T2IAdapter canny_image load_image( https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/canny-cat.png ) depth_image load_image( https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/sdxl_depth_image.png ) controls [canny_image, depth_image] 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 ] adapters MultiAdapter( [ T2IAdapter.from_pretrained(TencentARC/t2i-adapter-canny-sdxl-1.0, dtypetorch.float16), T2IAdapter.from_pretrained(TencentARC/t2i-adapter-depth-midas-sdxl-1.0, dtypetorch.float16), ] )关键点控制图列表顺序与 Adapter 列表顺序一一对应第 i 个控制图喂给第 i 个 AdapterMultiAdapter.__init__adapter.py 第 28-74 行要求至少 2 个 Adapter传入空列表或仅 1 个 Adapter 都会抛出ValueError由于各 Adapter 输出是逐尺度相加的MultiAdapter强制要求所有子 Adapter 的total_downscale_factor与downscale_factor完全一致否则抛出ValueError源码第 60-71 行的校验逻辑。因此实践中通常组合同一系列如都是 SDXL 系列的 Adapter。用 adapter_conditioning_scale 控制每个信号的权重将MultiAdapter作为adapter传入 Pipeline并通过adapter_conditioning_scale列表指定每个控制信号的权重vae AutoencoderKL.from_pretrained(madebyollin/sdxl-vae-fp16-fix, dtypetorch.float16) pipeline StableDiffusionXLAdapterPipeline.from_pretrained( stabilityai/stable-diffusion-xl-base-1.0, dtypetorch.float16, vaevae, adapteradapters, ).to(cuda) # or mps, xpu, cpu pipeline( prompt, imagecontrols, height1024, width1024, adapter_conditioning_scale[0.7, 0.7] ).images[0]工作原理源码可证传入列表时Pipeline 走MultiAdapter分支self.adapter(adapter_input, adapter_conditioning_scale)MultiAdapter.forwardadapter.py 第 76-108 行将每个 Adapter 的输出特征乘以其权重再逐尺度累加accume_state[i] w * features[i]若不传adapter_conditioning_scale则默认使用等权平均1/num_adapter源码第 93-94 行。调参建议基于实现语义的实践推断权重之和无需为 1它是逐尺度相加的系数但建议各权重取相近量级避免某个信号过强压制其他信号若某次生成中边缘轮廓过于生硬可降低 Canny 对应权重如[0.5, 0.8]多控制会占用更多显存并增加一次额外前向开销实际部署时建议先用num_inference_steps20~30快速验证组合效果再提高步数出正式结果。多 Adapter 的保存与加载MultiAdapter也支持save_pretrained/from_pretrained源码第 110-217 行保存时第 1 个 Adapter 存入./mydirectory/adapter第 2 个存入./mydirectory/adapter_1依此类推目录名带_N后缀递增加载时from_pretrained会循环探测adapter、adapter_1、adapter_2……直到目录不存在为止并将全部 Adapter 组装成MultiAdapter仓库测试 test_stable_diffusion_xl_adapter.py 中的StableDiffusionXLMultiAdapterPipelineTesterConfig以adapter_conditioning_scale[0.5, 0.5]驱动同一 Pipeline 进行验证可作为组合使用的参照。训练自己的 T2I-Adapter除了使用社区预训练权重仓库还提供了从零训练 T2I-Adapter 的完整脚本训练入口examples/t2i_adapter/train_t2i_adapter_sdxl.py环境依赖examples/t2i_adapter/requirements.txt使用说明examples/t2i_adapter/README_sdxl.md 与 examples/t2i_adapter/README.md冒烟测试examples/t2i_adapter/test_t2i_adapter.py训练脚本通常需要准备控制图 原图配对数据集如填充图像的线稿/深度/边缘与对应的真实图像通过拟合 UNet 冻结情况下的重建损失来让 Adapter 学会从控制信号中恢复内容。训练完成后同样可以用T2IAdapter.from_pretrained加载到推理 Pipeline 中。实用技巧与注意事项输入尺寸约束控制图会被自动缩放到生成分辨率_preprocess_adapter_image使用 Lanczos 插值但 T2I-Adapter 内部有 PixelUnshuffle 下采样源码明确要求输入尺寸可被downscale_factor整除建议控制图边长取 8 或 16 的整数倍。FP16 显存优化Adapter、VAE、Pipeline 均以dtypetorch.float16加载SDXL 场景推荐配合madebyollin/sdxl-vae-fp16-fix这类 FP16 修复版 VAE避免半精度下的 NaN/颜色偏移问题。与 LoRA、IP-Adapter 协同StableDiffusionXLAdapterPipeline继承了StableDiffusionXLLoraLoaderMixin与IPAdapterMixin见 pipeline_stable_diffusion_xl_adapter.py 的 import 与类定义因此可以叠加加载 LoRA 权重并支持传入ip_adapter_image做风格参考实现结构控制 风格迁移的组合玩法。控制强度调优adapter_conditioning_scale控制信号整体强度adapter_conditioning_factor控制在去噪后期逐步弱化控制二者配合可缓解控制过强导致图像呆板或控制过弱导致轮廓漂移的问题。可复现性传入generatortorch.manual_seed(42)官方文档示例做法可使相同输入产出稳定结果便于调试参数。总结T2I-Adapter 以极小的参数代价为 SDXL 等基础模型注入可控生成能力单控制场景用T2IAdapterStableDiffusionXLAdapterPipeline即可完成Canny 边缘 → 生成图像的闭环多控制场景用MultiAdapter组合多个 Adapter并通过adapter_conditioning_scale列表灵活调配各控制信号的权重。其底层实现多尺度 ResNet 特征提取 down_block_additional_residuals注入 UNet与 ControlNet 机制互补是资源受限场景下可控生成的务实之选。相关源码与测试可在 adapter.py、pipeline_stable_diffusion_xl_adapter.py 与 test_stable_diffusion_xl_adapter.py 中继续深入研读。【免费下载链接】diffusers Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表