news 2026/9/10 20:42:23

Diffusers 中的 Flux.1 ControlNet 管线:用 Canny / Depth / Union 条件精确控制图像生成

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Diffusers 中的 Flux.1 ControlNet 管线:用 Canny / Depth / Union 条件精确控制图像生成

Diffusers 中的 Flux.1 ControlNet 管线:用 Canny / Depth / Union 条件精确控制图像生成

【免费下载链接】diffusers🤗 Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusers

导读

本文围绕 Flux.1 ControlNet 官方文档,系统讲解 🤗 Diffusers 中FluxControlNetPipeline的完整用法:从 InstantX 与 XLabs 两套预训练 ControlNet 的选型,到文本到图像、图像到图像、局部重绘三种调用方式,再到多 ControlNet 组合、ControlNet-Union 模式与 LoRA 融合等进阶能力。读完本文,你将掌握如何加载 Flux.1-dev 基座模型与 ControlNet 权重、如何调优controlnet_conditioning_scalecontrol_guidance_start/end等核心参数,并理解其底层实现原理(对应源码 pipeline_flux_controlnet.py 与模型定义 controlnet_flux.py)。


一、背景:ControlNet 为 Flux.1 带来的条件控制

ControlNet 最初由 Lvmin Zhang、Anyi Rao 与 Maneesh Agrawala 在论文Adding Conditional Control to Text-to-Image Diffusion Models中提出。其核心思想是:在冻结已训练好的大规模文生图扩散模型(如 Flux.1)权重的前提下,额外训练一套可插拔的条件控制网络,用“零卷积”(zero-initialized convolution layers)从零逐步增长参数,从而在不破坏基座模型的前提下注入边缘、深度、分割、人体姿态等空间条件。

本文涉及的是 Flux.1 架构上的 ControlNet 实现,与 Stable Diffusion 的 ControlNet 在使用 API 上相似,但底层架构(MMDiT、2×2 打包等)完全不同。

在 Diffusers 中,这条管线即为FluxControlNetPipeline,位于 src/diffusers/pipelines/flux/pipeline_flux_controlnet.py。官方文档明确指出该代码由The InstantX Team实现,同时XLabs Team贡献的另一套 ControlNet 权重同样受支持。


二、选择预训练 ControlNet 权重

2.1 InstantX 系列(官方文档推荐)

ControlNet 类型开发者权重仓库
Canny(边缘)The InstantX TeamInstantX/FLUX.1-dev-Controlnet-Canny
Depth(深度)The InstantX TeamShakker-Labs/FLUX.1-dev-ControlNet-Depth
Union(多条件统一)The InstantX TeamInstantX/FLUX.1-dev-Controlnet-Union

2.2 XLabs 系列(同样受支持)

ControlNet 类型开发者权重仓库
CannyThe XLabs TeamXLabs-AI/flux-controlnet-canny-diffusers
DepthThe XLabs TeamXLabs-AI/flux-controlnet-depth-diffusers
HED(软边缘)The XLabs TeamXLabs-AI/flux-controlnet-hed-diffusers

使用提示:两套权重的结构存在差异,详见下文"两种架构分支"一节——InstantX 的模型没有input_hint_block,需要先把条件图编码进 VAE 潜在空间;XLabs 的模型自带input_hint_block,直接消费像素级提示图。因此在加载管线时,务必保证 ControlNet 权重与基座模型(black-forest-labs/FLUX.1-dev)配套使用,并统一使用torch_dtype=torch.bfloat16以匹配 Flux.1 的训练精度。


三、快速上手:文本到图像(Text-to-Image)

官方文档(同时被写入 pipeline_flux_controlnet.py 的 docstring 作为示例)给出的最小可用代码如下:

import torch from diffusers.utils import load_image from diffusers import FluxControlNetPipeline from diffusers import FluxControlNetModel base_model = "black-forest-labs/FLUX.1-dev" controlnet_model = "InstantX/FLUX.1-dev-controlnet-canny" controlnet = FluxControlNetModel.from_pretrained(controlnet_model, torch_dtype=torch.bfloat16) pipe = FluxControlNetPipeline.from_pretrained( base_model, controlnet=controlnet, torch_dtype=torch.bfloat16 ) pipe.to("cuda") control_image = load_image("https://huggingface.co/InstantX/SD3-Controlnet-Canny/resolve/main/canny.jpg") prompt = "A girl in city, 25 years old, cool, futuristic" image = pipe( prompt, control_image=control_image, control_guidance_start=0.2, control_guidance_end=0.8, controlnet_conditioning_scale=1.0, num_inference_steps=28, guidance_scale=3.5, ).images[0] image.save("flux.png")

关键参数解析(依据__call__签名,见 pipeline_flux_controlnet.py)

