1.人脸识别主要应用场景
人脸验证。判断两张图片里的人是否为同一人。最常见的应用场景便是人脸解锁,终端设备(如手机)只需将用户事先注册的照片与临场采集的照片做对比,判断是否为同一人,即可完成身份验证。比如,使用人脸验证登录“XX”、“XX”APP。
人脸识别。判断系统当前见到的人,是否为事先见过的人,为其中的哪一个。比如买咖啡刷脸,小区门禁,会场签到等。人脸识别系统都事先存储了大量的不同人脸和身份信息,系统运行时需要将见到的人脸与之前存储的大量人脸做比对,找出匹配的人脸。
2.关键技术点及思路
(1)登陆认证在服务器端实现还是在客户端实现?
换句话说,人脸识别的模型应该运行在服务器端还是客户端。如果人脸识别模型运行在服务器端,那么客户端必须在联网环境下才能通过服务端的认证并使用。某些场景下,例如音乐客户端场景(用户在无需联网的情况下也需要进入APP听音乐),人脸识别模型运行在服务器就无法满足需求。如果人脸识别模型运行在客户端,那么需要模型足够简单,客户端能够提供运行模型所需要的计算资源,例如,将能够运行在服务器的VGG16模型搬到客户端,大多数手机客户端的计算资源都无法满足需求,为了获得能在手机客户端运行的模型,需要投入人力做技术预研。
登陆认证在服务器端还是在客户端这个问题的整体思路:初期登录认证在服务器端运行,在必须联网才能使用客户端的场景使用,同时进行手机客户端做人脸识别的预研工作。手机客户端的人脸识别技术成熟后,再将登陆认证能力以SDK方式封装到客户端。
(2)人脸检测是服务器端还是在客户端做?
在进行人脸识别的过程中,我们使用采集到图片中的人脸区域,需要先检测图片中的人脸位置,然后将该位置的人脸裁剪为只包含人脸区域的小图片。原始人脸图片是在客户端通过摄像头采集的,那么人脸检测应该在服务器端做还是在客户端做呢?
为了让人脸识别模型获取更大的人脸区域,从而使模型提取到更全面的人脸体征,使人脸识别更准确,需要在人脸检测步骤获得的人脸bounding box基础扩大人脸图片区域,因此,人脸识别模型在哪里运行,人脸检测就在哪里做。
(3)为什么VGG、RESNET等网络模型不能直接用于人脸识别?
VGG、RESNET等网络模型因资源消耗多不适合运行在手机客户端,即便是可以在手机客户端运行的MobileNET,也无法直接应用到我们的人脸识别场景,原因是:这些典型的网络无法对陌生人脸进行划分,例如,分类器可以识别3个人的人脸,当第4个人要识别时,他就会被误识别为这3个人中的其中一个。
(4)MobileNet模型不能直接用于手机端人脸识别,那该怎么办?
解决对陌生类别划分的问题,目前主要是通过Siamese网络和Triplet网络思路来解决,例如,DLIB中的人脸识别就是通过训练基于RESNET的Triplet网络实现。下面简单介绍Siamese网络和Triplet网络的原理。
Siamese 网络的主要思想是通过一个函数将输入映射到目标空间,在目标空间使用简单的距离(欧式距离等)进行对比相似度。在训练阶段去最小化来自相同类别的一对样本的损失函数值,最大化来自不同类别的一堆样本的损失函数值。
根据Siamese网络的主要思想,有人发明了Triplet 网络。triplet是一个三元组,这个三元组是这样构成的:从训练数据集中随机选一个样本,该样本称为Anchor,然后再随机选取一个和Anchor (记为x_a)属于同一类的样本和不同类的样本,这两个样本对应的称为Positive(记为x_p)和Negative (记为x_n),由此构成一个(Anchor,Positive,Negative)三元组。针对三元组中的每个元素(样本),训练一个参数共享或者不共享的网络,得到三个元素的特征表达,分别记为:f(xia),f (xip),f (xin)。triplet loss的目的就是通过学习,让x_a和x_p特征表达之间的距离尽可能小,而x_a和x_n的特征表达之间的距离尽可能大,并且要让x_a与x_n之间的距离和x_a与x_p之间的距离之间有一个最小的间隔t。公式化表示就是:||f (xia)-f (xip)||+t<||f(xia)-f (xin)||,损失函数就是L={ ||f (xia)-f (xip)||-||f (xia)-f (xin)||+t }+。这里距离用欧式距离度量,+表示{ }内的值大于零的时候,取该值为损失,小于零的时候,损失为零。
(5)DLIB提供的人脸识别满足我们的需要吗?
前面提到过DLIB人脸识别是基于RESNET的Triplet网络,限制了它在手机端的应用,但是当人脸识别模型运行在服务器端时,可以方便地利用DLIB提供的人脸识别功能。
除了人脸识别外,人脸登录认证过程中需要对人脸的真实性做判断(例如进行活体检测),DLIB不能满足这些需要,需要投入人力预研。由于我们目前的场景并不涉及类似支付的高度敏感场景的认证,所以可以将活体检测预研的优先级排低一些。
(6)人脸识别模型在客户端运行有哪些难点需要解决?
如何选择能在手机端运行的深度学习框架。用什么框架(tensorflow、pytorch、caffe)训练的模型,能同时在IOS、Android是上运行?工程上如何实现对这些模型的调用?
手机端如何实现人脸识别。怎样对现有模型(如MobileNET)进行改造,才能达到既满足运行效率(例如<100ms)的要求,又有足够的识别准确度 (如99%)的要求。
手机端如何实现人脸检测。OpenCV DNN人脸检测性能和效果都比较好,但是集成OpenCV会导致安装包过大,裁剪OpenCV代价会比较大。
3.核心业务流程(不含产品设计)
(1)人脸识别在服务器端
人脸注册阶段,客户端负责采集各个角度(中、左、右、上、下)的人脸照片,上传服务端请求注册,服务端接收到注册请求后,从人脸照片中识别人脸,并提取人脸特征并保存在数据库中,待人脸识别阶段与新上传照片的特征进行比较。
认证阶段,客户端负责采集人脸图片,并上传服务器端请求认证,服务器端收到请求后进行人脸检测、人脸特征提取,并与注册阶段生成的人脸特征比较,如果特征距离低于某阀值(如DLIB设置为0.6)则认证通过。另外,服务器端可以采集认证的效果数据,用户模型的调优和评估。
(2)人脸识别在客户端
当人脸识别在客户端进行时,所有服务端的工作都将按顺序发生在客户端。人脸注册过程中,客户端可以将注册人脸过程中产生的特征值在联网状态下发送给服务器端做保存备份。
4.参考文献
https://xraft.github.io/2018/03/21/FaceRecognition/
https://github.com/opencv/opencv/blob/master/samples/dnn/js_face_recognition.html
https://github.com/yeziyang1992/Python-Tensorflow-Face-v2.0
https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html
https://www.pytorchtutorial.com/pytorch-one-shot-learning/
https://hackernoon.com/facial-similarity-with-siamese-networks-in-pytorch-9642aa9db2f7
https://github.com/zdavidli/siamese-facial-recognition
https://github.com/harveyslash/Facial-Similarity-with-Siamese-Networks-in-Pytorch
http://blog.dlib.net/2017/02/high-quality-face-recognition-with-deep.html
https://github.com/davisking/dlib/blob/master/python_examples/face_recognition.py
http://krasserm.github.io/2018/02/07/deep-face-recognition/
https://www.pyimagesearch.com/2018/06/18/face-recognition-with-opencv-python-and-deep-learning/