CVPR 2024 SMIRK 论文解读:从单张图像重建更真实的 3D 人脸表情

📅 2026/6/27 8:14:21
CVPR 2024 SMIRK 论文解读:从单张图像重建更真实的 3D 人脸表情
CVPR 2024 SMIRK 论文解读从单张图像重建更真实的 3D 人脸表情如果你做过 3D 人脸重建会发现一个很常见的问题很多方法能把“脸型”重建得不错但一到表情就开始变味。比如嘴角微微上扬、单边眉毛挑起、夸张张嘴、脸部不对称挤压这些对人眼来说很明显但对传统 3D face reconstruction 方法来说很难。模型最后往往给出一个“平均脸 平均表情”看起来像人但不像输入图像里的那个人正在做的表情。SMIRK 这篇 CVPR 2024 论文要解决的就是这个问题。论文全名是SMIRK: 3D Facial Expressions through Analysis-by-Neural-Synthesis。SMIRK 是Spatial Modeling for Image-based Reconstruction of Kinesics的缩写目标是从单张或视频中的 2D 人脸图像里恢复更准确的 3D 表情几何尤其是那些极端、细微、不对称、训练集中较少出现的表情。项目主页https://georgeretsi.github.io/smirk/GitHubhttps://github.com/georgeretsi/smirkarXivhttps://arxiv.org/abs/2404.041041. SMIRK 想解决什么问题一句话概括SMIRK 想让 3D 人脸重建模型不只是“重建一张脸”而是更准确地重建“这张脸此刻的表情”。现有很多 monocular 3D face reconstruction 方法比如基于 FLAME 这类 3D Morphable Model 的方法会从图像中预测face shape身份相关的脸型expression表情参数pose头部姿态camera相机参数lighting / albedo光照和纹理相关信息然后通过 differentiable rendering把预测出来的 3D mesh 渲染回 2D 图像再和输入图像做对比。理论上如果渲染图像和输入图像越像说明 3D 重建越准。但问题在于这个监督信号太混杂了。渲染误差不仅来自表情几何也可能来自光照估计不准纹理估计不准相机参数不准occlusion / hair / teeth / tongue 等非模型部分differentiable renderer 和真实图像之间的 domain gap也就是说当模型看到“渲染图和原图不一样”时它并不知道到底应该改 expression还是改 lighting还是改 albedo。这会让表情学习变得很不稳定。2. 为什么 3D 表情重建这么难人脸表情的难点主要有三个。2.1 细微变化很重要表情不是只有“笑”和“不笑”。嘴角抬起一点、眼睛眯一点、法令纹深一点都会改变我们对表情的判断。但这些细节在 3D mesh 上可能只是很小的顶点位移。对 loss 来说不一定大对人眼来说却很明显。2.2 表情高度不对称真实人脸表情经常是不对称的。比如一边嘴角上扬一边眉毛皱起。很多模型容易学出偏平滑、偏平均的 expression因为训练数据和模型参数空间本身就鼓励“常见表情”。这就是为什么重建结果看起来经常“脸是对的表情差点意思”。2.3 极端表情在训练集中少张大嘴、夸张皱眉、强烈惊讶、用力挤脸这些表情在普通人脸数据集中比例不高。模型如果主要见到的是中性脸或轻微表情自然很难泛化到极端表情。SMIRK 论文也明确指出现有方法的两个关键问题是self-supervised training formulation 本身存在局限training images 中缺少足够多样的表情。3. SMIRK 的核心思路Analysis-by-Neural-SynthesisSMIRK 最关键的设计是它不用传统 differentiable rendering 作为主要重建监督而是引入一个neural rendering module。传统路线大概是输入图像 → 编码器预测 3D 参数 → differentiable renderer 渲染图像 → 和原图做 photometric lossSMIRK 的路线更像输入图像 → 编码器预测 3D 几何 → 提供 mesh geometry 从原图采样的稀疏像素 → neural renderer 生成重建图像 → 用生成图像和原图做监督区别在哪里传统 renderer 要自己解释颜色、光照、纹理、几何。SMIRK 的 neural renderer 可以从输入图像中采样颜色信息所以它不需要把所有 photometric 差异都压到 3D 几何上。换句话说SMIRK 让 reconstruction loss 更专注于几何尤其是表情几何。这是这篇论文里很重要的思想用 neural synthesis 来辅助 analysis让模型从图像中分析出更准确的 3D 表情。4. SMIRK 的模型结构怎么理解从 GitHub README 和论文描述看SMIRK 的编码器大致分成三个部分shape encoder预测身份相关的脸型pose encoder预测头部姿态expression encoder预测表情训练分两个阶段。4.1 预训练阶段预训练时SMIRK 使用 landmark 和 MICA 输出作为监督训练 shape、pose、expression 三个 encoder。README 里给出的命令是python train.py configs/config_pretrain.yamltrain.log_pathlogs/pretrain这个阶段可以理解为先让模型学会一个基本的 3D face reconstruction 初始化能力。4.2 核心训练阶段后续训练中SMIRK 会 freeze shape encoder 和 pose encoder重点训练 expression encoder。README 中的命令是python train.py configs/config_train.yaml\resumelogs/pretrain/first_stage_pretrained_encoder.pt\train.loss_weights.emotion_loss1.0这点很合理如果目标是更好地恢复表情那训练时就要减少身份和姿态的干扰让 expression branch 承担主要学习压力。5. SMIRK 为什么要生成“同一个身份的不同表情”这是 SMIRK 的另一个关键点。因为 neural renderer 可以利用输入图像的颜色信息SMIRK 能在训练时生成同一个 identity 下的不同 expression 图像。然后这些合成图像再作为 reconstruction model 的输入并用对应的 geometry 作为监督。这相当于做了一种 expression-level data augmentation。普通数据增强可能是cropflipcolor jitterrotation但这些增强不会真的增加“表情多样性”。SMIRK 通过 synthesis 路径生成不同表情相当于给模型看更多“同一个人做不同表情”的样本。这对学习极端表情、不对称表情、少见表情很关键。6. SMIRK 和传统 differentiable rendering 方法的区别可以用一个表格理解维度传统 3D face reconstructionSMIRK监督方式differentiable rendering photometric lossneural rendering reconstruction loss主要问题几何、光照、纹理、相机误差混在一起让 loss 更聚焦几何表情多样性依赖训练数据本身通过 synthesis 增强表情变化目标重建整体脸部更准确恢复 expressive 3D face优势场景常规脸型、普通表情细微、极端、不对称表情我自己的理解是传统方法像是在逼一个 renderer “什么都解释清楚”而 SMIRK 是把一部分 appearance 问题交给 neural renderer让 3D reconstruction module 更专心处理 geometry。这有点像把问题拆干净颜色归颜色几何归几何表情归表情。7. 如何运行 SMIRK官方 repo 提供了安装和 demo。首先需要 PyTorch 和 PyTorch3D。README 给的是 Python 3.9 CUDA 11.7 的环境conda create-nsmirkpython3.9pipinstall-rrequirements.txt pipinstall--no-index --no-cache-dir pytorch3d\-fhttps://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/py39_cu117_pyt201/download.html然后下载模型bashquick_install.sh这里有一个注意点SMIRK 依赖 FLAME model而 FLAME 需要注册下载。没有 FLAME 账号的话需要先去官网注册https://flame.is.tue.mpg.de/单张图像 demopython demo.py\--input_pathsamples/test_image2.png\--out_pathresults/\--checkpointpretrained_models/SMIRK_em1.pt\--crop视频 demopython demo_video.py\--input_pathsamples/dafoe.mp4\--out_pathresults/\--checkpointpretrained_models/SMIRK_em1.pt\--crop\--render_orig视频 demo 本质上是逐帧做人脸重建然后渲染结果。所以它可以用于从视频里恢复动态表情但 SMIRK 本身不是 text/audio-driven talking head generator。这一点很重要。8. SMIRK 适合用在什么任务SMIRK 比较适合这些场景。8.1 3D 表情重建如果你有一张图或一段视频希望恢复 3D face mesh 和表情参数SMIRK 是直接相关的方法。8.2 表情分析因为它强调 subtle / asymmetric / extreme expressions所以可以作为表情分析、facial behavior understanding 的前处理模块。8.3 Avatar / Digital Human如果你要驱动 3D avatarSMIRK 可以提供更准确的表情几何。但它输出的是 3D reconstruction不是最终 photoreal rendering。8.4 数据生成和表情增强SMIRK 的 synthesis 思路也可以启发数据增强不只是对图像做像素增强而是在 expression geometry 层面制造变化。9. SMIRK 不是什么这点也值得单独说因为很容易误用。SMIRK 不是不是 Stable Diffusion 那种图像生成模型不是 SadTalker / LivePortrait 那种直接生成说话视频的方法不是 audio-driven facial animation不是端到端 photoreal talking head system不是不依赖 3D face model 的方法它仍然和 FLAME 体系有关。它更准确的定位是一个面向 expressive 3D face reconstruction 的方法重点是从图像中恢复更忠实的 3D 表情几何。如果你的目标是做“照片动起来”“音频驱动数字人”“全脸真实视频生成”SMIRK 可以作为中间表情/几何估计模块参考但不是完整解决方案。10. 我对 SMIRK 的理解SMIRK 最有价值的地方不只是“效果更好”而是它指出了一个很本质的问题用 2D photometric reconstruction loss 去监督 3D face geometry本身就很脏。因为 2D 图像里混着太多因素。你想学表情但 loss 同时被光照、纹理、遮挡、相机、renderer domain gap 影响。这样训练出来的 expression 很容易平均化。SMIRK 的 analysis-by-neural-synthesis 思路是用一个 neural renderer 把 appearance 问题吸收掉一部分让 expression geometry 学得更干净。同时它又通过生成不同表情来补足训练数据里的 expression diversity。所以这篇论文的核心可以总结成两句话别让 photometric loss 同时管太多事。如果真实数据里的表情不够多就用 synthesis 路径制造更多表情监督。这两个思想对 3D face reconstruction、avatar animation、甚至更广义的 analysis-by-synthesis 任务都有参考价值。参考资料Retsinas et al.,SMIRK: 3D Facial Expressions through Analysis-by-Neural-Synthesis, CVPR 2024https://arxiv.org/abs/2404.04104SMIRK Project Pagehttps://georgeretsi.github.io/smirk/Official PyTorch Implementationhttps://github.com/georgeretsi/smirk