前言
正如在这篇博客中提到的一样(https://blog.csdn.net/likewind1993/article/details/85212711 ),“Large Pose 3D Face Reconstruction from a Single Image via Direct Volumetric CNN Regression”提出的方法属于端到端的人脸重建方法,输入一张人脸照片便可以直接生成相应的人脸模型。
正是由于其“端到端”的特性,原本想着复现起来的难度会小点,于是一不小心入了这个坑:
VRN
online Demo: http://cvl-demos.cs.nott.ac.uk/vrn/
作者用webgl写了一个demo,因为有验证码,可能需要梯子才能跑自己的照片。
换个角度:
项目地址 https://github.com/AaronJackson/vrn
在github上作者公布了部分源码,但是没有公开网络结构、体素文件的生成。
因此复现的时候主要是实现这两个部分。
复现
数据集
使用到的人脸模型数据集为:300W-LP,基于BFM模型生成,包含了大约6万个人脸数据。
数据集相关地址如下:http://www.cbsr.ia.ac.cn/users/xiangyuzhu/projects/3DDFA/main.htm
体素文件的生成
关于体素文件的生成,作者在github的issue中给出了一点提示,基于这个脚本的思想进行三维模型的体素化:
https://www.mathworks.com/matlabcentral/fileexchange/27390-mesh-voxelisation
大致思想是先划定体素网格的大小,比如论文中的大小为192x192x200,然后对需要体素化的模型从x, y, z三个方向进行一个等比例的划分。
接下来从x,y,z三个方向发出射线,判断射线在是否在模型里,在模型外的数据是0, 在模型内的数据是1,这样便完成了模型的体素化(并且这样得到的体素结果是没有空洞的)。
Note:
在进行体素化的时候,论文的作者提出要先将模型转到正面,然后进行体素化,最后再转到原来的姿态。之前一直不理解为什么要这么做,后来在自己实现的时候发现:
转到正面进行体素化的时候,可以把模型的脸部取一个固定的顶点(index),在模型转到正面的时候,对z方向发出的射线做一个限定(只体素化z<z[index]的部分),就能得到的论文中的一半的脸部(由于使用到的BFM模型是带有耳朵、脖子部分,但是这些部位对深度学习并没有太大的用处,因此要去除这部分)。
体素化的结果如下:
侧面:
网络结构
论文中关于这部分没有太多的阐述,只是简单的说将两个去掉中继监督层的hourglass模块进行堆叠,因此我使用了pytorch实现的hourglass网络结构,https://github.com/bearpaw/pytorch-pose。
另外对模块之间的连接、输出部分进行了添加Conv层的操作,来修改相关数据格式大小。
训练结果
在进行了这么多工作的尝试之后,最后的结果并没有成功的跑起来,因为192x192x200的数据量过大,进行训练的时候太耗时了。我的机器(GTX1080,32G内存,框架用pytorch)上跑一个epoch需要2天多一点的时间,完全跑完有点不太现实,暂不清楚哪个部分出现了问题。
而作者使用的环境为GTX1080Ti x 2,跑2-3天,6万个样本大概迭代50~60次即可完成训练,但在以我的训练速度粗略估计一下,相同次数的迭代需要花几十天,时间太长了。
因此简单的用一个样本进行迭代10000次来验证模型的正确性,效果如下:
遇到的问题
虽然模型在验证的过程中显示了一定的可行性,但这次论文并没有成功复现,一方面是自己机器的原因,另一方面还遇到了一些问题:
- 论文体素部分的流程是“Rotated to Frontal -> Voxelisation -> Realigned”, 但是完成体素化后,得到的数据是一个192x192x200的三维数组,里面存着0,1,遇到了如何进行“Realigned”的问题,因为将原有模型的Rotate Matrix, Translate Matrix应用到这些整数数据上后,会得到小数,如果取整丢掉小数部分,得到的结果非常不好(因此我在实验的时候只挑选了正脸样本进行训练)。
总结
因为自己刚接触,整体复现的流程一步步摸索花了较多时间,把经验总结一下。
这样万一也有人想复现这篇论文,可以提前知道有哪些坑,对复现流程有更好的把握。