公司动态
FixAnything拆解:如何用视频生成先验实现三维一致渲染精化
FixAnything 这个名字最近在三维重建社区里经常被讨论。它要解决的是 3D-Consistent Rendering Refinement当 3D 场景里某个物体、某个视角或者整段渲染序列出现伪影时不再靠人工逐帧修图而是交给 Video Generative Priors 这种视频级生成先验去修复并保证修复结果在多个视角下仍然一致。这里的核心不是“把单张坏图变清楚”而是“让一段围绕三维场景渲染出来的视频在时间维度和空间维度都保持合理”。这篇文章不会复述某篇论文的官方实现而是把这类方法背后的共同链路、最小实验和排查方法拆开讲方便在实际渲染管线里落地。先从问题出发渲染一个三维场景时经常会出现三种伪影。一是几何穿模物体表面在特定视角下互相穿插二是材质噪点光线追踪采样不足导致画面颗粒感明显三是透明物体闪烁同一根头发、同一片玻璃在不同帧里表现不一致。传统做法是后期修图或者反复调渲染参数但如果是动画序列单帧修好下一帧可能又坏。视频生成先验能够一次性修整一段时间窗口内的帧利用相邻帧的信息约束一致性和真实性。因此FixAnything 强调的不只是“修复”而是“把生成先验转成渲染精化工具”。1. 为什么渲染精化需要视频生成先验1.1 渲染伪影从哪里来在 NeRF、3D Gaussian Splatting、传统网格渲染和光线追踪流程里伪影的产生路径完全不同但表现往往相似。NeRF 和 Gaussian Splatting 这类 3D 表示在训练不充分时会出现“雾状残影”和“漂浮物”。本质上是优化过程中没有足够视角约束导致空间里某个区域被赋予了过高或过低的密度。比如一个平面从正面看没问题从侧面看却出现半透明拖影。这不是贴图问题而是几何/密度分布问题单帧图像生成模型根本看不出原因是深度不对。传统渲染器的问题更常见。光线追踪需要采样数以千计的路径才能得到干净结果生产环境为了控制渲染时间通常只采样几十次或几百次于是阴影、景深和反射区域出现黑色或彩色噪点。另一个常见来源是 LOD细节层级切换。物体靠近相机时加载高模远离时切换低模低模和高模法线差异会导致画面跳变。这种跳变天然是时间维度的不可能用单张图修复。所以渲染精化面对的输入不是“一张质量差的静态图”而是“一段带有时间相关伪影的渲染序列”。如果只把问题理解成图像去噪、去模糊或超分后面的方案大概率会在帧间一致性上失败。1.2 图像生成先验为什么不够图像级生成模型或者图像修复模型输入是一张图输出是一张图。单看每一帧修复结果可能非常自然但把修复后的帧连起来播放问题就暴露了。原因在于同一三维表面在不同视角下颜色和纹理应该来自同一个物理属性。图像模型看不到这个约束它只会按照单帧视觉合理性去生成。比如一个木纹桌面上有一道渲染噪点第一帧模型给桌面生成了一道新的木纹第二帧模型认为该区域应该是一个浅色斑点第三帧又还原成木纹。三帧单独看都很正常连起来播放就是闪烁。视觉上容易被忽略的问题是“几何漂移”。图像修复模型改变像素位置后该像素对应的三维射线发生了变化。如果修复后的帧被用来继续训练 NeRF 或 Gaussian Splatting等于往三维场景里灌入了互相矛盾的观测。渲染器会为了迎合这些错误观测把密度场调成一团糊状。最终结果不是细节更清晰而是场景变得更脏。因此图像生成先验只能做“单帧观感修复”不能直接参与“三维一致的精化”。要让修复结果成为三维场景的新观测就必须保证多帧之间共享同一套几何和外观信息。1.3 视频先验带来的时间维度约束视频生成先验和图像生成先验的最大差异在于模型内部有时间注意力、光流约束或者三维卷积结构。这些模块在训练时见过大量真实视频会学习到“相邻帧内容不能突变”这个规律。把渲染序列当作视频输入时模型不只是逐帧生成像素还会判断当前帧和前后帧是否构成合理的运动。这种时间维度约束对三维渲染精化有三个直接帮助。第一闪烁被抑制。同一个三维点在不同视角下应该颜色一致视频模型在解码时会参考相邻帧因此不会每帧独立脑补出不同纹理。第二可以处理相机运动。围绕物体旋转的渲染序列中前景物体的缩放、旋转、遮挡都在连续变化。视频模型见过大量类似运动会倾向于生成符合运动规律的结果。第三可以作为可微监督信号。视频生成模型内部有噪声预测网络和去噪过程可以用类似扩散分数蒸馏的方式把它对视频合理性的判断转化成梯度直接引导三维表示更新。这个能力让“渲染精化”不再只是后处理而是能够参与三维重建的优化循环。2. 拆解标题背后的技术链路2.1 Fix 要定义清楚什么输入什么输出FixAnything 这个名字听起来很宽泛但工程实现必须有严格边界。修复任务的输入不是“任意坏模型”而是一段已经渲染出来的多视角图像序列通常还包含相机位姿、深度图或 alpha 通道。输出是精化后的图像序列要求保持原始分辨率、语义内容和相机轨迹不变。一个关键设计是“允许改哪里”。无约束的全局修复会让视频模型把原本正确的几何细节也改掉。更稳妥的做法是提供影响图例如伪影 mask、置信度图或采样次数图。光线追踪噪点通常出现在阴影边缘和金属反射区这些区域可以通过采样方差估算出来。穿模区域则需要结合深度图或者 mesh 检测。Fix 阶段要做的第一件事不是调用生成模型而是把需要修复的像素范围圈出来。在实际操作中可以用下面的抽象表示# 输入 rendered_frames: [T, C, H, W] fix_mask: [T, 1, H, W] # 1 表示需要修复0 表示保持原样 camera_poses: [T, 4, 4] # 输出 refined_frames: [T, C, H, W] confidence: [T, 1, H, W] # 修复结果置信度供下游渲染器使用mask 不一定要很精确。视频生成模型本身有一定抗噪能力粗糙的 mask 可以靠采样或膨胀处理。但完全没有 mask等于把画面的所有区域都交给模型自由发挥这在三维场景里非常危险。2.2 Anything类别无关的通用修复Anything 的含义是“不限定对象类别”。一个旋转的杯子、一个人物模型、桥梁结构、室内家具都应该能够在同一套管线里被修复而不需要为每个类别训练专用模型。实现类别无关有两个常见路径。第一种是使用大规模视频生成模型作为先验让模型在开放域视频数据上习得的纹理和结构知识发挥作用。第二种是在推理阶段不依赖文本 prompt更强调 condition 帧和 mask 的作用。这样模型不会把车门修成木板也不会把人体皮肤修成大理石纹理。需要注意的是通用先验不等于“一定正确”。当渲染场景属于工业零件、医学模型、建筑构件等少见类别时视频模型可能生成缺失或不合理的结构。这时需要在修复结果和原始渲染之间做插值或者限制去噪强度让模型只负责去除伪影不负责“重新发明”物体结构。2.3 3D-Consistent 的含义与验证方式三维一致不能只靠肉眼判断。它要求在同一个三维几何点被多个视角观测到的情况下修复后的颜色应该一致。用文字表达就是在世界坐标系中取一个物体表面点 P在视角 A 和视角 B 都可见时P 对应到修复后帧 A 的颜色应该和对应到修复后帧 B 的颜色接近。如果 P 的颜色在视角 A 下偏红在视角 B 下偏蓝说明修复过程已经破坏了三维一致性渲染器会同时接收到两个矛盾的光照信息。验证方式通常分成两种。一种使用相机位姿和多视角几何把帧 A 中的像素反投影到三维空间再投影到帧 B比较颜色差异。另一种使用光流计算相邻帧之间的运动场再把修复后帧 A 的像素运动到修复后帧 B比较误差。两种方法都需要除了图像之外的辅助信息这也说明渲染精化管线不能只有“视频模型 图像”两个部分。2.4 Video Generative Priors 在管线里的三个角色视频生成先验在渲染精化里可以担任三种角色实际项目通常是多种角色混合。第一种是后处理修复器。渲染完成后先把序列切成窗口送进视频模型得到修复序列再合成回去。这种方式对已有渲染器侵入最小生产环境最容易接入。第二种是可微监督器。在训练三维表示时对当前渲染出的视频窗口计算视频扩散模型的噪声预测损失梯度回传到 3D 表示参数。这种方法和常见扩散分数蒸馏类似适合在 NeRF 或 Gaussian Splatting 这类可微渲染器上使用。第三种是伪标签生成器。视频模型不是直接参与梯度回传而是先修复出高质量帧再把修复帧当作新的 ground truth继续微调三维表示。这种方式适合外部渲染器、游戏引擎或闭源软件缺点是有可能把模型生成的错误纹理固化到三维场景里。无论选择哪种角色都要在管线中加入“一致性回读”步骤修复后的帧必须重新渲染或重投影到三维空间验证它和周围视角是否协调。如果这一步缺失修复结果很容易出现“单帧好看、多视角崩溃”。3. 搭建一个最小可运行管线3.1 环境依赖和项目结构下面这套最小管线假设已经有一个可用的视频生成先验模型重点展示如何把渲染序列、mask、相机位姿和三维表示串起来。代码是流程骨架实际项目需要根据模型仓库和渲染接口调整。一个建议的目录结构如下fixanything-demo/ ├── configs/ │ └── refine.yaml ├── data/ │ └── render_views/ │ ├── frame_0001.png │ ├── frame_0002.png │ └── poses.txt ├── models/ │ ├── video_prior.py │ └── renderer_adapter.py ├── pipeline.py ├── metrics.py └── README.md最小依赖可以写在requirements.txt中torch2.0.0 torchvision0.15.0 opencv-python4.8.0 numpy1.24.0 pyyaml6.0 tqdm4.65.0如果使用 Hugging Face diffusers 或 ComfyUI 这类工具链还需要额外安装对应依赖。落地前建议先确认视频生成模型的加载方式因为不同仓库的 API 差异很大。配置文件configs/refine.yaml可以长这样data: frame_dir: data/render_views img_ext: png frame_start: 0 frame_end: 72 window_size: 8 overlap: 2 prior: model_id: your-video-prior-model device: cuda denoise_strength: 0.6 cfg_scale: 1.0 num_inference_steps: 20 refinement: consistency_lambda: 0.5 lr: 0.001 max_iterations: 1003.2 准备测试数据先跑通再追求效果测试数据不建议一开始就用复杂场景。可以先渲染一段绕物体旋转的序列固定相机高度物体放在中心画面不要有太复杂的遮挡关系。这样便于排查是修复模型的问题还是相机位姿对齐的问题。如果使用 Blender 渲染命令行可以类似blender -b scene.blend \ -o data/render_views/frame_ \ -F PNG \ -E CYCLES \ --frame-start 1 \ --frame-end 72 \ -a注意不同 Blender 版本对参数略有差异。核心是保证输出连续帧的相机路径固定且每个 png 文件都带完整 alpha 通道。alpha 在后续生成 mask 时会非常有用。建议准备三组数据干净参考序列用于衡量最终效果离理想结果有多远。带噪序列模拟采样不充分导致的渲染噪点。缺失区域序列通过挖掉部分像素模拟穿模或遮挡问题。三组数据都使用同一套相机位姿否则所有指标对比都无效。3.3 封装视频先验模型接口视频生成模型的接口不能写死因为不同开源仓库的 pipeline 差异很大。可以在自己的工程里封装一个VideoPrior类把实际模型加载和推理藏起来。# models/video_prior.py from dataclasses import dataclass import torch dataclass class VideoPriorConfig: model_id: str your-video-prior-model device: str cuda denoise_strength: float 0.6 cfg_scale: float 1.0 num_inference_steps: int 20 class VideoPrior: def __init__(self, cfg: VideoPriorConfig): self.cfg cfg self.model self._load_model(cfg.model_id, cfg.device) def _load_model(self, model_id, device): raise NotImplementedError(替换为实际视频生成模型的加载逻辑) def repair( self, frames: torch.Tensor, mask: torch.Tensor, condition_frame: int 0, ) - torch.Tensor: # frames: [T, C, H, W], value range 0-1 # 返回修复后的帧范围 0-1 raise NotImplementedError(替换为实际 video prior 推理逻辑)这个接口会让后面的 pipeline 更干净也能方便替换模型。3.4 用光流或深度图做帧间对齐视频模型输出的结果要用于三维精化必须知道帧与帧之间哪些像素对应同一个物体点。获取对应关系有两种常见方式。第一种是渲染器直接输出深度图。给定相机内参和位姿可以把帧 A 的像素反投影到世界坐标再投影到帧 B。缺点是深度图本身可能在有几何缺陷的区域不可靠。第二种是使用光流模型估计运动场。光流模型不依赖三维几何适合未校准的渲染序列。但光流在遮挡边界会产生错误需要前后向一致性检查。下面是一个简化版光流 mask 计算思路# models/optical_flow.py import torch def forward_backward_flow_mask(flow_ab, flow_ba, threshold0.6): # flow_ab: 从 A 到 B 的光流 # flow_ba: 从 B 到 A 的光流 b, _, h, w flow_ab.shape yy, xx torch.meshgrid( torch.arange(h, deviceflow_ab.device), torch.arange(w, deviceflow_ab.device), indexingij, ) base torch.stack([xx, yy], dim0).float() warped base flow_ab warped warped.round().long() mask (warped[:, 0] 0) (warped[:, 0] w) (warped[:, 1] 0) (warped[:, 1] h) return mask真正落地时建议使用已经开源的光流模型并保存中间结果避免每次都重新计算。3.5 回传精化结果到渲染器管线主循环可以设计为for step in range(cfg.refinement.max_iterations): batch load_window(step) repaired video_prior.repair(batch[frames], batch[mask]) loss content_loss(repaired, batch[frames]) loss cfg.refinement.consistency_lambda * temporal_loss( batch[frames], repaired, batch[flow] ) if renderer.is_differentiable(): renderer.optimizer.zero_grad() loss.backward() renderer.optimizer.step() else: save_pseudo_gt(repaired, batch[view_ids]) renderer.finetune_from_pseudo_gt(batch[view_ids])这段逻辑强调的是不能把repaired直接当作最终结果也不应该直接覆盖原始渲染。它需要经过损失函数约束再决定是回传梯度还是生成伪标签。4. 关键代码与参数解释4.1 读取渲染批次窗口读取需要同时拿到图像、相机位姿、mask 和可选光流。这里用一个简化版Dataset示例import cv2 import numpy as np import torch from torch.utils.data import Dataset class RenderWindowDataset(Dataset): def __init__(self, paths, window_size, overlap0): self.paths paths self.window_size window_size self.overlap overlap self.stride window_size - overlap def __len__(self): return max(1, (len(self.paths) - self.window_size) // self.stride 1) def __getitem__(self, idx): start idx * self.stride end start self.window_size frames [] masks [] for i in range(start, end): img cv2.imread(self.paths[i], cv2.IMREAD_UNCHANGED) img cv2.cvtColor(img, cv2.COLOR_BGRA2RGB) / 255.0 frames.append(img[..., :3]) alpha img[..., 3] masks.append((alpha 0.5).astype(np.float32)) return { frames: torch.from_numpy(np.stack(frames)).permute(0, 3, 1, 2).float(), masks: torch.from_numpy(np.stack(masks)).unsqueeze(1).float(), }这里把 alpha 低于 0.5 的区域当作需要修复的区域只是一个示例。实际项目中 mask 可能来自采样方差异常、深度不连续或手动标注。4.2 视频先验推理与数值范围视频生成模型对输入数值范围非常敏感。有的模型要求输入在[0, 1]有的在[-1, 1]。在封装VideoPrior.repair时要在入口统一转换在出口统一还原。def repair(self, frames, mask, condition_frame0): # 进入模型前转成 [-1, 1] frames_input frames * 2.0 - 1.0 mask_input mask # 视模型要求决定是否需要拼接到通道上 output self.model( framesframes_input, maskmask_input, condition_framecondition_frame, denoise_strengthself.cfg.denoise_strength, num_inference_stepsself.cfg.num_inference_steps, ) # 模型输出转回 [0, 1] repaired (output 1.0) / 2.0 return repaired.clamp(0.0, 1.0)denoise_strength控制模型对输入帧的保留程度。设置过高模型会重新生成更多内容修复力度大但容易偏离原始几何设置过低修复效果不明显。因此这个参数需要根据伪影严重程度调整不是一个固定值。4.3 时序一致性损失时序一致性损失的核心思想是修复后的帧经过光流对齐后应该和相邻修复帧保持一致。def temporal_consistency_loss(repaired, flow_fw, occ_mask): t repaired.shape[0] src repaired[: t - 1] dst repaired[1:] warped warp_flow(src, flow_fw) # 需要自己实现 warp 函数 diff (warped - dst).abs().mean(dim1, keepdimTrue) # [T-1, 1, H, W] loss (diff * occ_mask).sum() / (occ_mask.sum() 1e-6) return losswarp_flow可以使用 PyTorch 的grid_sample实现。occ_mask来自光流前后向一致性检查用于屏蔽遮挡区域。如果不加occ_mask遮挡边界处会产生非常大的错误损失视频模型会被迫修改本来正确的边缘。时序一致性损失不能单独使用。它只能保证帧间变化平滑但可能让所有帧一起偏离真实三维结构所以必须和内容损失一起用。consistency_lambda就是这个权衡系数。4.4 关键参数速查表参数含义示例值调大影响调小影响window_size一次送入视频模型的帧数8时序信息更足但显存占用高时序约束弱容易闪烁overlap相邻窗口重叠帧数2融合更平滑计算量增加窗口边界可能出现跳变denoise_strength视频先验去噪强度0.6修复能力强过度生成风险高更保守伪影残留多num_inference_steps采样步数20质量可能提升推理变慢结果粗糙consistency_lambda时序一致性损失权重0.5帧间更平滑但可能丢失真实细节单帧更自由易闪lr三维表示更新步长0.001优化快容易震荡稳定但慢mask_threshold判定伪影像素的阈值0.5mask 大修改区域多mask 小只改强伪影这些数值只作为初始参考。不同视频模型、不同分辨率、不同场景的合适区间可能差异很大需要通过小规模实验扫描。4.5 三种常见的错误设计第一种错误设计是“整段视频一口气修复”。很多人会以为视频模型天然能处理任意长度视频但显存和时序感受野都有限。正确做法是滑动窗口窗口之间要有重叠并在重叠区域做加权融合。第二种错误设计是“不同窗口独立并行不做重叠融合”。每个窗口采样随机性不同窗口 A 修复的纹理和窗口 B 修复的纹理可能接不上最终在窗口边界出现硬切。修复时必须让相邻窗口共享至少 1 到 2 帧并设置固定随机种子。第三种错误设计是“把修复帧直接作为 ground truth 继续训练三维表示”。修复帧只是先验给出的“合理猜测”它可能不是真实几何。直接当 ground truth 使用会把模型幻觉固化到三维场景里。正确做法是保留原始渲染帧作为内容约束或者用 confidence 图限制修复帧的影响范围。5. 运行验证怎么看精化有没有生效5.1 先做定性检查定量指标再漂亮也要先肉眼过一遍。把修复前后的序列分别合成视频循环播放重点看以下位置物体边缘和背景交界处有没有出现“爬动”的毛边。高光和镜面反射区域是否出现颜色漂移。透明物体内部是不是被模型补成了实心材质。相机快速旋转时背景是否稳定。干净区域是否被过度涂抹。如果干净区域被修改说明 mask 太粗或者denoise_strength太高。第一轮验证不应该追求指标最优而应该先确认“修改被限制在合理位置”。5.2 定量指标单帧指标和时间一致性指标常用单帧指标包括 PSNR、SSIM 和 LPIPS。PSNR 对像素级误差敏感SSIM 对结构相似度敏感LPIPS 更接近人的感知。这三个指标分别计算修复后帧与参考干净帧的差异。但单帧指标无法反映闪烁。需要额外计算时间一致性指标。最常见的是 warped error把修复后帧 t 用光流对齐到帧 t1再计算与修复后帧 t1 的像素差异。# metrics.py def compute_warp_error(frames, flow_fw, occ_mask): t frames.shape[0] errors [] for i in range(t - 1): warped warp_flow(frames[i].unsqueeze(0), flow_fw[i]) diff (warped - frames[i 1].unsqueeze(0)).abs() diff diff * occ_mask[i] errors.append(diff.mean().item()) return sum(errors) / len(errors)发布结果时建议同时报告单帧指标和时间一致性指标。只有单帧指标高而 warped error 高说明结果只是“每帧好看播放闪”。5.3 保存中间结果和可视化中间结果必须保存否则后期排查时无法判断是哪一步引入的问题。建议输出以下目录output/ ├── refined/ │ ├── frame_0001.png │ └── frame_0002.png ├── masks/ │ ├── frame_0001.png │ └── frame_0002.png ├── metrics.json └── logs/合成 mp4 可以方便播放ffmpeg -framerate 30 -i output/refined/frame_%04d.png \ -c:v libx264 -pix_fmt yuv420p refined.mp46. 常见问题排查6.1 视频先验把干净区域也改了现象修复后原本没有伪影的地面纹理、字体边缘、细小结构全部变糊或变形。可能原因输入没有使用 mask或者 mask 范围过粗denoise_strength设置过高导致整帧被重新生成输入窗口没有提供足够的 condition 帧模型缺少保留内容的依据。检查方式对比原始帧和修复帧查看差异集中在 mask 外还是 mask 内降低denoise_strength后重跑把 mask 可视化输出确认纹理区域没有被错误标为 1。处理建议传入更精确的 mask 或 confidence 图使用较小的denoise_strength如果模型支持 condition 帧强制保留第一帧或中心帧不变只允许其他帧在可见范围变化。6.2 帧之间闪烁没有消除现象单帧看很干净播放视频时出现亮度跳动、纹理闪烁。可能原因每个窗口独立推理随机种子不一致窗口重叠区域没有做融合视频模型本身没有使用时序注意力输入帧没有按相机轨迹排序而是按文件名字典序排序导致运动跳跃。检查方式查看窗口切分方式确认相邻窗口是否共享帧检查视频模型是否真的接收多帧打印光流确认帧间运动是否连续。处理建议所有窗口固定随机种子在重叠区域做线性加权或基于置信度的融合确认输入排序方式是文件名的数字顺序而不是字符串顺序。6.3 精化结果和原渲染不一致现象修复后物体的细长结构消失或者新增了不存在的结构。可能原因内容损失权重太低时序一致性损失过大视频模型对少见结构没有先验认知mask 把结构边缘完全覆盖模型失去了几何提示。检查方式查看 loss 曲线确认内容损失和时序损失是否在同一个量级把修复帧和原渲染帧做差分可视化检查修复后的物体边界是否发生位移。处理建议提高内容损失权重减少consistency_lambda在 mask 中保留结构边缘的少量原图信息对少见类别使用 LoRA 微调或少量参考帧提示。6.4 显存 OOM现象模型推理到某个窗口时 CUDA out of memory。可能原因窗口太大输入分辨率过高采样步数多但中间结果没有释放开了过多梯度图。检查方式用nvidia-smi查看推理前后显存变化记录每个窗口的峰值显存。处理建议降低window_size降低推理分辨率后超分回原图开启混合精度把光流和深度图放在 CPU对视频模型使用 CPU offload 或者分块解码。学习环境可以单窗口跑通但生产环境必须把窗口调度做成异步队列避免请求突增导致 OOM。6.5 多视角接缝明显现象在同一个三维物体的不同视角切换时颜色和纹理出现明显接缝仿佛物体被分成几块不同材质。可能原因不同窗口被视频模型修复成不同纹理后续三维优化没有把多视角观测联合起来相机位姿本身存在误差。检查方式找到接缝两侧对应的三维点观察各自视角下的修复帧固定同一三维点比较不同视角的颜色。处理建议把同一物体的多个窗口送进同一个视频模型调用而不是逐窗口独立处理在三维优化阶段使用重投影颜色一致性 loss对边缘区域降低修复置信度。以下排查表可以直接贴在项目文档里问题现象常见原因检查方式处理建议干净区域被修改mask 太粗或 denoise 太高可视化 mask 与差分图收紧 mask降低 denoise视频仍然闪烁窗口独立采样检查窗口重叠和随机种子固定 seed窗口重叠融合几何结构消失内容损失太小查看 loss 曲线提高内容损失权重显存 OOM窗口和分辨率过大nvidia-smi 监控缩小窗口混合精度多视角接缝不同窗口纹理不统一重投影对比颜色联合推理增加一致性 loss7. 最佳实践与扩展方向7.1 学习环境与生产环境的差距学习环境跑通的最小管线通常只有几十帧、单一场景、低分辨率。生产环境接入时需要额外考虑五件事。第一任务队列。视频先验推理很慢不能放在渲染主线程同步调用。生产管线要把渲染帧、mask、相机位姿打包成任务由后台 worker 消费。第二结果缓存。同一个渲染版本、同一个相机路径不要重复修复。任务消息里要带上场景版本号和帧范围方便做结果复用。第三可观测性。不仅要记录修复耗时还要记录每个窗口的denoise_strength、随机种子、模型版本和指标。否则一个窗口出了问题无法回溯。第四灰度开关。先让视频先验处理低风险区域比如只处理边缘噪点确认稳定后再逐步开放到更难的区域。第五回滚。修复过程可能恶化画面必须保留原始渲染帧和配置快照。回滚时直接切回原渲染而不是依赖模型再修复一次。7.2 可复用检查清单下面这份清单适合在每次跑实验前过一遍。输入帧是否按相机轨迹正确排序。相机位姿单位是否统一是否和渲染器一致。图像数值范围是否统一模型输入输出转换是否对称。mask 是否覆盖了所有需要修复的区域是否泄漏到干净区域。窗口之间是否有重叠重叠宽度是否足够融合。随机种子是否固定便于复现。denoise_strength是否根据伪影严重程度调整过。是否同时保存了原始渲染帧和修复帧。是否计算了单帧指标和时间一致性指标。是否人工播放了修复前后视频而不是只看数值表格。修复帧是否经过三维重投影验证。模型版本和配置文件是否已经记录到日志。7.3 可以继续做的方向如果当前管线已经能稳定修复一段旋转序列下一步可以尝试把相机位姿作为显式条件输入视频模型。很多渲染抖动和相机运动有关模型如果知道当前帧的相机朝向更能区分“物体移动”和“相机移动”。也可以引入深度先验。渲染器输出的深度图即使有噪声也比纯视觉模型估计的深度可靠。用深度图约束重投影能显著减少多视角接缝问题。还可以针对自己团队的资产微调视频先验。开放视频模型对通用物体效果好但对特定风格角色、工业零件不一定稳定。微调 LoRA 时不需要重新训练整个模型成本可控。FixAnything 的真正难点不在于引入大模型而在于如何让大模型输出和三维几何对齐。谁把修补的“概率”变成三维的“约束”谁就能把这套流水线落地。