生物识别技术——人脸识别

生物识别技术——人脸识别

作者:算法小七cvplus 版权所有 新书即将发行

生物识别技术是利用人的生理特性或者行为特征实现人的身份核验,其中生理特性包含身高体重、体态、声纹、虹膜、指纹、掌纹、人脸等,行为特征包含步态、笔迹等。人脸识别属于生物识别技术的范畴。

人脸识别是计算机视觉领域中一个非常重要的研究方向[1],人脸识别中经常遇到的遮挡(帽子、口罩、面罩、手遮挡、眼镜、人群遮挡等)、化妆、噪点、模糊度(模糊、清晰、一般)、大角度、光照度(强光、弱光、逆光、黑夜、背光)、人脸完整度、人脸角度姿态(正脸、侧脸、抬头、低头等)、人脸运动、面部表情、性别、年龄等问题都需要我们来攻克。

人脸识别是以人脸为目标对象实现的一系列计算机视觉技术,它包含人脸检测、人脸关键点检测、人脸对齐、人脸对比、人脸身份验证、人脸搜索等内容。在本书中笔者把眨眼检测、人脸追踪、活体检测[2]、人脸特效(包含美颜、瘦脸、大眼、换脸[3]、动态贴纸、虚拟特效、滤镜等)、人脸皮肤分析(包含肤色、肤质、单双眼皮、眼袋、黑眼圈、纹理、皱纹、毛孔、色斑、斑点、痘痘、痣等)、拍照图像质量评估(炫光、光斑、模糊、遮挡、多个人脸、有无人脸、侧脸、闭眼等,通过拍照图像质量的评估和交互控制,进而保证图片质量)、人脸属性分析(包含性别、年龄、人种、情绪、微表情[4]、颜值、脸型、头部姿态、是否闭眼、是否配戴眼镜等,其中情绪识别如图3.1所示)等也归属到人脸识别的范畴,因为这些场景研究对象均是人脸,以及均涉及到人脸识别的技术栈。人脸识别的落地场景非常丰富,它广泛应用于交通、酒店、金融、保险、安防、零售、直播等行业场景,满足身份核验、闸机通行、人脸考勤等业务需求。

图3.1 情绪识别

以下笔者重点介绍人脸识别中的人脸检测、人脸关键点检测以及眨眼检测。

3.1 人脸检测——人脸识别的第一步

人脸检测(英文全称Face detection),就是实际图像中人脸目标的检测,它是人脸识别的第一步,不管是做人脸身份验证、人脸搜索、眨眼检测,均需要先实现人脸检测。人脸检测一般是我们接触OpenCV中关于人脸识别的第一个例子(关于OpenCV的介绍,下一章会单独展开),笔者曾经第一个研究的DEMO就是人脸检测,具体的测试参考代码如下(代码中已经做了相关的注释):

#include <iostream>

#include <string>

#include <OpenCV2/core/core.hpp>

/*OpenCV中主要模块:

core(核心功能模块:基本数据结构等)

imgproc(图像处理模块:特征检测等)

highgui(高层gui图形用户界面)

stitching

calib3d等

*/

#include <OpenCV2/highgui/highgui.hpp>

// HighGUI,high-level graphical user interface,可移植图形工具包

#include <OpenCV2/gpu/gpu.hpp>

using namespace cv;

using namespace std;

string xml_path = "haarcascade_frontalface_default.xml";

//人脸检测分类器模型

void detect_show(Mat image); //函数声明

int main( int argc, char**argv )

{

string path = "test.jpg";

Mat image = imread(path, -1); //加载图片

CascadeClassifier face_model; //创建人脸检测模型

if(!face_model.load(xml_path)) { //加载人脸检测分类器模型

cout<<"无法加载分类器模型xml文件"<<endl;

return 0;

}

try {

// ……

}

catch (cv::Exception& e) { // 异常检查

cerr << "Error \" " << " "<< "\"reason: " << e.msg << endl;

exit(-1);

}

// cerr流对象是标准错误流,cout流是传送到显示器输出和磁盘文件,而cerr流只能输出到显示器

detect_show(image); // 检测人脸

return 0;

}

void detect_show(Mat image) //函数定义

