人脸姿态估计算法,主要用以估计输入人脸块的三维欧拉角。一般选取的参考系为相机坐标系,即选择相机作为坐标原点。姿态估计可用于许多业务场景,比如在人脸识别系统的中,姿态估计可以辅助进行输入样本的筛选(一般人脸要相对正脸才进行召回和识别);在一些需要人脸朝向作为重要业务依据的场景中,人脸姿态算法也是不可或缺的,比如疲劳驾驶产品中驾驶员的左顾右盼检测。
人脸姿态估计的算法,其大致可分为两类:一类是通过2D标定信息来估计3D姿态信息的算法,如先计算人脸的关键点,然后选取一个参考系(平均正脸的关键点),计算关键点和参考系的变换矩阵,然后通过迭代优化的算法来估计人脸的姿态(可参考Opencv中的SolvePnP算法,或参考中的1和2);另一类就是通过数据驱动的方式训练一个回归器,由该回归器对输入人脸的块进行一个直接的预测。
两类方法各有利弊,在项目中都能得到不用程度的应用。下面我们来看看上述两类方式的优缺点对比,为了方便大家区分,我们这里称第一类算法为landmark-based,第二类为landmark-free。
两类方法对比
1. 数个2维坐标点坐标 使用人脸特征点检测算法对二维人脸图像进行特征点检测。本文中,作者使用鼻尖、下巴、左眼左眼角、右眼右眼角、左嘴角和右嘴角的坐标。
2. 和每个2维坐标点对应的3维坐标 在实际应用中,不需要获取一个精确的人脸三维模型并且也没法获取这样的模型,因此,作者设置了上述6个二维点对应的3维坐标,分别为: Tip of the nose : ( 0.0, 0.0, 0.0) Chin : ( 0.0, -330.0, -65.0) Left corner of the left eye : (-225.0f, 170.0f, -135.0) Right corner of the right eye : ( 225.0, 170.0, -135.0) Left corner of the mouth : (-150.0, -150.0, -125.0) Right corner of the mouth : (150.0, -150.0, -125.0)
3. 相机的内参数矩阵 进行相机参数估计时首先需要对相机进行标定,精确的相机标定需要使用张正友的棋盘格标定,这里还是进行近似。相机的内参数矩阵需要设定相机的焦距、图像的中心位置并且假设不存在径向畸变。这里设置相机焦距为图像的宽度(以像素为单位),图像中心位置为(image.width/2,image.height/2).
如何进行姿态估计
姿态估计过程中有三个坐标系,分别为世界坐标系、相机坐标系和图像坐标系。一个世界坐标系中的三维点(U,V,W)(U,V,W)通过旋转矩阵RR和平移向量tt映射到相机坐标系(X,Y,Z)(X,Y,Z),一个相机坐标系中的三维点(X,Y,Z)(X,Y,Z)通过相机的内参数矩阵映射到图像坐标系(x,y)(x,y)。
本文要给大家介绍的这个算法,属于上述提到的第二类方法,给定一个人脸patch,该算法能直接对人脸patch的三维欧拉角进行回归预测。在跟大家讨论本文的创新点前,我们先来看看一个非常朴素的例子。
朴素的姿态回归器
之前的文章也有跟大家介绍过如何设计一个对嵌入式设备友好的回归器,其本质上于我们这里要跟大家介绍的姿态回归器是一样的,这里我们默认用MSE损失函数进行训练。该回归器的设计可以分成两个部分,第一个是骨干网络的设计,骨干网络的设计可轻可重,如果是在PC平台上进行部署,可以选择较大型的网络,如VGG16、ResNet50、ResNet101等。如果需要面对嵌入式设备进行部署,则需要选择诸如MobileNet、ShuffleNet、SqueezeNet等轻型网络;第二个是回归器的设计,输入数据在经过骨干网络以后会生成一个高纬度的非线性特征,这里我们给大家介绍两种设计,一类为直接回归,即输入特征经过flatten以后直接经由dense层进行回归。另一类为多分只的回归,每个输出元素经由一个dense层进行回归。两者用概率的角度来解释的话,前者更倾向于关联,后者更倾向于独立同分布。结构可以参考下图,
左:直接回归 , 右: 分支回归
存在的问题
上述提到的回归器,在实际应用的时候,还是存在不少问题的。第一个是训练数据的需求较大,这个是任何回归器都需要面临的挑战,因为你目的是需要尽可能拟合输入数据的分布;第二个是训练数据分布不均,有文章对300W-LP的数据分布进行过统计,该数据库存在很明显的长尾分布,主要数据都集中在相对正脸的数据上面,而大幅度抬头、侧脸、低头的数据占比非常小。这使得训练出来的模型在处理这类长尾数据的时候非常吃力;第三个是模型训练较难收敛。
面对上述几个问题,工程上有许多技巧可以规避。比如面对第一个问题,你可以采用现有的大量landmark数据进行pose的估算,或者采用合成的方式来生成训练数据,比如300W-LP数据库;面对第二个问题,可以采用控制输入训练数据的分布,或者加权的方式来训练模型;第三个问题的解决,我们可以先拿骨干网络在一些分类模型上进行预训练(pretrain)。当然此类的处理方式比较简单粗暴实用,到若回归到论文写作本身来看,是没什么贡献的。我们下面来看看这篇论文,是怎么优雅的处理以上问题的。
该论文的网络设计
该论文的网络设计几乎考虑到了我们上面所提到的三个问题,首先针对训练难收敛的问题,作者提出了将回归空间离散化,引入一个中间分类层去学习数据的分布,这样既能解决难收敛的问题,同时又对数据的分布进行了刻画;第二点,作者将对姿态的直接回归,转化成该数据分布和预先设定的锚点的一个期望,这里跟物体检测任务中引入anchor的机制很类似;第三,通过引入加权的loss来调整不同分布数据对网络训练的贡献。出发点其实很简单,就是希望占比大的数据贡献较少,占比小的数据贡献较大。最后的网络形态可参考下图,
网络结构及训练细节
这里需要注意的是,上图中的H代表的是分类层中的CrossEntropy Loss。在进行训练数据准备的时候,对于输入的训练数据[ pitch, yaw, roll],作者将[0,180]度分成61个bins,然后根据三个角度所处的bin生成label,并用来训练分类层;根据分类层出来的概率分布,和61个bins的值求期望得出回归的值,最后以加权的方式来整合分类损失和回归损失。感谢作者,提供了一个很好的思路,以非常优雅的方式同时处理了刻画数据分布和回归两个任务。