Overview

首先要明确的是人脸检测(Detection)和人脸识别(Recognition)是两个不同的步骤,前者是检测图像中是否存在人脸,后者才是识别两张图像中的人脸是否属于同一人。

而这篇文章主要是用Google ML Kit的人脸检测实现简单的非静默式活体检测,而人脸识别不在讨论范围内,但是可以参考这篇文章: Medium - Real time face recognition with android + TensorFlow Lite

非静默和静默的活体检测

活体检测的主要分为非静默(配合式)和静默式活体检测,前者需要人类配合做一些特定指令,如摇头、点头、张嘴等。

而后者无需人类配合,而是根据面部的一些微表情、光线等数据进行分析,对使用者更加友好。但实现的复杂度远远要比非静默活体检测复杂,需要利用高度训练的深度学习模型。

下文只讨论非静默活体检测的简单实现,如果需要静默活体检测,额外接入成熟的第三方SDK才是首选,例如华为的HSM ML Kit。

Google ML Kit - Face Detection

选择Google ML Kit是因为该SDK非常成熟且接入简单,可以直接使用离线使用,无需在平台上注册应用。需要再次声明的是,Face Detection 只负责检测人脸,不做识别。

关于Google ML Kit 人脸识别更详细的解释可以到其官方文档查看:Google ML Kit - Face Detection,这里只针对活体检测需要使用到的功能进行简单的说明。

  • Face tracking:追踪摄像机上的人脸,用来活体检测流程的连续性,防止用户以多张图片进行欺骗。

  • Face orientation: 识别脸部的旋转角度,用欧拉角表示。可以用来检测点头、摇头、歪头等。

  • Landmark:人脸特征点的坐标,例如眼睛、鼻子、嘴巴等。可以用来检测嘴巴是否张开。

活体检测

讨论市场面上最常用的检测流程,并保证流程的连续性。

  1. 保持脸部正对着摄像机
  2. 摇头
  3. 张嘴

使用Google ML Kit 人脸检测还能实现更多的检测方式,例如点头、笑脸等,但是在这里我们只讨论以上三种。

正脸检测

Google ML Kit 的人脸检测能提供相对于摄像机的脸部三维旋转的欧拉角

  • EularX:脸部上下旋转,正数表示向上(抬头)
  • EularY:脸部左右旋转,正数表示向左(左侧摇头)
  • EularZ:脸部时钟旋转,正数表示逆时针(左侧歪头)

如果人脸是正对着摄像机,这三个值都趋近于0,我们可以检测一定时间内这三个值没有出现过于激烈的变化,就认为人脸是正对摄像机。例如两秒内,X Y Z 的值(欧拉角)的范围都在10 ~ -10 。

摇头检测

还是根据X Y Z这三个欧拉角,保证一定时间内 X 和 Z 的值没有发生激烈变化的情况下,Y 的值大小超过左右两个阈值。例如两秒内,Y < -30 且 Y‘ > 30,如果两秒内没有完成摇头检测,则将记录的Y值清空重新检测。

张嘴检测

相对于正脸和摇头检测来说,这个稍微复杂那么一点点。

Google ML Kit 的人脸检测的Landmark提供嘴巴的三个特征点

  • LeftMouth:左嘴角
  • RightMouth:右嘴角
  • BottomMouth:下嘴唇底

我们可以通过这三个点组成的三角形,计算其各个角的欧拉角来判断是否张嘴。例如嘴巴紧闭时底部的角度大约是140~150度,而嘴巴张开时大约是110~120度。

liveness-detection-mouth

而根据三个点计算三角形各个角的欧拉角度的方式可以查看这篇文章: Find all angles of a given triangle

人脸追踪保证连续性

以上三个检测,可以通过多张照片切换的方式蒙骗过关,所以需要用到额外的人脸追踪功能。

Google ML Kit 的人脸检测可以追踪检测到的人脸,并为其分配一个ID,当人脸离开摄像机后再次被检测到时,ID会发生变化。

所以我们只要保证整个检测流程中的FaceID都是相同的即可。

Android Demo

针对以上的讨论,我写了一个简单的Android项目来进行演示,摄像机使用了Jetpack的CameraX,仅支持Android 5.0 以上版本。

References