参数默认值说明
control_image必填条件控制图,支持PIL.Image.Imagenp.ndarraytorch.Tensor及对应 list;多 ControlNet 时必须按序传入 list
controlnet_conditioning_scale1.0ControlNet 输出注入主网络残差前的乘性权重;多 ControlNet 时可传 list 分别指定
control_guidance_start0.0ControlNet 开始生效的步数百分比(0~1)
control_guidance_end1.0ControlNet 停止生效的步数百分比(0~1)
control_modeNone仅 ControlNet-Union 使用,指定条件类型(见下文 Union 小节)
guidance_scale7.0无分类器引导强度,越高越贴近 prompt,但过高会降低图像质量
true_cfg_scale1.0大于 1 且传入negative_prompt时启用真正的无分类器引导(Flux.1 默认不适用传统 CFG)
num_inference_steps28去噪步数,越多质量越高但更慢
height/width1024(由default_sample_size=128与 VAE 缩放因子推导)生成尺寸,须能被vae_scale_factor * 2(即 16)整除
max_sequence_length512T5 文本编码器最大序列长度,上限 512(超限会在check_inputs中报错)
generatorNone随机数生成器,传入后可复现结果
latentsNone预先生成的噪声潜在向量,用于固定构图/种子
joint_attention_kwargsNone透传给注意力处理器的 kwargs,可用于 LoRA scale 等

control_guidance_start/end的范围语义:以0.2 ~ 0.8为例,表示前 20% 与后 20% 的采样步中 ControlNet 不参与,只在中间 60% 的步数施加条件——这在"先用 prompt 自由构图、再让条件约束细节"的工作流中非常实用。若传入多 ControlNet,这两个参数会自动扩展为与 ControlNet 数量等长的 list(见 pipeline_flux_controlnet.py 的归一化逻辑)。


四、底层原理:ControlNet 是如何接入 Flux 的

4.1 模型定义与两种架构分支

FluxControlNetModel定义于 src/diffusers/models/controlnets/controlnet_flux.py。其__init__中有一个关键开关:

  • 当构造时传入conditioning_embedding_channels时,会创建ControlNetConditioningEmbeddingblock_out_channels=(16, 16, 16, 16))作为input_hint_block——这是XLabs 架构,条件图直接走提示编码块进入网络;
  • 当该值为Noneinput_hint_block = None——这是InstantX 架构,条件图必须先经 VAE 编码并完成 2×2 打包。

对应地,管线在 pipeline_flux_controlnet.py 中用self.controlnet.input_hint_block is None判断分支:

# xlab controlnet has a input_hint_block and instantx controlnet does not controlnet_blocks_repeat = False if self.controlnet.input_hint_block is None else True if self.controlnet.input_hint_block is None: # vae encode control_image = retrieve_latents(self.vae.encode(control_image), generator=generator) control_image = (control_image - self.vae.config.shift_factor) * self.vae.config.scaling_factor # pack:将 latent 切分为 2×2 patch control_image = self._pack_latents(...)

4.2 Flux 特有的 latent 打包(packing)

Flux 的 MMDiT 架构不直接处理B, C, H, W的潜在张量,而是将其拆成 2×2 的 patch 并展平为序列。因此管线中的_pack_latents(pipeline_flux_controlnet.py)会把(batch, channels, H, W)重排为(batch, (H/2)*(W/2), channels*4)_unpack_latents则在解码前反向还原。这也是为什么height/width必须能被 16 整除(VAE 8 倍压缩 × 2×2 打包),check_inputs会对不满足的尺寸发出告警。

4.3 前向推理流程(__call__主循环)

__call__的执行顺序可归纳为:

  1. 输入校验check_inputs检查promptprompt_embeds二选一、negative_prompt配对、尺寸可整除等;
  2. 文本编码encode_prompt分别调用 CLIP(得到 pooled 输出)与 T5(序列最长 512)两套编码器,得到prompt_embedspooled_prompt_embedstext_ids
  3. 条件图准备prepare_image完成预处理、resize 到目标尺寸并按num_images_per_prompt重复;随后按上节所述进入 VAE 编码 + 打包分支;
  4. 步进去噪:每步用FlowMatchEulerDiscreteScheduler计算时间步,将control_imagetext_idslatent_image_ids一并送入transformer,ControlNet 输出乘以controlnet_conditioning_scale后叠加进主网络;
  5. 解码输出_unpack_latents还原潜在张量,VAE 解码为图像,默认返回FluxPipelineOutputreturn_dict=True)或 tuple。

4.4 多 ControlNet:FluxMultiControlNetModel

