《Towards Fast, Accurate and Stable 3D Dense Face Alignment 》3DDFA-V2论文研读和工程实现

一:论文主要的4部分

在这里插入图片描述
1:使用轻量级网络,训练模型回归62个3DMM参数。
default output is dimension with length 62 = 12(pose) + 40(shape) +10(expression)
工程公布了mb05_120x120,mb05_120x120,resnet_120x120三个模型(mobilenet 0.5,mobilenet 1.0, resnet 1.0)
2:提出meta-joint optimization优化策略。
即动态组合fwpdc和vdc损失函数,加快拟合。
即使用一套元学习的方式,动态调整fwpdc与vdc的权重。
具体的骚操作是:
用vdc 微调 wpdc损失函数训练好的模型(或者用wpdc微调vdc)。即先使用wpdc损失函数同上进行训练模型 ; 保存模型的参数 ; 重新开始此次训练时,将神经网络模型的参数初始化为刚刚用wpdc训练好模型的参数,然后继续用vdc损失函数去训练该模型,如下图 所示。
在这里插入图片描述
在这里插入图片描述
(1)the Vertex Distance Cost(Vdc)
在这里插入图片描述
这里的parameter,即模型回归的62个3DMM参数(12(pose) + 40(shape) +10(expression))。
这里的V3d 表示使用62个3DMM参数计算3DMM头模上的点.
代码实现为:

pts3d = R @ (self.u_base + self.w_shp_base @ alpha_shp + self.w_exp_base @ alpha_exp). \
                    reshape(3, -1, order='F') + offset

这里的T为一个3X4的矩阵,存着pose系数。其中最后一个3X1矩阵表示偏移信息。

offset = R_[:, -1].reshape(3, 1)

在这里插入图片描述
基础头模。
使用模型预测出的参数,计算出人脸3D点P_pre,然后与头模上相同索引点的3D点(这些数据先前就已经存在PKL文件中),作L2范式loss。
(2)Fwpdc
在这里插入图片描述
计算回归出的3DMM参数与真实的3DMM参数在固定权重上的距离损失。
3:特征标记回归正则化
在全局池化层后面加一个回归68个2D点的回归分支。
4:短视频合成(不关注)

二:使用论文工程跑人脸3D点数据集

官方工程地址:https://github.com/cleardusk/3DDFA_V2

工程没有公布训练代码,只公布了测试demo,可以将该工程当作跑数据的工具,用来生成人脸3D点,效果还可以。
1:直接用论文公开的demo跑数据:
在这里插入图片描述
同一个人在不同角度,脸型在2D视觉上有差别。这种现象属于正常。2D视觉上没有结合深度信息,看起来会有视觉差,但是同一个人,不管视角怎么变,随意两个3D点,在3D空间中的关系不变。比如下图中,向量BA和向量BC的模长度不变,两者之间的夹角也不变。
所以,一个胖脸,俯视角度,视觉看起来脸变小属于正常.
在这里插入图片描述
2:将各个角度的脸摆正
即去掉头模中pose系数,可以直观比较脸型。
将pose 3*3矩阵预测的系数,改为初始化的单位矩阵。
代码需要更该的地方:

def recon_vers(self, param_lst, roi_box_lst, **kvs):
        dense_flag = kvs.get('dense_flag', False)
        size = self.size

        ver_lst = []
        inp_lst=[]
        for param, roi_box in zip(param_lst, roi_box_lst):
            R, offset, alpha_shp, alpha_exp = _parse_param(param)
            if dense_flag:
                inp_dct = {
    
    
                    'R': R, 'offset': offset, 'alpha_shp': alpha_shp, 'alpha_exp': alpha_exp
                }
                pts3d = self.bfm_session.run(None, inp_dct)[0]

                pts3d = similar_transform(pts3d, roi_box, size)
            else:
                a = [-(self.param_std[0] + self.param_mean[0]),0,0]
                b = [0,self.param_std[5] + self.param_mean[5],0]
                c = [0,0,-(self.param_std[10] + self.param_mean[10])]
               
                R2 = []
                R2.append(a)
                R2.append(b)
                R2.append(c)
                
                R2=np.array(R2)

                #d=np.array([self.param_std[3] + self.param_mean[3],self.param_std[7] + self.param_mean[7],self.param_std[11] + self.param_mean[11]])
                d=np.array([0,0,self.param_std[11] + self.param_mean[11]])
                #d=np.array([self.param_std[3] + self.param_mean[3],self.param_std[7] + self.param_mean[7],0])
                d=d.reshape(3, 1)

                pts3d = R @ (self.u_base + self.w_shp_base @ alpha_shp + self.w_exp_base @ alpha_exp). \
                    reshape(3, -1, order='F') + offset
                
                pts3d_front = R2 @(self.u_base + self.w_shp_base @ alpha_shp + self.w_exp_base @ alpha_exp). \
                    reshape(3, -1, order='F')+ d

               
                pts3d = similar_transform(pts3d, roi_box, size)
                pts3d_front = similar_transform(pts3d_front, roi_box, size)

            ver_lst.append(pts3d)
            inp_lst.append(pts3d_front)


        return ver_lst,inp_lst

效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/jiafeier_555/article/details/127307853
今日推荐