三维人脸重建:精读3dmm.py

该博客详细介绍了3D人脸模型的使用过程,包括加载BFM模型、生成3D顶点和颜色、坐标变换以及关键点拟合。通过随机参数生成形状和表情,将3D模型渲染为2D图像,并利用68个关键点进行反向的3D参数估计。文章涵盖了从3D到2D的变换以及2D到3D的逆变换,涉及到的关键技术包括PCA、纹理映射和坐标变换。
摘要由CSDN通过智能技术生成

  • 转载请注明出处

这个代码的主要内容就是根据一些随机的参数从3d模型渲染到2d图片
然后从图片再变换回去

代码解析

1. 载入模型
bfm = MorphabelModel('Data/BFM/Out/BFM.mat')

# 这里面初始化的参数有:
def __init__(self, model_path, model_type = 'BFM'):
        super( MorphabelModel, self).__init__()
        if model_type=='BFM':
            self.model = load.load_BFM(model_path)
   
        # fixed attributes
        self.nver = self.model['shapePC'].shape[0]/3 # 顶点的个数
        self.ntri = self.model['tri'].shape[0] # 三角形的个数
        self.n_shape_para = self.model['shapePC'].shape[1]  # 199
        self.n_exp_para = self.model['expPC'].shape[1] # 29
        self.n_tex_para = self.model['texMU'].shape[1] # 1
        
        self.kpt_ind = self.model['kpt_ind'] # 关键点索引
        self.triangles = self.model['tri']
        self.full_triangles = np.vstack((self.model['tri'], self.model['tri_mouth']))  # 按行堆叠, 例如两个(1, 3)成为(2, 3)

2. 生成mesh, 也就是一些点,三角形的集合
sp = bfm.get_shape_para('random')
ep = bfm.get_exp_para('random')
# 上面就是生成一些随机的形状与表情参数

vertices = bfm.generate_vertices(sp, ep) 
# 模型所有不包含颜色后加和的点

tp = bfm.get_tex_para('random')
colors = bfm.generate_colors(tp)
colors = np.minimum(np.maximum(colors, 0), 1)
  • 看看这个generate_vertices, 输入形状系数和表情系数,返回顶点, 大小是(nver, 3)
def generate_vertices(self, shape_para, exp_para):
        '''
        Args:
            shape_para: (n_shape_para, 1)
            exp_para: (n_exp_para, 1) 
        Returns:
            vertices: (nver, 3)
        '''
        vertices = self.model['shapeMU'] + self.model['shapePC'].dot(shape_para) +
         self.model['expPC'].dot(exp_para)
         # 这个求解的过程就是均值加上系数乘PCA降维后的基向量

        vertices = np.reshape(vertices, [int(3), int(len(vertices)/3)], 'F').T

        return vertices
  • 这个generated_colors是根据纹理系数生成颜色, 其实这里并没有对
    纹理也就是颜色做后续的fit, 只不过是用一个随机数乘了原来的系数
# 输入纹理系数, 返回颜色
    def generate_colors(self, tex_para):
        '''
        Args:
            tex_para: (n_tex_para, 1)  这个其实是1,1
        Returns:
            colors: (nver, 3)
        '''
        colors = self.model['texMU'] + 
        self.model['texPC'].dot(tex_para*self.model['texEV'])
# 这里是个随机的数乘原来的texEV
'''
texEV是纹理正交空间的系数, 大小是199*1
'''

        colors = np.reshape(colors, [int(3), int(len(colors)/3)], 'F').T/255.  
        
        return colors

3. 坐标变换
  • 指定了s, R, t等缩放旋转位移参数, 然后把3D的点变到2D
s = 8e-04
angles = [0, 0, 0]
t = [0, 0, 0]
transformed_vertices = bfm.transform(vertices, s, angles, t)
projected_vertices = transformed_vertices.copy() 
'''
这里应该就对应相机坐标系的变换, 相机坐标系和两个投影变换不要混了
'''
# using stantard camera & orth projection
h = w = 256; c = 3


# 这个是变换到图片坐标系上,x,y加上图片的一半, y轴反转
image_vertices = mesh.transform.to_image(projected_vertices, h, w)


# 这个在之前的精度中讲过, 就是利用重心坐标对颜色进行插值
'''
这个的返回值是image: [h, w, 3] , 三个通道是一样的
'''
image = mesh.render.render_colors(image_vertices, bfm.triangles, colors, h, w)
4. 使用68个关键点做fit
x = projected_vertices[bfm.kpt_ind, :2] 
 # 这个是相机坐标系下的人脸关键点
 
X_ind = bfm.kpt_ind  # index of keypoints in 3DMM. fixed. 

# fit 根据二维点来解出对应的3d参数叫fit
fitted_sp, fitted_ep, fitted_s, fitted_angles, fitted_t = bfm.fit(x, X_ind, max_iter = 3)


  • 这里的fit算法里面有个黄金标准算法, 网上没有讲的很深入的, 同时现在大多数是用深度学习的方法fit了, 这个先占坑

这里的fit结果有5个参数, 分别是形状, 表情, s, R, t

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

live_for_myself

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值