传入 list/tuple 形式的 ControlNet 时,__init__会自动包装为FluxMultiControlNetModel(controlnet_flux.py),并在前向中逐条读取controlnet_condcontrolnet_modeconditioning_scale,把多个条件网络的结果累加进主网络(controlnet_flux.py)。此时control_imagecontrolnet_conditioning_scalecontrol_guidance_start/endcontrol_mode都应传等长 list,实现"Canny 边缘 + Depth 深度"之类的组合控制。


五、进阶用法一:图像到图像(Image-to-Image)

仓库还提供FluxControlNetImg2ImgPipeline(pipeline_flux_controlnet_image_to_image.py),支持在条件控制的同时以一张源图初始化 latent,实现"参考原图结构 + 受 ControlNet 约束"的重绘。

import torch from diffusers import FluxControlNetImg2ImgPipeline, FluxControlNetModel from diffusers.utils import load_image controlnet = FluxControlNetModel.from_pretrained( "InstantX/FLUX.1-dev-controlnet-canny", torch_dtype=torch.bfloat16 ) pipe = FluxControlNetImg2ImgPipeline.from_pretrained( "black-forest-labs/FLUX.1-dev", controlnet=controlnet, torch_dtype=torch.bfloat16, ) pipe.to("cuda") init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/img2img-init.jpg") control_image = load_image("https://huggingface.co/InstantX/SD3-Controlnet-Canny/resolve/main/canny.jpg") image = pipe( "a cat wearing sunglasses", image=init_image, control_image=control_image, strength=0.6, # 保留原图结构的程度 controlnet_conditioning_scale=0.8, num_inference_steps=28, guidance_scale=3.5, ).images[0]

strength控制重绘程度:值越大越偏离原图。该参数与control_image的 VAE 编码逻辑共同作用,实际效果建议在 0.4~0.8 之间调试。


六、进阶用法二:局部重绘(Inpainting)

FluxControlNetInpaintPipeline(pipeline_flux_controlnet_inpainting.py)把 ControlNet 条件与掩码重绘结合起来:掩码区域被重新生成,而 ControlNet 约束确保生成结果贴合指定的空间结构(如边缘、深度)。

import torch from diffusers import FluxControlNetInpaintPipeline, FluxControlNetModel from diffusers.utils import load_image controlnet = FluxControlNetModel.from_pretrained( "InstantX/FLUX.1-dev-controlnet-canny", torch_dtype=torch.bfloat16 ) pipe = FluxControlNetInpaintPipeline.from_pretrained( "black-forest-labs/FLUX.1-dev", controlnet=controlnet, torch_dtype=torch.bfloat16, ) pipe.to("cuda") init_image = load_image(".../dog.png") mask_image = load_image(".../dog_mask.png") control_image = load_image(".../canny.png") image = pipe( "a majestic lion", image=init_image, mask_image=mask_image, control_image=control_image, strength=0.8, guidance_scale=3.5, controlnet_conditioning_scale=1.0, num_inference_steps=28, ).images[0]

掩码(白色区域为待重绘)会通过 VAE 编码进 latent 空间,并与控制条件一起在去噪循环中发挥作用;两种进阶管线共享本文第一节的所有 ControlNet 参数语义,可平滑迁移。


七、进阶用法三:ControlNet-Union 与多条件组合

7.1 Union 模式

InstantX/FLUX.1-dev-Controlnet-Union允许单个 ControlNet 处理多种条件类型。通过control_mode指定条件类型(管线要求其为intNone,多 ControlNet 时传等长 list,见 pipeline_flux_controlnet.py):

