ChronoEdit 图像编辑管线实战:基于 diffusers 的时序推理与视频式编辑

发布时间:2026/9/11 22:28:05
ChronoEdit 图像编辑管线实战:基于 diffusers 的时序推理与视频式编辑
ChronoEdit 图像编辑管线实战基于 diffusers 的时序推理与视频式编辑【免费下载链接】diffusers Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch.项目地址: https://gitcode.com/GitHub_Trending/di/diffusersChronoEdit 由 NVIDIA 与多伦多大学联合提出其核心思路是把图像编辑重构为视频生成任务将输入图与目标编辑图分别视为视频的首帧与末帧借助大规模预训练视频生成模型所习得的时序一致性隐式建模物体的运动与物理交互从而在编辑结果中保持物理一致性。本指南基于本仓库diffusers中 ChronoEditPipeline 的完整实现逐步讲解环境准备、基础图像编辑、时序推理temporal reasoning加速、8 步蒸馏 LoRA 与多 LoRA 组合推理并深入剖析其底层实现原理与测试验证帮助你直接上手并理解该管线的运行机制。ChronoEdit 是什么从编辑到视频生成的范式转换传统图像编辑模型往往只关注改了什么而忽略改得是否物理合理。ChronoEdit 将编辑问题重新表述为给定一张输入图作为视频第一帧生成一段以编辑后图像为末帧的短视频。这样做的直接收益是可以直接利用预训练视频生成模型的时序一致性——模型在训练中习得的运动、遮挡、光照与交互物理规律会被迁移到编辑任务中。在此基础上ChronoEdit 引入推理期时序推理阶段temporal reasoning stage在去噪的前若干步中将目标帧与推理 tokenreasoning tokens联合去噪想象出一条物理上可行的编辑轨迹从而把解空间约束在物理可行的变换内随后在剩余步骤中丢弃推理 token避免渲染完整视频带来的高计算开销。这也是num_temporal_reasoning_steps参数存在的意义。在本仓库中该模型由三个主要组件构成全部位于 src/diffusers/pipelines/chronoedit/ 与 src/diffusers/models/transformers/transformer_chronoedit.py组件类说明去噪主干ChronoEditTransformer3DModel3D DiT基于 WanTransformer3DModel 改造负责噪声预测视频自编码器AutoencoderKLWan在像素空间与潜空间之间编解码视频管线入口ChronoEditPipeline编排图像编码、文本编码、去噪循环与解码输出结构ChronoEditPipelineOutput以frames字段承载生成的视频帧模型权重与 LoRA 位于nvidia/ChronoEdit模型集合其中本仓库文档明确列出nvidia/ChronoEdit-14B-Diffusers主模型nvidia/ChronoEdit-14B-Diffusers-Upscaler-Lora超分 LoRAnvidia/ChronoEdit-14B-Diffusers-Paint-Brush-Lora画笔 LoRA将线稿转化为实物准备工作组件加载与依赖ChronoEdit 依赖torch、transformers、PIL、numpy以及 diffusers 本体。加载模型时各组件精度要求不同这与常规整管线上 bfloat16的做法不同import torch import numpy as np from diffusers import AutoencoderKLWan, ChronoEditTransformer3DModel, ChronoEditPipeline from diffusers.utils import export_to_video, load_image from transformers import CLIPVisionModel from PIL import Image model_id nvidia/ChronoEdit-14B-Diffusers # 图像编码器与 VAE 使用 float32 image_encoder CLIPVisionModel.from_pretrained(model_id, subfolderimage_encoder, dtypetorch.float32) vae AutoencoderKLWan.from_pretrained(model_id, subfoldervae, dtypetorch.float32) # Transformer 使用 bfloat16 以节省显存 transformer ChronoEditTransformer3DModel.from_pretrained(model_id, subfoldertransformer, dtypetorch.bfloat16) pipe ChronoEditPipeline.from_pretrained( model_id, image_encoderimage_encoder, transformertransformer, vaevae, dtypetorch.bfloat16, ) pipe.to(cuda) # 或 mps、xpu、cpu为什么 VAE 与图像编码器要保留 float32测试用例 tests/pipelines/chronoedit/test_chronoedit.py 中明确注释了原因ChronoEditPipeline必须以混合精度运行若把整条管线以 FP16 保存/加载会导致错误对应测试test_save_load_float16被 skip 并附此说明。同时在 pipeline_chronoedit.py 的类定义中可以看到模型 CPU offload 顺序为text_encoder-image_encoder-transformer-vae见 model_cpu_offload_seq这意味着即便显存紧张也可以借助enable_model_cpu_offload()自动按该顺序逐模块搬运到 GPU 执行。基础图像编辑输入尺寸对齐与推理参数ChronoEdit 的视频 VAE 具有固定的下采样倍率输入图像尺寸必须满足对齐约束。文档给出的做法是以面积上限推导宽高image load_image( https://huggingface.co/spaces/nvidia/ChronoEdit/resolve/main/examples/3.png ) max_area 720 * 1280 aspect_ratio image.height / image.width mod_value pipe.vae_scale_factor_spatial * pipe.transformer.config.patch_size[1] height round(np.sqrt(max_area * aspect_ratio)) // mod_value * mod_value width round(np.sqrt(max_area / aspect_ratio)) // mod_value * mod_value print(width, width, height, height) image image.resize((width, height))这里mod_value的计算揭示了两层约束的乘积pipe.vae_scale_factor_spatialVAE 空间下采样倍率AutoencoderKLWan默认为 8见 pipeline_chronoedit.pypipe.transformer.config.patch_size[1]Transformer 3D patch 的高方向 patch 大小默认(1, 2, 2)中的 2。两者相乘得到 16即宽高必须是 16 的倍数。这与 check_inputs 中的校验逻辑一致height % 16 ! 0 or width % 16 ! 0会直接抛出ValueError。文档示例将面积控制在约 720×1280约 92 万像素属于该 14B 模型相对均衡的显存/质量折中。随后构造提示词并执行推理prompt ( The user wants to transform the image by adding a small, cute mouse sitting inside the floral teacup, enjoying a spa bath. The mouse should appear relaxed and cheerful, with a tiny white bath towel draped over its head like a turban. It should be positioned comfortably in the cups liquid, with gentle steam rising around it to blend with the cozy atmosphere. The mouses pose should be natural—perhaps sitting upright with paws resting lightly on the rim or submerged in the tea. The teacups floral design, gold trim, and warm lighting must remain unchanged to preserve the original aesthetic. The steam should softly swirl around the mouse, enhancing the spa-like, whimsical mood. ) output pipe( imageimage, promptprompt, heightheight, widthwidth, num_frames5, num_inference_steps50, guidance_scale5.0, enable_temporal_reasoningFalse, num_temporal_reasoning_steps0, ).frames[0] Image.fromarray((output[-1] * 255).clip(0, 255).astype(uint8)).save(output.png)要点说明num_frames5基础编辑只需 5 帧最终取output[-1]即编辑完成的末帧保存为 PNGenable_temporal_reasoningFalse、num_temporal_reasoning_steps0关闭推理 token最快速度得到编辑结果输出output是归一化到[0,1]的浮点帧序列因此保存前需要乘 255 并clip再转uint8。从源码看当关闭时序推理时管线会强制num_frames 5见 pipeline_chronoedit.py并提示num_frames - 1必须能被vae_scale_factor_temporal默认为 4整除否则自动向下取整到最近的可整除值。编辑为何物理合理prepare_latents 的秘密在 prepare_latents 中可以看到视频式编辑的关键构造输入图像被编码为视频条件video_condition——第一帧为真实输入图其余帧为零帧经 VAE 编码后与一个首帧掩码拼接作为去噪网络的额外条件通道。这保证模型在生成后续帧包括末帧编辑结果时始终看到原始输入图从而在时序上锚定编辑内容。启用时序推理编辑轨迹的可视化当需要更强的物理一致性、或想同时得到从原图到编辑图的过渡视频时开启 temporal reasoningoutput pipe( imageimage, promptprompt, heightheight, widthwidth, num_frames29, num_inference_steps50, guidance_scale5.0, enable_temporal_reasoningTrue, num_temporal_reasoning_steps50, ).frames[0] export_to_video(output, output.mp4, fps16) Image.fromarray((output[-1] * 255).clip(0, 255).astype(uint8)).save(output.png)其底层行为对应 pipeline_chronoedit.py 中的分支逻辑前num_temporal_reasoning_steps步内模型对完整帧序列含推理 token 对应的中间帧联合去噪想象一条物理可行的编辑轨迹当i num_temporal_reasoning_steps时潜变量与条件被截断为[0, -1]两帧同时清理调度器缓存model_outputs、last_sample以匹配新的帧数剩余步骤只对首、末两帧去噪大幅降低计算量解码阶段pipeline_chronoedit.py分别解码推理轨迹与首末帧两部分再拼接出完整视频video torch.cat([video_reason, video_edit[:, :, 1:]], dim2)。参数关系num_temporal_reasoning_steps表示前多少步启用推理 token。文档示例中设为 50等于总步数表示全程保持推理 token 直至生成完整 29 帧视频若设为较小值如 20则前 20 步联合去噪、后 30 步仅精修首末帧兼顾质量与速度。视频条件帧数约束注意源码中有num_frames 5 if not enable_temporal_reasoning else num_frames的强制逻辑只有开启时序推理时自定义num_frames如 29才会生效关闭时固定输出 5 帧。此外视频式帧数还需满足(num_frames - 1) % vae_scale_factor_temporal 0即num_frames形如4k1否则管线自动向下取整。8 步蒸馏 LoRA极速推理官方提供蒸馏 LoRA可将推理步数从 50 步压缩到8 步并配合UniPCMultistepScheduler使用import torch import numpy as np from diffusers import AutoencoderKLWan, ChronoEditTransformer3DModel, ChronoEditPipeline from diffusers.schedulers import UniPCMultistepScheduler from diffusers.utils import export_to_video, load_image from transformers import CLIPVisionModel from PIL import Image model_id nvidia/ChronoEdit-14B-Diffusers image_encoder CLIPVisionModel.from_pretrained(model_id, subfolderimage_encoder, dtypetorch.float32) vae AutoencoderKLWan.from_pretrained(model_id, subfoldervae, dtypetorch.float32) transformer ChronoEditTransformer3DModel.from_pretrained(model_id, subfoldertransformer, dtypetorch.bfloat16) pipe ChronoEditPipeline.from_pretrained(model_id, image_encoderimage_encoder, transformertransformer, vaevae, dtypetorch.bfloat16) # 加载并融合蒸馏 LoRA pipe.load_lora_weights(nvidia/ChronoEdit-14B-Diffusers, weight_namelora/chronoedit_distill_lora.safetensors, adapter_namedistill) pipe.fuse_lora(adapter_names[distill], lora_scale1.0) # 切换到多步调度器并设置 flow_shift pipe.scheduler UniPCMultistepScheduler.from_config(pipe.scheduler.config, flow_shift2.0) pipe.to(cuda) # 或 mps、xpu、cpu # ……图像加载、尺寸对齐代码同上…… output pipe( imageimage, promptprompt, heightheight, widthwidth, num_frames5, num_inference_steps8, # 蒸馏后只需 8 步 guidance_scale1.0, # 蒸馏模型通常搭配低 guidance enable_temporal_reasoningFalse, num_temporal_reasoning_steps0, ).frames[0] export_to_video(output, output.mp4, fps16) Image.fromarray((output[-1] * 255).clip(0, 255).astype(uint8)).save(output.png)关键差异与原因guidance_scale1.0此时do_classifier_free_guidance属性为False见 pipeline_chronoedit.py管线跳过无条件分支只需一次 transformer 前向这也是 8 步能跑得快的原因之一调度器替换默认FlowMatchEulerDiscreteScheduler换为UniPCMultistepScheduler并从原调度器配置继承from_config(pipe.scheduler.config)额外指定flow_shift2.0以匹配蒸馏模型的噪声调度ChronoEditPipeline继承自WanLoraLoaderMixin见 类定义因此load_lora_weights/fuse_lora用法与 Wan 系列管线一致。多 LoRA 组合Paint-Brush 蒸馏ChronoEdit 支持同时叠加多个 LoRA典型场景是画笔 LoRA 蒸馏 LoRA组合前者负责把输入线稿转化为与画面内容一致的实物后者负责加速。示例以一张铅笔线稿为输入import torch import numpy as np from diffusers import AutoencoderKLWan, ChronoEditTransformer3DModel, ChronoEditPipeline from diffusers.schedulers import UniPCMultistepScheduler from diffusers.utils import export_to_video, load_image from transformers import CLIPVisionModel from PIL import Image model_id nvidia/ChronoEdit-14B-Diffusers image_encoder CLIPVisionModel.from_pretrained(model_id, subfolderimage_encoder, dtypetorch.float32) vae AutoencoderKLWan.from_pretrained(model_id, subfoldervae, dtypetorch.float32) transformer ChronoEditTransformer3DModel.from_pretrained(model_id, subfoldertransformer, dtypetorch.bfloat16) pipe ChronoEditPipeline.from_pretrained(model_id, image_encoderimage_encoder, transformertransformer, vaevae, dtypetorch.bfloat16) # 同时注册两个 LoRAadapter_name 用于区分 pipe.load_lora_weights(nvidia/ChronoEdit-14B-Diffusers-Paint-Brush-Lora, weight_namepaintbrush_lora_diffusers.safetensors, adapter_namepaintbrush) pipe.load_lora_weights(nvidia/ChronoEdit-14B-Diffusers, weight_namelora/chronoedit_distill_lora.safetensors, adapter_namedistill) pipe.fuse_lora(adapter_names[paintbrush, distill], lora_scale1.0) pipe.scheduler UniPCMultistepScheduler.from_config(pipe.scheduler.config, flow_shift2.0) pipe.to(cuda) # 或 mps、xpu、cpu image load_image( https://raw.githubusercontent.com/nv-tlabs/ChronoEdit/refs/heads/main/assets/images/input_paintbrush.png ) # ……尺寸对齐代码同上…… prompt ( Turn the pencil sketch in the image into an actual object that is consistent with the images content. The user wants to change the sketch to a crown and a hat. ) output pipe( imageimage, promptprompt, heightheight, widthwidth, num_frames5, num_inference_steps8, guidance_scale1.0, enable_temporal_reasoningFalse, num_temporal_reasoning_steps0, ).frames[0] export_to_video(output, output.mp4, fps16) Image.fromarray((output[-1] * 255).clip(0, 255).astype(uint8)).save(output_1.png)使用要点先注册、后融合load_lora_weights(..., adapter_name...)逐个注册适配器fuse_lora(adapter_names[...], lora_scale1.0)一次性融合并可通过lora_scale调节整体强度每个 LoRA 的权重文件名不同paintbrush_lora_diffusers.safetensors与lora/chronoedit_distill_lora.safetensors通过weight_name指定组合后仍采用 8 步 UniPCMultistepSchedulerguidance_scale1.0的蒸馏配置说明多个 LoRA 可以在同一套加速配置下协同工作。核心调用链与源码级解析管线前向流程ChronoEditPipeline.__call__的完整流程对应 pipeline_chronoedit.py输入校验check_inputsimage与image_embeds二选一、prompt与prompt_embeds二选一、宽高必须被 16 整除文本编码encode_prompt/_get_t5_prompt_embeds使用 UMT5 编码器先做prompt_cleanftfy.fix_text HTML 反转义 空白归一化见 basic_clean / whitespace_clean再 padding/truncation 到max_sequence_length默认 512图像编码encode_imageCLIP Vision 编码器输出倒数第二层 hidden statesoutput_hidden_statesTrue时的hidden_states[-2]作为图像条件嵌入潜变量准备prepare_latents构造视频条件与首帧掩码细节见上文去噪循环逐时间步调用transformer若guidance_scale 1则并行计算条件/无条件两条路径按noise_uncond guidance_scale * (noise_pred - noise_uncond)合成期间支持callback_on_step_end步级回调可监听latents、prompt_embeds、negative_prompt_embeds以及 XLAmark_step解码latents 先按latents_mean/latents_std反归一化再经vae.decode得到视频帧最后通过VideoProcessor.postprocess_video输出。Transformer 架构要点ChronoEditTransformer3DModel 是标准的视频 DiT关键设计包括3D patch 化nn.Conv3d以patch_size(1, 2, 2)对视频进行时空 patch时间维度不压缩、空间维度各下采样 2 倍3D 旋转位置编码ChronoEditRotaryPosEmbed 将 head 维度拆分为时间/高/宽三部分分别注入 RoPE支持num_frames 2的首末帧特例时序推理截断后的去噪正是利用这一点双条件交叉注意力每个 WanTransformerBlock 依次执行自注意力 → 交叉注意力 → FFN交叉注意力同时注入文本嵌入与图像嵌入add_k_proj/add_v_proj额外投影并在注意力内完成图像 token 与文本 token 的分离拼接数值稳定性归一化层采用FP32LayerNorm_keep_in_fp32_modules声明了time_embedder、scale_shift_table、各 norm 层保持 FP32避免低精度下归一化数值溢出上下文并行CP支持_cp_plan定义了 rope 与 transformer 块的张量切分策略其中注释明确说明因图像编码器固定输出 257 个 token、拼接后文本总长 769 无法被设备数整除因此对encoder_hidden_states不做切分transformer_chronoedit.py。测试验证仓库提供了完整的管线测试 tests/pipelines/chronoedit/test_chronoedit.pyChronoEditPipelineTesterConfig声明了管线为视频管线暴露num_videos_per_prompt而非num_images_per_prompt输出形状为(5, 3, 16, 16)帧数、通道、高、宽test_inference使用 CPU 运行 dummy 组件并比对固定输出的前 8 与后 8 个元素的期望张量切片atol1e-3锁定推理数值稳定性TestChronoEditPipelineMemory覆盖 CPU offload、group offload 与 layerwise casting 等显存优化路径两个 skip 测试揭示了使用约束管线必须混合精度运行不能整体 FP16 保存/加载批量推理的严格一致性测试需要极高的容差阈值暂被跳过。如果你需要修改管线行为或排查问题可以从 pipeline_chronoedit.py 与 transformer_chronoedit.py 入手二者都标注了大量Copy from Wan注释与 Wan 系列管线如pipeline_wan_i2v共享实现理解 Wan 会有助于快速上手 ChronoEdit。参数速查表参数默认值说明height/width480 / 832输出视频分辨率必须能被 16 整除vae_scale_factor_spatial * patch_size[1]num_frames81视频帧数需满足(num_frames - 1) % 4 0关闭时序推理时强制为 5num_inference_steps50去噪步数搭配蒸馏 LoRA 时可降至 8guidance_scale5.0CFG 强度1 时启用 classifier-free guidance蒸馏场景用 1.0enable_temporal_reasoningFalse是否启用推理 token 阶段num_temporal_reasoning_steps0推理 token 保留的去噪步数max_sequence_length512UMT5 文本编码最大长度超长截断、不足 paddingnum_videos_per_prompt1每个提示词生成的视频数量output_typenp输出格式可选np、pt、pil、latent小结ChronoEdit 提供了一条以视频生成思路解决物理一致性图像编辑的完整实现路径。在本仓库中你可以通过 ChronoEditPipeline 一键完成基础图像编辑5 帧快速出图、带编辑轨迹可视化的时序推理29 帧视频、8 步蒸馏 LoRA 极速推理以及 Paint-Brush 蒸馏的多 LoRA 组合。其底层 3D DiT 架构、首帧条件构造与推理 token 的先联合去噪、后丢弃截断机制均可在 transformer_chronoedit.py 与 pipeline_chronoedit.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),仅供参考