3D人脸问题
人脸关键点算法已经从2D人脸渐渐发展变化为3D人脸,2D人脸是给定一副图片,找到图片中人脸关键点,这些关键点都是有着明确语义信息的,或者说都是可见的。而对于3D人脸,本身就是有一个立体结构的,也就是所谓的深度信息。在3D人脸中所要预测出来的关键点数量会远远地多于2D人脸。通过3D人脸关键点定位,能更好的对人脸来进行重构。目前2D人脸对关键点的检测已经相当准确了,从2D过度到3D人脸是一个主要的问题。
在进行人脸到美妆、人脸编辑、换脸,3D人脸是具有非常大的作用的。
对于3D人脸,主要用到的是人脸的深度信息,目前常用的是3D mesh,UV图。对于UV图,输入的是2D图,输出的是UV图,中间的网络是一个编解码的过程。UV图就描述了3D人脸的坐标信息。
人脸对齐算法常用数据集
数据集 | 关键点个数 | 下载地址 |
---|---|---|
BioID | 20 | |
LFPW | 29 | |
AFLW | 21 | |
COFW | 29 | |
300-W | 68 | |
HELEN | 29 | |
CelebA | 5 |
我们这里使用300W-LP的数据集,它包含了68个人脸关键点,并且包含了非常多的人脸图向,这些人脸图向分别来自AFW、LFPW、HELEN、IBUG and XM2VTS。300W-LP将这些数据集进行了汇总,并进行了68个人脸关键点的标注。下载地址链接:https://pan.baidu.com/s/1XGHrHdZzvLw1TNcNNmuKkw 提取码:bwus
除了已经公开的数据集以外,当我们面对一个新的任务,这个任务同我们实际的数据集中的人脸都会存在明显的差异,比如说要检测一些明星的人脸关键点,这个时候我们就需要去下载一个明星的数据库,这个数据库可能需要用爬虫去爬取图片。爬取到这些图片之后需要做标注。如果人工的去标注可能需要消耗非常多的时间成本,这里推荐使用Dlib库,利用这个库能够去检测出当前下载的图片中的人脸的位置并且完成人脸关键点定位。Dlib库完成一个68点的人脸关键点的定位。
利用Dlib库能够快速的进行人脸检测和关键点定位,生成深度学习模型输入的训练样本。此时我们能够快速的验证模型是否能够收敛,是否合理。验证模型的收敛性,模型的合理性之后再去人工的对人脸关键点坐标进行调整。在上图中就睡Dlib库检测出的正脸以及正脸关键点的位置。如果我们只是验证模型的算法和优劣,收敛性合理性,这个时候我们可以人为的去生成一些样本。整个任务解决的效率也会高很多。当然最终要去做一款好的产品,此时这些关键点的信息必须要去经过人工进行标注的,这个工作是省不了的。
人脸对齐算法常见问题及解决思路
对于遮挡和稠密点可以采用3D人脸关键点定位的相关策略来解决这些遮挡和侧脸,对人脸加一个深度信息来解决相关的问题。比如说PRNet或编解码网络或者热力图等。除了这些策略以外我们还可以去优化主干网络,比如去关注ImageNet图像挑战赛中更好的网络,能够提取出更加鲁棒的特征,对主干网络进行优化同样也能提高模型的性能。
SENet模型介绍
这里的数据就是训练样本,网络结构采用SENet来作为核心网络结构,经过FC层最后输出68点关键点136维的向量。因为预测的是一个值,所以这个网络是一个回归网络。
在上图中的c1、c2表示了一个卷积层,对于卷积的结构,SENet的核心单元实际上是对于卷积的通道,通过一个单独的分支去计算这个通道(特征图)c2所对应的权重。对于一个特征图,它的尺寸为n*H*W*c,其中n为样本数量,H为特征图的高,W为特征图的宽,c为通道的数量,也就是特征图的个数。
表示一个平均池化层,将特征图转化为一个1*1*c2的一个点,每一个特征图对应到一个c2。经过平均池化层之后,再经过FC层回归计算出每一个通道的权重,计算出权重后去对c2特征图的不同的通道进行加权。这样就可以拿到对通道进行加权之后的特征图(就是最后那个彩色图)。在上图中我们也可以看到该特征图不同的颜色对应到不同的权值,这个流程是对通道的加权,这个加权可以理解成Attention。SENet主要是体现在了对通道的加权上,具体SENet的设计需要去结合一些具体的网络结构。
这里就给出了两个网络结构,一个是SENet Inception,一个是SENet ResNet。对于Inception输出的特征图再经过SENet进行通道上的加权,所以SENet Inception的结构就是在Inception结构的后面再加一个SENet的单元。而SENet ResNet则是将SENet融入到了ResNet残差的结构中,SENet添加的部分是在残差之后的单元,在这个结构单元,拿到了特征图之后,同样经过一个SENet来对特征图进行通道上的加权,最后再同原先的特征图进行相加,可以看到这是集成到了ResNet残差结构当中,同Inception结构有一点区别。这里我们可以看到在SENet的结构中有两个FC层,第一个FC层会对通道进行一个下采样,此时整个网络的参数量会有一定的减少,通过FC层计算出权重后,再通过一个Sigmoid将权值归一化,做个激活,映射到0~1之间。最后再将这个权重乘回到特征图上完成对通道的加权。最终将加权之后的特征图同输入的原始的特征图进行相加,得到最终ResNet结构网络的输出。对于SENet ResNet的网络结构可以用下面的代码来表示
这里X1 = conv(X0)卷积就表达了Residual结构,X2 = weight(X0)就是计算权重的过程,就表达了SENet结构的部分,X3 = X0 + X1 ** X2表示最后相加的运算。