image = pipe( prompt, control_image=control_image, control_mode=0, # 具体取值映射见 InstantX 权重仓库说明(如 Canny/Depth/…) controlnet_conditioning_scale=1.0, num_inference_steps=28, guidance_scale=3.5, ).images[0]

control_mode会在进入多 ControlNet 前向时被展开为与条件图等长的张量(FluxMultiControlNetModel.forward中逐一对应,未指定时以-1兜底,见 controlnet_flux.py)。

7.2 多 ControlNet 组合(以 Canny + Depth 为例)

controlnet_canny = FluxControlNetModel.from_pretrained( "InstantX/FLUX.1-dev-controlnet-canny", torch_dtype=torch.bfloat16 ) controlnet_depth = FluxControlNetModel.from_pretrained( "Shakker-Labs/FLUX.1-dev-ControlNet-Depth", torch_dtype=torch.bfloat16 ) pipe = FluxControlNetPipeline.from_pretrained( "black-forest-labs/FLUX.1-dev", controlnet=[controlnet_canny, controlnet_depth], # list 自动包装为 FluxMultiControlNetModel torch_dtype=torch.bfloat16, ) pipe.to("cuda") image = pipe( prompt, control_image=[canny_image, depth_image], controlnet_conditioning_scale=[0.8, 0.7], # 逐 ControlNet 权重 control_guidance_start=[0.0, 0.1], control_guidance_end=[1.0, 0.9], num_inference_steps=28, guidance_scale=3.5, ).images[0]

八、进阶用法四:与 LoRA 协同使用

FluxControlNetPipeline同时继承FluxLoraLoaderMixinFromSingleFileMixinFluxIPAdapterMixin(pipeline_flux_controlnet.py),因此可:

  • 通过pipe.load_lora_weights(...)加载风格/概念 LoRA,并通过joint_attention_kwargs={"scale": 0.8}调节 LoRA 强度(源码中encode_prompt会根据lora_scale动态scale_lora_layers/unscale_lora_layers);
  • 通过pipe.load_ip_adapter(...)ip_adapter_image参数叠加 IP-Adapter 图像语义引导,实现"文本 + 条件图 + 参考图"三重控制;
  • 通过FromSingleFileMixin从单文件权重加载整条管线。

提示:_callback_tensor_inputs = ["latents", "prompt_embeds", "control_image"],这意味着步进回调(callback_on_step_end)可拿到这三个张量,用于中间过程可视化或提前中断(pipe.interrupt)。


九、参考实现与自测

仓库为上述能力提供了完整的单测覆盖,可作为行为基准(torch_dtype建议按 CI 环境使用torch.bfloat16):

  • 文本到图像: tests/pipelines/controlnet_flux/test_controlnet_flux.py
  • 图像到图像: tests/pipelines/controlnet_flux/test_controlnet_flux_img2img.py
  • 局部重绘: tests/pipelines/controlnet_flux/test_controlnet_flux_inpaint.py

测试中覆盖了control_guidance_start/end边界、多 ControlNet 传参、FluxPipelineOutput结构等关键行为,阅读这些用例可帮助你校准自己的调用参数。若需要为 Flux.1 训练自定义 ControlNet,仓库还提供了官方训练脚本 examples/flux-control/train_control_flux.py(支持--dataset_name/--jsonl_for_train数据源、--image_column/--conditioning_image_column列名配置、--resolution(需能被 8 整除,以保证 VAE 与 Transformer 尺寸一致)、--validation_prompt/--validation_image周期验证等参数),以及 LoRA 版 train_control_lora_flux.py。


十、常见问题与调参建议

  1. 生成尺寸异常height/width必须能被 16 整除,否则check_inputs会告警并自动调整尺寸(pipeline_flux_controlnet.py)。
  2. 条件约束过强/过弱:优先调节controlnet_conditioning_scale(0.5~1.0 常见区间);当希望"先自由生成、后受约束"时,使用control_guidance_start=0.2, control_guidance_end=0.8这类区间化设置。
  3. InstantX 与 XLabs 权重混用:两者架构分支不同(input_hint_block有无),混用可能导致维度不匹配,请保持同一团队权重。
  4. 内存占用过高:可启用 CPU offload(pipe.enable_model_cpu_offload(),类属性model_cpu_offload_seq = "text_encoder->text_encoder_2->image_encoder->transformer->vae"已按依赖顺序定义)或enable_sequential_cpu_offload()
  5. 关于调度器:管线默认使用FlowMatchEulerDiscreteScheduler,可参考 Schedulers 指南 在速度与质量之间权衡;若需在多条管线间复用 VAE/文本编码器等组件,参见 Reusing models across pipelines。

小结

FluxControlNetPipeline及其衍生管线(Img2Img、Inpaint)把 ControlNet 的空间条件控制能力完整地带到了 Flux.1 生态:通过 controlnet_flux.py 中的FluxControlNetModel/FluxMultiControlNetModel与管线侧 pipeline_flux_controlnet.py 的打包-去噪-解包流程,配合 InstantX / XLabs 的预训练权重,即可用 Canny 边缘、深度图、Union 多模式乃至多个 ControlNet 的组合,精确约束 Flux.1 的图像生成结果,同时保留 LoRA、IP-Adapter 等生态能力的叠加空间。

【免费下载链接】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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 20:41:01

CANN/ge GE工具模块文档

GeUtils 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的…

作者头像 李华
网站建设 2026/9/10 20:40:29

Ricon组态系统在智能楼宇中的核心应用与优化

1. Ricon组态系统与智能楼宇的完美结合 第一次接触Ricon组态系统是在三年前的一个商业综合体项目中。当时业主方提出要实现整栋大楼的智能化管控,要求将空调、照明、安防等十几个子系统集成到一个平台上。经过多方对比,我们最终选择了Ricon组态系统作为核…

作者头像 李华
网站建设 2026/9/10 20:39:09

昇腾/ge自定义逻辑流分配Pass开发

使用自定义逻辑流分配Pass定制并发 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 P…

作者头像 李华