(简单易懂PRNet)Joint 3D Face Reconstruction and Dense Alignment with position Map Regression Netw

原文链接:[https://blog.csdn.net/yfy1127yfy/article/details/102839840?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162736575416780261967321%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162736575416780261967321&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-6-102839840.first_rank_v2_pc_rank_v29&utm_term=Joint+3D+Face+Reconstruction+and+Dense+Alignment+with+Position+Map+Regression+Network&spm=1018.2226.3001.4187]
(https://blog.csdn.net/yfy1127yfy/article/details/102839840?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162736575416780261967321%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162736575416780261967321&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-6-102839840.first_rank_v2_pc_rank_v29&utm_term=Joint%203D%20Face%20Reconstruction%20and%20Dense%20Alignment%20with%20Position%20Map%20Regression%20Network&spm=1018.2226.3001.4187)
Github项目链接:https://github.com/YadiraF/PRNet
训练数据300W-LP,ground-truth是没有用UV表示的,所以要用3DMM系数先生成UV训练数据。再根据损失函数,最后模型输出的也是UV-map图。

2019/10/31,想起来之前看的没做笔记,重新总结下吧。

论文地址:http://openaccess.thecvf.com/content_ECCV_2018/papers/Yao_Feng_Joint_3D_Face_ECCV_2018_paper.pdf

github地址:https://github.com/YadiraF/PRNet

摘要

本文提出一种直接的方法,来实现3D人脸重建和稠密对齐。设计了一种2D表达,称之为UV坐标图,可以在UV空间保存完整的人脸3D形状。然后就可以训练CNN网络从一张2D图回归出3D形状。

一、简介

早期的3D重建和稠密对齐研究中,使用过2D关键点,但2D关键点无法处理大角度和遮挡;

使用了3DMM方法,又受限于透视投影和3D样条曲线(3D ThinPlate Spline)的计算量大;

有的端到端方案,摆脱了这些限制,但需要额外的网络来估计深度信息,且并没有提供稠密对齐;

VRN提出了体素表示法,该方法计算量大,分辨率低,且由于点云稀疏特性,存在大量无效计算。

本文提出了一种端到端的PRN多任务方法,能够同时完成稠密人脸对齐和3D人脸形状重建。主要几个贡献:

  1. 以端到端方式,实现了高分辨率的3D人脸重建和稠密对齐;
  2. 设计了UV位置图,来记录人脸的3D位置信息;
  3. 设计了权重掩模用于loss计算,loss中每个点权重不同,可明显提高网络性能
  4. CNN采用轻量级模式,单张人脸任务可达到100FPS
  5. 在AFLW200-3D和Florence数据集上可达到25%的性能提升

二、方法介绍

拿之前写的ppt用一下吧。

(a)输入图+点云;(b)输入图;(c)UV纹理图;(d)UV坐标图;(e)(f)(g)UV坐标的三通道
图1 UV空间

开源数据集,如300W-LP,ground-truth是没有用UV表示的,所以要先生成UV训练数据。将(a)中的点云坐标转变成(d)的表达形式,该方法如图2:

图2 点云转换为UV表示

生成需要的训练数据后就可以用轻量级的CNN网络来处理了:

图3 PRN网络结构

网络结构代码如下:


   
   
  1. se = tcl.conv2d(x, num_outputs=size, kernel_size= 4, stride= 1) # 256 x 256 x 16
  2. se = resBlock(se, num_outputs=size * 2, kernel_size= 4, stride= 2) # 128 x 128 x 32
  3. se = resBlock(se, num_outputs=size * 2, kernel_size= 4, stride= 1) # 128 x 128 x 32
  4. se = resBlock(se, num_outputs=size * 4, kernel_size= 4, stride= 2) # 64 x 64 x 64
  5. se = resBlock(se, num_outputs=size * 4, kernel_size= 4, stride= 1) # 64 x 64 x 64
  6. se = resBlock(se, num_outputs=size * 8, kernel_size= 4, stride= 2) # 32 x 32 x 128
  7. se = resBlock(se, num_outputs=size * 8, kernel_size= 4, stride= 1) # 32 x 32 x 128
  8. se = resBlock(se, num_outputs=size * 16, kernel_size= 4, stride= 2) # 16 x 16 x 256
  9. se = resBlock(se, num_outputs=size * 16, kernel_size= 4, stride= 1) # 16 x 16 x 256
  10. se = resBlock(se, num_outputs=size * 32, kernel_size= 4, stride= 2) # 8 x 8 x 512
  11. se = resBlock(se, num_outputs=size * 32, kernel_size= 4, stride= 1) # 8 x 8 x 512
  12. pd = tcl.conv2d_transpose(se, size * 32, 4, stride= 1) # 8 x 8 x 512
  13. pd = tcl.conv2d_transpose(pd, size * 16, 4, stride= 2) # 16 x 16 x 256
  14. pd = tcl.conv2d_transpose(pd, size * 16, 4, stride= 1) # 16 x 16 x 256
  15. pd = tcl.conv2d_transpose(pd, size * 16, 4, stride= 1) # 16 x 16 x 256
  16. pd = tcl.conv2d_transpose(pd, size * 8, 4, stride= 2) # 32 x 32 x 128
  17. pd = tcl.conv2d_transpose(pd, size * 8, 4, stride= 1) # 32 x 32 x 128
  18. pd = tcl.conv2d_transpose(pd, size * 8, 4, stride= 1) # 32 x 32 x 128
  19. pd = tcl.conv2d_transpose(pd, size * 4, 4, stride= 2) # 64 x 64 x 64
  20. pd = tcl.conv2d_transpose(pd, size * 4, 4, stride= 1) # 64 x 64 x 64
  21. pd = tcl.conv2d_transpose(pd, size * 4, 4, stride= 1) # 64 x 64 x 64
  22. pd = tcl.conv2d_transpose(pd, size * 2, 4, stride= 2) # 128 x 128 x 32
  23. pd = tcl.conv2d_transpose(pd, size * 2, 4, stride= 1) # 128 x 128 x 32
  24. pd = tcl.conv2d_transpose(pd, size, 4, stride= 2) # 256 x 256 x 16
  25. pd = tcl.conv2d_transpose(pd, size, 4, stride= 1) # 256 x 256 x 16
  26. pd = tcl.conv2d_transpose(pd, 3, 4, stride= 1) # 256 x 256 x 3
  27. pd = tcl.conv2d_transpose(pd, 3, 4, stride= 1) # 256 x 256 x 3
  28. pos = tcl.conv2d_transpose(pd, 3, 4, stride= 1, activation_fn = tf.nn.sigmoid)

残差块代码如下,激活是relu,归一化是BN,shortcut对应三次卷积,随后通道合并,最后归一化和激活:


   
   
  1. def resBlock(x, num_outputs, kernel_size = 4, stride=1, activation_fn=tf.nn.relu, normalizer_fn=tcl.batch_norm, scope=None):
  2. assert num_outputs% 2== 0 #num_outputs must be divided by channel_factor(2 here)
  3. with tf.variable_scope(scope, 'resBlock'):
  4. shortcut = x
  5. if stride != 1 or x.get_shape()[ 3] != num_outputs:
  6. shortcut = tcl.conv2d(shortcut, num_outputs, kernel_size= 1, stride=stride,
  7. activation_fn= None, normalizer_fn= None, scope= 'shortcut')
  8. x = tcl.conv2d(x, num_outputs/ 2, kernel_size= 1, stride= 1, padding= 'SAME')
  9. x = tcl.conv2d(x, num_outputs/ 2, kernel_size=kernel_size, stride=stride, padding= 'SAME')
  10. x = tcl.conv2d(x, num_outputs, kernel_size= 1, stride= 1, activation_fn= None, padding= 'SAME', normalizer_fn= None)
  11. x += shortcut
  12. x = normalizer_fn(x)
  13. x = activation_fn(x)
  14. return x

Loss

P(x,y) 是UV位置空间的预测结果,代表着每个像素的xyz位置
W(x,y) 是UV位置空间的权重,对UV空间进行权重控制,2D关键点:眼鼻嘴:脸部其他:其他 = 16:4:3:0;

训练

训练数据来源: 使用了300W-LP数据集

  • 拥有各个角度的人脸数据,resize到256x256
  • 3DMM系数的标注
  • 使用3DMM 生成3D点云,并转换3D点云至UV空间

虽然生成GT使用了3DMM的标注系数,但是模型本身不包含3DMM模型的任何线性约束.

数据增广:各种场景

  • 角度变换:-45 ~ 45 度
  • 平移:系数0.9 ~ 1.2 (原图大小为基准)
  • 颜色通道变换:系数0.6 ~ 1.4
  • 添加噪音、纹理遮挡,模拟真实情况遮挡.
  • adam优化器,初始学习率0.0001,每5个epoch,衰减1半,batch size:16

三、测试结果

先提一下这个方法能做的事,由于学习到了2D与3D之间的映射,因次能实现的功能如下:

论文中部分测试指标如下:

 

 

   
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值