See-through核心实现原理(二):Marigold如何为动漫估计伪深度?2D→3D权重转换技术拆解
【免费下载链接】see-through"Single-image Layer Decomposition for Anime Characters" (SIGGRAPH 2026 Conference Paper)项目地址: https://gitcode.com/gh_mirrors/se/see-through
See-through 是 SIGGRAPH 2026 收录的动漫角色单图图层分解项目,能将一张静态动漫插画自动拆解为最多 23 层可编辑图层。本篇聚焦其中最关键的深度环节:Marigold 扩散深度估计模型如何为动漫角色生成"伪深度",以及项目独创的2D→3D 权重转换技术——只改配置文件就能让 2D 深度网络"长出"帧间注意力,且转换后输出与 2D 模型完全一致。
上图为 See-through 的代表效果:左侧是原始插画I与重合成结果R,右上方是带透明通道的语义图层(hair、face、topwear、tail……),右下角正是 Marigold 输出的伪深度图(Spectral 伪彩着色)。
为什么动漫图层分解需要"伪深度"?
动漫插画是纯 2D 的,但图层分解本质上是个遮挡排序问题:尾巴压住桌沿、刘海盖住眼睛、手伸在衣服前面……谁在上谁在下,全靠深度关系判断。
See-through 的解法是:用 Marigold 这类单目深度估计模型给每个图层估计一张"伪深度"(pseudo-depth)。注意"伪"字——它不追求真实米制距离,只关心相对远近,足以让后续模块决定 23 个图层的堆叠顺序。
Marigold 深度流水线:4 步扩散式推理
深度推理的核心是 MarigoldDepthPipeline,它把"估计深度"改写成了一道条件去噪题:
| 步骤 | 做什么 | 关键实现 |
|---|---|---|
| 1️⃣ 条件编码 | 输入图像经 VAE 编码为 4 通道潜变量(latent) | encode_rgb(),缩放系数 0.18215 |
| 2️⃣ 加噪去噪 | 从噪声出发,U-Net 以图像潜变量为条件,仅4 步 DDIM去噪出深度潜变量 | single_infer() |
| 3️⃣ 深度解码 | 深度潜变量经 VAE 解码回图像空间,得到 0~1 归一化深度 | decode_depth() |
| 4️⃣ 集合投票 | 多次推理取中位数(ensemble),输出MAD不确定度 | ensemble_depth |
几个对新手友好的设计点:
- 默认只要 4 步去噪:
default_denoising_steps=4,比传统扩散模型快一个量级,单图推理约分钟级; - 批量大小自适应:显存不够时 find_batch_size 会自动降 batch,不用手动调参;
- 3D 模型自动切换:当 U-Net 是
UNetFrameConditionModel时走多帧分支,同一套 pipeline 直接复用于 3D 模型(见下文)。
多分辨率噪声:给动漫细节"打补丁"
动漫线稿边缘锐利,普通高斯噪声偏"高频均匀",不利于恢复细线。multi_res_noise.py 采用 Multi-Resolution Noise:在多个尺度上叠加随机噪声再上采样混合,strength=0.9衰减权重,让噪声自带从粗到细的结构,去噪时线条更稳。训练配置 test_marigold3d.yaml 中downscale_strategy: original即对应这套策略。
为动漫微调:伪深度训练数据从哪来?
Marigold 原版在真实照片上训练,直接拿来跑动漫会"脑补"出照片式透视。See-through 的做法是在 train_marigold3d.py 中以Depth-Anything-V2-Large为基座微调:
- 数据合成:用 Live2D 模型渲染出多深度、多部件的帧序列(
live2d_bodysamples),得到动漫风格下有真值的深度对; - 19 类部件标签:hair、face、eyes、topwear、tail、wings……训练时按
mix_tag_groups分层组合部件,模拟真实插画的堆叠关系; - 损失与评测:
mse_loss监督,验证指标含abs_relative_difference、delta1/2/3_acc等标准深度评测指标,配置见 test_marigold3d.yaml。
2D→3D 权重转换:一行配置差异的"魔法"
这是本篇最硬核的部分。要让深度估计感知图层之间的帧间关系(3D),朴素做法是重训一个全新 3D 网络——贵。See-through 的 cvt_marigold2d_to_3d.py 给出了巧妙方案:
第一步:只换块类型,权重照搬。对比两份配置文件的down_block_types:
- 2D 版 marigold.json:
CrossAttnDownBlock2D×3 +DownBlock2D - 3D 版 marigold3d.json:
CrossFrameAttnDownBlock×3 +DownBlock2D
块结构变了,但2D 部分的卷积权重原样载入微调后的 2D checkpoint;新增的帧间注意力模块用zero_module零初始化(见 layerdiff3d.py)。
第二步:等价性验证。转换脚本用同一份随机输入分别过 3D 模型和 2D 模型,打印输出差 cvt_marigold2d_to_3d.py#L99:
零初始化的帧间注意力对输出贡献为 0 → 转换后 3D 模型的输出与 2D 模型逐像素一致,差值应趋近 0。
第三步:渐进微调。有了热启动,train_marigold3d.py 只需小学习率(4e-5)在 Live2D 多帧数据上微调,让帧间注意力"长"出来,代价远低于从头训练。
同样的思路还体现在输入通道扩展上:patch_unet_convin 给conv_in追加通道时新通道权重填零,保证扩通道瞬间模型行为不变——"先等价、再学习"是这套转换技术的核心哲学。
上图是配套 UI 中部件标签的工作画面:Marigold 估计的伪深度与 19 类部件标签配合,共同决定图层的绘制顺序。
相关模块速查表
| 模块 | 路径 | 作用 |
|---|---|---|
| 深度推理流水线 | common/modules/marigold/marigold_depth_pipeline.py | VAE 编码 + 4 步去噪 + ensemble |
| 多分辨率噪声 | common/modules/marigold/multi_res_noise.py | 结构化加噪,利于动漫线条 |
| 3D 帧间注意力 U-Net | common/modules/layerdiffuse/layerdiff3d.py | UNetFrameConditionModel |
| 2D→3D 转换脚本 | training/scripts/cvt_marigold2d_to_3d.py | 换块 + 零初始化 + 等价性验证 |
| 3D 微调脚本 | training/train/train_marigold3d.py | 动漫伪深度微调 |
| 3D 训练配置 | training/configs/test_marigold3d.yaml | 数据、噪声、损失、评测指标 |
| 2D/3D 模型配置 | marigold.json / marigold3d.json | 块类型差异所在 |
小结
See-through 的深度链路可以一句话概括:用扩散模型把"看深度"变成"画深度",用零初始化 + 配置替换让 2D 权重无损升级为 3D,再用动漫合成数据微调出可靠的伪深度。这套"先等价、再学习"的权重转换思路,对任何想给现有 2D 扩散模型加时序/多帧能力的同学都有借鉴价值。
【免费下载链接】see-through"Single-image Layer Decomposition for Anime Characters" (SIGGRAPH 2026 Conference Paper)项目地址: https://gitcode.com/gh_mirrors/se/see-through
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考