← ALL ARTICLES

视频生成的逐步颜色约束

全库目录221
本文目录11

有效对应只提供可复用的颜色,模型还需要明确的初始化、加噪和逐步约束规则。本组示例使用同一镜头的渲染序列,第0、10帧为批准关键帧,角色在第3帧被柱子遮挡、第4帧重新显露。R是当前原始渲染色,D是以米计的正向视深度,ID是稳定对象标识,W是重投影历史色,M是有效历史二值遮罩;颜色在固定色调映射后的显示线性RGB域混合,交给模型前编码为sRGB。Q表示局部历史置信度,A_anchor表示连接批准关键帧的路径置信度,两者分别记录。对应与遮罩的完整判定见视频历史重投影。本页定义一条教学用像素投影DDIM变体。

历史图与潜变量

像素空间合成

令W_t是重投影后的线性历史颜色。分配W、重投影Q和锚点置信度缓冲时先填有限零值;图外或其他拒绝分支不执行无效采样,保留占位值并将M置零。着色器或张量运算中的0*NaN仍为NaN,遮罩乘法不能替代有效数据初始化;同样先检查深度、法线和置信度为有限数,再进入除法与归一化。

先将位置、ID、深度、置信度与法线检查的结果合为几何有效遮罩,再与当前照明、材质稳定遮罩相交,得到M_t。灯光切换或材质更新的对象在构造A以前就令M为零;没有事件信息时,比较当前R和重投影的历史渲染色,亮度变化超过10%的对象保守拒绝。历史记录因此同时保存原始渲染R,不能拿风格化生成图作渲染亮度比较。具体亮度筛选与曝光用途见视频曝光与关键帧融合。

以sRGB编码传递T构造模型输入:这里的线性RGB已经经过视频历史重投影规定的镜头固定色调映射,T只把显示线性RGB编码为sRGB,不重复执行色调映射。历史和生成结果均保存为这个显示线性工作域,而不是场景辐射亮度。

At=MtWt+(1−Mt)Rt,zA=s E(2T(At)−1)A_t=M_t W_t+(1-M_t)R_t,\qquad z_A=s\,E(2T(A_t)-1)

E取VAE编码分布的均值,s读取vae.config.scaling_factor,不手填另一个模型的常量。模型图像张量为1×3×H×W、值域[−1,1],潜变量为1×4×H/8×W/8。VAE解码器记为Dec,解码使用Dec(z/s)再由[−1,1]回到[0,1],最后撤销sRGB传递得到线性颜色。比如历史0.8、当前渲染0.2,接受像素的A为0.8,拒绝像素为0.2;遮罩决定复用哪份信息,然后才编码整张图。

像素遮罩不能直接当潜变量遮罩。8×8块只要有一个显露像素,平均池化就会留下非零历史权重;保守取最小值又会整块放弃历史。即使扩大拒绝边缘,VAE卷积与注意力也可能让远处像素影响同一个特征。本路线因此始终在图像空间作遮罩投影,再编码整图;它允许模型特征有全局耦合,明确控制的是哪一个像素直接复制历史。这个差别在后面的每一步约束中保持一致。

潜变量重投影的替代路线

直接搬运历史潜变量可以省去一部分图像重编码,但要另行解决遮罩与编码不等变问题。对于缩小8倍且无裁剪的编码,原图像素中心采用整数坐标,潜变量中心l对应x=8(l+0.5)-0.5;查询原图反向流后,有:

lh=(x+B+0.5)/8−0.5=l+B/8l_h=(x+B+0.5)/8-0.5=l+B/8

l=20、B=−8时查19,直接查12会把运动扩大8倍。存在裁剪和填充时,先由当前潜变量中心还原原图位置,加上原图流,再应用历史图的预处理仿射变换。这个坐标正确性只保证查询位置正确,不能保证E(warp(I))=warp(E(I))。编码感受野和压缩会破坏这个等式。采用该路线时,显露区须独立编码当前渲染,并对混合边界观察重建误差;它不能与本页整图编码路径交替使用而不重新定义历史。

条件去噪与历史约束

模型和条件契约

下面选用Diffusers 0.35.1、Stable Diffusion 1.5、lllyasviel/sd-controlnet-depth和DDIM。模型权重、提示词、负面提示词、随机种子与色彩变换在镜头内固定并写入任务清单;每帧种子取镜头种子+帧号,让显露区域获得新噪声。固定种子固定重试的随机采样起点;逐位结果还取决于设备、算子和运行库,已采用结果按文件哈希恢复。时序对应由几何与历史判定提供。

深度ControlNet接收三通道[0,1]图,近处亮、远处暗。使用镜头固定近远距离n、f,先验证n、f为有限数且0<n<f,对有限正深度令C=clamp((1/D-1/f)/(1/n-1/f),0,1)并复制到RGB;n、f以米计,天空填零。非天空像素的深度为零、负数或非有限数时报告无效输入并停止本帧,修复深度后重试,避免除零或把坏数据静默当作远景。固定映射避免同一深度随着逐帧极值变化。该权重由估计深度训练,渲染逆深度提供结构条件,模型仍可能移动轮廓;几何对应成立不代表生成内容必然遵守对应。