{

CascadeClassifier face_model; //创建人脸检测模型,级联分类器

if(!face_model.load(xml_path)) { //加载人脸检测分类器模型

cout<<"无法加载分类器模型xml文件"<<endl;

return 0;

}

vector<Rect> obj;

Mat gray;

cvtColor(image, gray, CV_BGR2GRAY);

equalizeHist(gray, gray);

//直方图均衡化,Histogram equalization,在深度学习中直方图均衡化基本上有没有使用,这个是经典图像算法和深度学习方法的一个区别吧

face_model.detectMultiScale(gray, obj, 1.1, 3, 0, Size(50,50), Size(200,200));

/*

gray, 待检测输入图像

obj,检测结果

1.1,尺寸减小比例

3,minNeighbors,目标被检测到minNeighbors次才被认可

Size(50,50), Size(200,200),目标最小尺寸和最大尺寸

*/

for(vector<Rect>::const_iterator iter = obj.begin(); iter != obj.end(); iter++)

{

rectangle(image, *iter, Scalar(0,0,255), 2, 6);

}

// Vector向量,封装动态大小向量存储容器Sequence Container;、

// const_iterator,迭代器,修改指针地址, 不能修改指针所指的值

Mat image_;

Mat frame;

for(int i=0; i< obj.size(); i++) {

Point center(obj[i].x + obj[i].width / 2, obj[i].y + obj[i].height / 2);

Image_ = image(Rect(obj[i].x, obj[i].y, obj[i].width, obj[i].height));

Mat faceROI = frame (obj[i]);

}

imshow("image", image);

imshow("image_obj", image_obj);

cvWaitKey();

}

以上代码是OpenCV中基于Haar-like特征的AdaBoost算法实现的人脸检测,这个算法创新点有:1、使用积分图(Integral Image)的方法加速特征计算;2、AdaBoost分类器;3、级联分类器实现“三个臭皮匠赛过诸葛亮”[5]。Haar-like特征+AdaBoost算法在大多正脸图片场景中检测精度大约可以做到99%,但是对侧脸、表情、光线过暗、反光、遮挡等场景中,检测效果会不佳,表现在很容易造成人脸漏检,所以目前阶段通过深度学习方法实现人脸检测是最好的方案。关于深度学习的方案,在第5章开始给读者朋友介绍。关于人脸检测的应用,我们先看图3.2所示的活体检测,所谓活体检测,简称活检,它通过实时视频流中眨眼、摇头、张嘴等动作的检测,用于辅助判断用户上传的照片是否是真实的人脸,防止不法用户使用照片替代真实人脸的情况,一般用在远程开户等远程业务办理场景中。在活检实现的算法流程中,第一步我们就需要实现人脸检测,所以说人脸检测很关键,我们需要考虑检测的精度和鲁棒性,其中精度包括漏检率(是人脸目标却没有被检测到)、误检率(不是人脸的物体被检测为人脸),当然漏检测和误检率均越小越好。

图3.2 活体检测

3.2 人脸关键点检测

人脸关键点检测(Face Landmark Detection),也叫人脸对齐(Face Alignment),它是精确定位标记人脸各个器官(脸颊、眉毛、眼睛、口、鼻等)和轮廓的关键点坐标,如图3.3所示是人脸关键点检测,如图3.4所示是人脸嘴巴关键点检测。

图3.3 人脸关键点检测

图3.4 人脸嘴巴关键点检测效果

关于人脸关键点检测,Dlib是一个非常重要的开源库,引用官网的一段话:Dlib is a modern C++ toolkit containing machine learning algorithms and tools for creating complex software in C++ to solve real world problems. It is used in both industry and academia in a wide range of domains including robotics, embedded devices, mobile phones, and large high performance computing environments. Dlibs open source licensing allows you to use it in any application, free of charge. [6](译:Dlib是一个现代C++工具包,包含机器学习算法和工具,用于在C++中二次开发新的服务来解决现实问题。它被工业界和学术界广泛应用于机器人、嵌入式设备、移动电话和大型高性能计算环境等领域。Dlib的开源许可允许您在任何应用程序中免费使用它。)

Dlib支持人脸检测和68点关键点检测,接下来笔者给读者介绍两种安装方法:

方法一、命令安装:

pip install dlib

or

pip install dlib-bin

or

pip install face_recognition -i https://pypi.tuna.tsinghua.edu.cn/simple

方法二、源码编译安装,具体方法如下:

git clone https://github.com/davisking/dlib.git //下载源码

cd dlib/examples

mkdir build

cd build

//cmake ..

cmake --build . --config Release

cd dlib

sudo python setup.py install

以上两种方法安装好后,我们通过以下命令测试(如果没有报错,表明安装成功):

python -c "import dlib"

Dlib安装好后,我们可以使用Dlib开始编程,在开始编程之前,我们首先需要理解它和OpenCV、PIL中关于图片格式的区别,具体区别如表3.1所示:

表3.1 图片格式要求

类型图片格式要求OpenCVRGB格式图像PILRGB,1,L,P,RGBA,CMYK,YCbCr,I,FdlibBGR格式图像img = cv2.cvtColor(cv_img, cv2.COLOR_RGB2BGR)

接下来我们就可以基于Dlib编程,以下代码展示的是Python版本的Dlib测试代码,测试代码的功能是实现人脸的关键点的检测和标记。

#!/usr/bin/python

# -*- coding: utf-8 -*-

import cv2

import dlib

import numpy as np

