本文主要基于开源项目Face2face
[1](中间会提及到face3d
[2]和eos
[3]),对采用传统优化方法从二维图片拟合3DMM
的三维人脸重建算法整体流程做一个介绍。由于项目作者没有给出参考文献,笔者是从代码推论出来的整个算法,如有错误,欢迎指正。
一.算法流程
如图一所示,整个算法包含三个步骤,其中人脸关键点检测,用于获取二维图像上人脸的语义点,连同图片本身作为拟合问题的真值,而估计相机变换和估计身份、表情、纹理和光照系数则是拟合问题待求解的参数。
二.具体步骤
1.人脸关键点检测
项目中采用了dlib
或openpose
进行提取。非重点,这里就略过了。
2.估计相机变换参数
根据上述检测到的2D人脸关键点和当前估计的3DMM
人脸的3D关键点,采用黄金标准算法来估计相机变换参数,包括旋转、平移和尺度(对应项目代码位于face2face/optimize/camera.py)
。
当采用射影摄像机时,算法如下(见[4] P 123 P{123} P123)
当采用仿射摄像机时,算法如下(见[4] P 126 P_{126} P126)
与sfm
中估计基础矩阵或者本质矩阵的方法一样,这两种不同的相机模型下求解变换矩阵时也需要进行图像点和空间点归一化(见[4] P 122 P_{122} P122)
3.估计身份、表情、纹理和光照参数
构建目标函数
采用了投影2d关键点损失 E l a n d E_{land} Eland、像素损失 E p i x e l E_{pixel} Epixel和正则化损失 E i d / e x p / t e x r e g E_{id/exp/tex_{reg}} Eid/exp/texreg:
E t o t a l = w 1 E l a n d + w 2 E p i x e l + w 3 E i d r e g + w 4 E e x p r e g + w 5 E t e x r e g E_{total}=w_1E_{land}+w_2E_{pixel}+w_3E_{id_{reg}}+w_4E_{exp_{reg}}+w_5E_{tex_{reg}} Etotal=w1Eland+w2Epixel+w3Eidreg+w4Eexpreg+w5Etexreg
E l a n d = ∣ ∣ L 2 d p r e ( α i d , α e x p ) − L 2 d ∣ ∣ 2 2 E_{land}=||L2d_{pre}(α_{id},α_{exp})-L2d||^2_2 Eland=∣∣L2dpre(αid,αexp)−L2d∣∣22
E p i x e l = ∣ ∣ I p r e ( α i d , α e x p , α t e x , α s h ) − I ∣ ∣ 2 2 E_{pixel}=||I_{pre}(α_{id},α_{exp},α_{tex},α_{sh})-I||^2_2 Epixel=∣∣Ipre(αid,αexp,αtex,αsh)−I∣∣22
E i d r e g = ∣ ∣ α i d ∣ ∣ 2 2 / i d e v a l E_{id_{reg}}=||α_{id}||^2_2/id_{eval} Eidreg=∣∣αid∣∣22/ideval
E e x p r e g = ∣ ∣ α e x p ∣ ∣ 2 2 / e x p e v a l E_{exp_{reg}}=||α_{exp}||^2_2/exp_{eval} Eexpreg=∣∣αexp∣∣22/expeval
E t e x r e g = ∣ ∣ α t e x ∣ ∣ 2 2 / t e x e v a l E_{tex_{reg}}=||α_{tex}||_2^2/tex_{eval} Etexreg=∣∣αtex∣∣22/texeval
式中, α i d α_{id} αid 为形状估计参数, α e x p α_{exp} αexp 为表情估计参数, α t e x α_{tex} αtex 为纹理估计参数, α s h α_{sh} αsh球谐基底的估计权重参数, e x p e v a l exp_{eval} expeval 为3DMM
模型形状基底的特征值, 为3DMM模型表情基底的特征值, t e x e v a l tex_{eval} texeval为3DMM模型纹理基底的特征值。
求解方法
属于非线性最小二乘问题,可推导出该目标函数对于各 α \alpha α系数的jacobi
矩阵(见·face2face/optimize/image.py里面denseJointJacobian函数·),然后采用高斯牛顿法迭代求解即可。
注意点
1)以上是单帧图像的估计,Face2face
项目中首先是用3帧左右估计id, tex,exp,cam,sh等参数,然后固定id和tex,对剩余帧进行exp,cam,sh的跟踪。
2)Face2face
[1]在得到3DMM
的几何模型和每个几何点的RGB颜色后,直接采用了opengl的渲染管线来得到预测出的图像(见face2face/utils/opengl.py
里面的具体实现)。(当固定住像素和三角形的对应关系后,此步骤是可微分的)
3)face3d
[2]里面手写了光栅化(从NDC
空间到屏幕空间)这部分的代码,感兴趣的可以自行查看(见face3d/mesh_numpy/render.py
)。
4)光照模型-spherical harmonic
这里补充说下球谐光照模型,简单来说球谐为我们提供了一组在球面上的正交基底,类似于欧式空间的傅里叶基底,并且只需要取前9个基底就能很好的模拟我们的光照环境[6]:
上式中 ( x , y , z ) (x,y,z) (x,y,z)为点的法线,并且在看实现代码[1]、[2]时发现,在三维人脸重建领域通常会忽略式中基底前面的系数:
最终一个点的颜色的计算公式为 I ( p , n ) = λ ( p ) E ( n ) I(p,n)=λ(p)E(n) I(p,n)=λ(p)E(n) , p p p为三维点, n n n为点 p p p的法线, E ( n ) E(n) E(n)为根据法线 n n n计算得到的基底与 α s h α_{sh} αsh的乘积, λ λ λ是albedo也就是原始点的颜色,对应代码如下:
因为光照计算中涉及到法线,表明其对于身份系数有贡献,所以可以加入到优化项中来。
三.其它
对于侧脸的情况,目测[1]、[2]的重建效果都不会很好,而eos
[3]、[9]在实现的过程中对于轮廓点进行了特殊处理,其基本流程如下:
- 使用非轮廓点及其对应3d关键点,采用黄金标准算法估计姿态;
- 施加了上述估计的姿态之后,同样利用非轮廓点及其对应3d关键点,采用NNLS算法估计表情参数(注:该算法无法加表情参数约束);
- 对可见轮廓点一侧,对相应的3d关键点施加姿态之后,查找最近2d轮廓点;
而对不可见轮廓点一侧,根据[10]中介绍的法线方向变化和raycast
可见性检查计算得到3d轮廓点,然后查找最近2d轮廓点。注意这里2d轮廓点和3d轮廓点不是一对一的关系,会存在一个2d轮廓点对应多个3d轮廓点的情况;
将轮廓点与非轮廓点合并到一起后,先采用采用黄金标准算法估计姿态,然后采用[11]中算法估计形状参数(解析解),最后采用NNLS
算法估计表情参数(解析解)。注意整个步骤是迭代求解,因为需要更新轮廓点的对应。
注:笔者做实际项目时将这些方法的更新轮廓点方法加入到了损失项中,计算速度很慢,而且提升效果有限;另外还有个对于轮廓点的处理还有个叫landmark marching的方法,效果应该都差不多)
四.参考
[1]https://github.com/kimoktm/Face2face
[2]https://github.com/YadiraF/face3d
[3]https://github.com/patrikhuber/eos
[4]计算机视觉中的多视图几何-中文版,安大出版社,2002.8
[5]Face Recognition from a Single Training Image under Arbitrary Unknown Lighting Using Spherical Harmonics
[6]Inverse Rendering of Faces with a 3D Morphable Model
[7]3D Morphable Face Models - Past, Present and Future
[8]Hypochondria:有关opengl各种空间变换
[9]https://github.com/Yinghao-Li/3DMM-fitting
[10]Fitting a 3D Morphable Model to Edges: A Comparison Between Hard and Soft Correspondences
[11]Inverse Rendering of Faces with a 3D Morphable Model
最后,创作不易,如果对您有一点点帮助,希望可以给笔者点点关注、给个免费的赞or收藏or小心心,谢谢。