本路线的法线参与历史拒绝与诊断,深度进入ControlNet,文本进入文本编码器。二者用途分开,代码无需一个未定义的“深度、法线和角色参考”接口。需要法线ControlNet时,增加独立权重并按该权重的坐标、朝向和RGB约定转换当前法线;其残差与深度残差相加。需要跨大转身保持身份时,另接参考图适配器的图像编码与交叉注意力,几何历史只覆盖可对应表面,不能提供背面身份信息。关键帧锚点负责把这些无历史表面纳入已确认外观。

起始噪声与步长

先令DDIM使用50步、timestep_spacing="leading"、steps_offset=0、prediction_type="epsilon"、clip_sample=False、set_alpha_to_one=True,并保留所用模型配置的训练噪声表。图生图强度取0.6,从末尾30步开始。训练1000步时,50步列表为980、960、…、0,本次起点是580而不是“第30步”。定义a_k为调度器在训练步k的累积alpha;对新采样的标准正态噪声ε:

zk=akzA+1−akϵz_k=\sqrt{a_k}z_A+\sqrt{1-a_k}\epsilon

调用set_timesteps(50)后截取timesteps[20:],以首项580调用add_noise,这样起点与实际迭代一致。强度过小会保留原渲染外观,过大则更容易改变局部身份;两个效果都来自起始信噪比,而不是随机种子是否相同。

每步预测与颜色投影

每一步将当前潜变量分别与负面提示词、镜头提示词送入ControlNet和UNet;负面提示词为空时就是空文本分支。ControlNet的深度残差权重固定为1,输入两份同一深度图;残差写入UNet的下采样块和中间块。两份噪声预测按ε̂=ε_negative+7.5(ε_text-ε_negative)合成;ε_negative对应负面提示词分支,负面提示词为空时才是空文本。这里的7.5是文本引导权重,1是结构残差权重,两者作用在不同数据上。

由噪声预测反推干净潜变量,解码成线性图P_k,再施加当前像素的历史约束:

P'_k=(1-\lambda M_t)P_k+\lambda M_tW_t$$ 教学权重λ取0.75,随后把`P'_k`整张重新编码为`z'_0`。接受位置的预测颜色0.4、历史0.8,投影为0.7;拒绝位置保持0.4。投影修正干净图,不把无噪声历史直接塞进带噪声的`z_k`。下一步k'用相同的本步噪声预测重建: $$z_{k'}=\sqrt{a_{k'}}z'_0+\sqrt{1-a_{k'}}\hat\epsilon$$ 这是本页明确定义的像素投影DDIM变体,随机步长η取零。它不是把官方`step`的结果再当作同噪声级别的图,也不是现有论文的完整复现。最后一步令`a_next=1`,输出干净图;解码后再作一次相同像素投影,让接受区域的颜色约束不被最后一次VAE重建削弱。最终投影控制直接复制,不能保证扩散网络完全忽略远处的历史上下文。 投影强会锁住纹理,也会保留历史里的错误。光照变化、非刚体不可靠区和镜头切换因此必须在构造M时撤去历史权重,不能依靠去噪器事后修正。反复解码、编码还增加每个去噪步的VAE成本,并可能累积细节损失;提高关键帧密度能缩短传播距离,代价是人工确认与额外生成。 ### 去噪循环实现 下面是机制片段,`pipe`是已加载上述权重的`StableDiffusionControlNetImg2ImgPipeline`,只处理一帧、一个样本。`A`、`W`为线性RGB张量,M为`1×1×H×W`二值张量,`control`为当前逆深度RGB。`encode_linear`依次执行sRGB传递、范围转换、`vae.encode(...).latent_dist.mode()*s`;`decode_linear`执行上述逆过程。线性分量x转sRGB时,x≤0.0031308用12.92x,否则用`1.055*x**(1/2.4)-0.055`;反向在s≤0.04045时用s/12.92,否则用`((s+0.055)/1.055)**2.4`。输入先截到[0,1],不对米单位深度应用颜色传递。 ```python # PyTorch / Diffusers 0.35.1,机制片段;在 torch.no_grad() 内执行。 scheduler.set_timesteps(50, device=device) steps = scheduler.timesteps[20:] # strength=0.6 text, negative = pipe.encode_prompt(prompt, device, 1, True, negative_prompt=negative_prompt) embeds = torch.cat([negative, text]) z_A = encode_linear(A) eps = torch.randn(z_A.shape, generator=generator, device=device, dtype=z_A.dtype) z = scheduler.add_noise(z_A, eps, steps[:1]) for i, k in enumerate(steps): x = scheduler.scale_model_input(torch.cat([z, z]), k) down, mid = pipe.controlnet( x, k, encoder_hidden_states=embeds, controlnet_cond=torch.cat([control, control]), conditioning_scale=1.0, return_dict=False) e = pipe.unet(x, k, encoder_hidden_states=embeds, down_block_additional_residuals=down, mid_block_additional_residual=mid).sample e0, e1 = e.chunk(2) e = e0 + 7.5 * (e1-e0) a = scheduler.alphas_cumprod[int(k)].to(z) clean = (z-(1-a).sqrt()*e)/a.sqrt() P = decode_linear(clean) projected = (1-.75*M)*P + .75*M*W clean = encode_linear(projected.clamp(0, 1)) if i+1 < len(steps): an = scheduler.alphas_cumprod[int(steps[i+1])].to(z) else: an = torch.ones((), device=z.device, dtype=z.dtype) z = an.sqrt()*clean + (1-an).sqrt()*e P = decode_linear(z) output = ((1-.75*M)*P + .75*M*W).clamp(0, 1) ``` 实现把模型全部移到同一设备,模型输入采用其权重精度;VAE若以float32运行,就在编码、解码边界显式转换,并把得到的潜变量转回UNet精度。`scheduler`使用上述DDIM配置并赋给`pipe.scheduler`。这里只支持epsilon预测,换成v预测时必须改反推公式,不能只换模型名。运行任务同时保存每一步的干净预览、M和W,才能分清错误来自对应、生成还是投影。 ## 实现与证据 链路数例和test_reference.py验证显露像素投影、起始训练步和下一步噪声级别;运行 `python -B 知识库/examples/mechanism_chain/video/test_reference.py` 可复现。模型接口按Diffusers 0.35.1源码核读;正文是教学用投影DDIM机制片段,尚未加载权重执行,未产出视频或质量评测。CPU标量关系通过不代表张量管线已经运行。 ## 相关主题 - [视频生成时序一致性](/knowledge/17_AIGC%E4%B8%8EAgent%E7%AE%A1%E7%BA%BF/%E8%A7%86%E9%A2%91%E7%94%9F%E6%88%90%E6%97%B6%E5%BA%8F%E4%B8%80%E8%87%B4%E6%80%A7) - [视频历史重投影](/knowledge/17_AIGC%E4%B8%8EAgent%E7%AE%A1%E7%BA%BF/%E8%A7%86%E9%A2%91%E5%8E%86%E5%8F%B2%E9%87%8D%E6%8A%95%E5%BD%B1) - [视频曝光与关键帧融合](/knowledge/17_AIGC%E4%B8%8EAgent%E7%AE%A1%E7%BA%BF/%E8%A7%86%E9%A2%91%E6%9B%9D%E5%85%89%E4%B8%8E%E5%85%B3%E9%94%AE%E5%B8%A7%E8%9E%8D%E5%90%88) - [视频生成任务恢复](/knowledge/17_AIGC%E4%B8%8EAgent%E7%AE%A1%E7%BA%BF/%E8%A7%86%E9%A2%91%E7%94%9F%E6%88%90%E4%BB%BB%E5%8A%A1%E6%81%A2%E5%A4%8D) - [ComfyUI工作流](/knowledge/17_AIGC%E4%B8%8EAgent%E7%AE%A1%E7%BA%BF/ComfyUI%E5%B7%A5%E4%BD%9C%E6%B5%81) - [抗锯齿与时域重建](/knowledge/02_GPU%E4%B8%8E%E5%85%89%E6%A0%85%E5%8C%96%E7%AE%A1%E7%BA%BF/%E6%8A%97%E9%94%AF%E9%BD%BF%E4%B8%8E%E6%97%B6%E5%9F%9F%E9%87%8D%E5%BB%BA) ## 参考资料 - [Diffusers 0.35.1 ControlNet图生图源码](https://github.com/huggingface/diffusers/blob/v0.35.1/src/diffusers/pipelines/controlnet/pipeline_controlnet_img2img.py):2026-10-23核读文本批次、深度残差注入与循环接口;[视频生成的逐步颜色约束](/knowledge/17_AIGC%E4%B8%8EAgent%E7%AE%A1%E7%BA%BF/%E8%A7%86%E9%A2%91%E7%94%9F%E6%88%90%E7%9A%84%E9%80%90%E6%AD%A5%E9%A2%9C%E8%89%B2%E7%BA%A6%E6%9D%9F)中的逐步像素投影独立定义。 - [Diffusers 0.35.1 DDIM源码](https://github.com/huggingface/diffusers/blob/v0.35.1/src/diffusers/schedulers/scheduling_ddim.py):同日核读时间表、epsilon反推与alpha关系。 - [深度ControlNet模型卡](https://huggingface.co/lllyasviel/sd-controlnet-depth):同日核读深度条件方向与基础模型要求。