detector = dlib.get_frontal_face_detector()

landmark_predictor = dlib.shape_predictor(shape_predictor_68_face_landmarks.dat)

img_rgb = cv2.imread(test_dlib.jpg)

# img_bgr = cv2.resize(img_bgr, (int(w*0.25), int(h*0.25)), interpolation=cv2.INTER_CUBIC)

h, w = img_rgb.shape[:2]

img_landmark = 255 * np.ones([h, w, 3],dtype=np.uint8)

# img_landmark = np.zeros([h, w, 3], np.uint8)

# img_landmark[:, :, 0] = np.ones([h, w]) * 255 # R

# img_landmark[:, :, 1] = np.ones([h, w]) * 255 # G

# img_landmark[:, :, 2] = np.ones([h, w]) * 255 # B

print(img_landmark.shape[:2])

#img[0,0] = 5

#img_landmark = cv2.imread(img_landmark.jpg)

img_bgr = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR)

faces = detector(img_bgr, 1)

if (len(faces) > 0):

for k, d in enumerate(faces):

cv2.rectangle(img_rgb, (d.left(), d.top()), (d.right(), d.bottom()), (0, 0, 255))

shape = landmark_predictor(img_rgb, d)

for i in range(68):

cv2.circle(img_rgb, (shape.part(i).x, shape.part(i).y), 3, (255, 0, 0), 1, 1)

cv2.putText(img_rgb, str(i), (shape.part(i).x, shape.part(i).y), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2,2)

cv2.circle(img_landmark, (shape.part(i).x, shape.part(i).y), 3, (255, 0, 0), 1, 1)

cv2.putText(img_landmark, str(i), (shape.part(i).x, shape.part(i).y), cv2.FONT_HERSHEY_SIMPLEX,1, (0, 0, 0), 2,2)

for i in range(16):

cv2.line(img_landmark, (shape.part(i).x, shape.part(i).y),

(shape.part(i+1).x, shape.part(i+1).y), (0, 0, 255), thickness=3, lineType=1)

for i in range(17,21):

cv2.line(img_landmark, (shape.part(i).x, shape.part(i).y),

(shape.part(i+1).x, shape.part(i+1).y), (0, 0, 255), thickness=3, lineType=1)

for i in range(22,26):

cv2.line(img_landmark, (shape.part(i).x, shape.part(i).y),

(shape.part(i+1).x, shape.part(i+1).y), (0, 0, 255), thickness=3, lineType=1)

for i in range(48, 59):

cv2.line(img_landmark, (shape.part(i).x, shape.part(i).y),

(shape.part(i + 1).x, shape.part(i + 1).y), (0, 0, 255), thickness=3, lineType=1)

cv2.line(img_landmark, (shape.part(48).x, shape.part(48).y),

(shape.part(59).x, shape.part(59).y), (0, 0, 255), thickness=3, lineType=1)

for i in range(60, 67):

cv2.line(img_landmark, (shape.part(i).x, shape.part(i).y),

(shape.part(i + 1).x, shape.part(i + 1).y), (0, 0, 255), thickness=3, lineType=1)

cv2.line(img_landmark, (shape.part(60).x, shape.part(60).y),

(shape.part(67).x, shape.part(67).y), (0, 0, 255), thickness=3, lineType=1)

for i in range(27, 35):

cv2.line(img_landmark, (shape.part(i).x, shape.part(i).y),

(shape.part(i + 1).x, shape.part(i + 1).y), (0, 0, 255), thickness=3, lineType=1)

cv2.line(img_landmark, (shape.part(30).x, shape.part(30).y),

(shape.part(35).x, shape.part(35).y), (0, 0, 255), thickness=3, lineType=1)

for i in range(36, 41):

cv2.line(img_landmark, (shape.part(i).x, shape.part(i).y),

(shape.part(i + 1).x, shape.part(i + 1).y), (0, 0, 255), thickness=3, lineType=1)

cv2.line(img_landmark, (shape.part(36).x, shape.part(36).y),

(shape.part(41).x, shape.part(41).y), (0, 0, 255), thickness=3, lineType=1)

for i in range(42, 47):

cv2.line(img_landmark, (shape.part(i).x, shape.part(i).y),

(shape.part(i + 1).x, shape.part(i + 1).y), (0, 0, 255), thickness=3, lineType=1)

cv2.line(img_landmark, (shape.part(42).x, shape.part(42).y),

(shape.part(47).x, shape.part(47).y), (0, 0, 255), thickness=3, lineType=1)

cv2.imwrite("img_landmark_out.jpg",img_landmark)

cv2.imwrite("img_rgb_out.jpg",img_rgb)

print("test end")

人脸关键点检测是包括人脸身份验证、人脸搜索、眨眼检测、三维人脸重建、人脸特效、人脸皮肤分析、人脸属性分析等其它人脸相关任务的基础,它是一个很有挑战的任务。在本章下一节我们介绍的眨眼检测也是应用到人脸关键点检测的方法。

3.3 眨眼检测实现疲劳驾驶检测——ADAS重要模块

ADAS(英文全称Advanced Driver Assistance System)是高级驾驶辅助系统,它主要功能如图3.5所示:

图3.5 ADAS功能模块

注:FCWS全称为Forward Collision Warning System,SVM全称为Surround View Monitor,LDW全称为Lane Departure Warning System,AP全称为Automatic Parking

其中疲劳驾驶检测是通过车载内置摄像头实时采集驾驶员驾驶影像,使用算法分析检测驾驶员眨眼频率和人眼注视时间等生理状况,进一步分析是否处于疲劳状态和注视力是否集中(分心驾驶探测)。关于人眼的眨眼检测模块,我们可以使用Dlib库来演示其功能,图3.6所示的是人眼睁眼和闭眼的检测情况:

睁眼检测

闭眼检测

图3.6 睁眼和闭眼状态检测,其中数字部分代表人眼的关键点位置

然后通过以下公式计算人眼的闭合程度K:

参数K可以反映人眼的闭合程度,通过这个参数我们可以区分人眼睁眼和闭眼,进一步我们可以检测人眼眨眼的频率。

讲解完人脸检测、人脸关键点检测和眨眼检测部分后,考虑到篇幅的限制,笔者在此给大家简单概念性讲解一下人脸身份验证和人脸搜索内容。其中人脸身份验证的目标是确认图片中的人脸是不是本人,它的应用场景有远程开户、酒店入住、身份证人证合一等等,有别于人脸搜索(人脸搜索的目标是确认图片中的人脸是谁)[7],人脸搜索是将一张人脸图片如图3.7所示在人脸库中进行相似匹配搜索,返回最相似的一张或多张人脸图片及对应相似度,即1:N的人脸搜索技术。人脸搜索可用于用户身份验证、门禁刷脸、安防监控(比如特定人物识别和追踪)、智能照片库等场景。

图3.7 人脸搜索

本章小结

本章主要介绍生物识别技术人脸识别的概念以及包含人脸检测、人脸关键点检测、人脸身份验证、人脸搜索、眨眼检测等。

人脸识别在智能安防、交通出行、金融支付等场景中发挥巨大作用,也是一门不断创新和发展的技术,在端边云中均有很好的技术支持方案,其中深度学习技术作为新的引擎让人脸识别精度更高,场景更鲁棒。

研究内容包含DeepFace、DeepID、FaceNet、RetinaFace、ArcFace,更多参考资料有:1、Jiankang Deng, Jia Guo, Niannan Xue. ArcFace: Additive Angular Margin Loss for Deep Face Recognition.2、InsightFace: 2D and 3D Face Analysis Project:https://github.com/deepinsight/insightface.git3、ArcFace/Insight face模型及代码讲解:https://www.bilibili.com/video/BV1Vc411h7oN?from=search&seid=11946584543999450056 活体检测实现检测可能是照片、面具、模型以及图片合成、翻拍等风险场景。 换脸技术的应用场景有很多,比如数字人、元宇宙人像、虚拟主播和虚拟偶像等。 微表情识别(Micro-Expression Analysis)指对面部短暂而变化细微的动作识别,可以应用在金融风控、司法审讯等场景。 Haar-like特征+AdaBoost算法更多内容可以参考以下2个文献,读者朋友可以进一步理解积分图的概念和分类器的设计:[1] Viola P A , Jones M J . Rapid Object Detection using a Boosted Cascade of Simple Features[C]// Computer Vision and Pattern Recognition, 2001. CVPR 2001. Proceedings of the 2001 IEEE Computer Society Conference on. IEEE, 2001.[2] Viola P A , Jones M J . Robust Real-Time Face Detection[C]// Computer Vision, 2001. ICCV 2001. Proceedings. Eighth IEEE International Conference on. IEEE, 2001. Dlib官网地址:http://dlib.net/ 更多资料可以参考学习腾讯优图开源项目Tface:https://github.com/Tencent/TFace.git,关于Tface官方介绍引文:TFace: A trusty face recognition research platform developed by Tencent Youtu Lab. It provides a high-performance distributed training framework and releases our efficient methods implementation.This framework consists of several modules: 1. various data augmentation methods, 2. backbone model zoo, 3. our proposed methods for face recognition and face quality, 4. test protocols of evalution results and model latency.(译:Tface是腾讯优图实验室开发的一个可信的人脸识别研究平台,它提供一个高性能的分布式训练框架,并发布高效的方法实现。该框架由几个模块组成:1、各种数据增强方法;2、主干模型zoo;3、我们提出的人脸识别和人脸质量评估方法;4. 推理耗时评估和精度评估。)