张杜娟,丁莉,吴玉莲
(西安医学院卫生管理学院,陕西西安 710021)
人脸识别是利用人脸视觉特征信息的分析比较结果进行身份认证的一种生物特征识别技术[1],是计算机视觉中图像识别技术的应用典范,也是近几年人工智能的热点之一,机器对人脸的识别率比人眼识别率高。2015 年Google 研究人员训练了一个深度神经网络进行人脸识别,在LFW 数据测试集上的精确度为99.63%,而目前人类眼睛的识别率约为95%。通过人脸进行身份确定或身份查找,可以避免证件、磁卡、IC 卡和密码等传统身份鉴别技术缺陷。人脸识别可以大大减少人工的工作量,目前在金融、安防、车站、无人商店、公安系统等领域都有广泛的应用[2]。
该文详细论述了深度学习及基于卷积神经网络的人脸识别算法,以此为基础采用Python+Dlib 实现人脸检测和识别。
人脸识别包括人脸检测、特征点提取、人脸校准、人脸比对等过程[3]。通过对视频流中每帧人脸图像或静态图片中人脸进行检测、跟踪和分析,按照卷积神经网络二分类原理对图片进行卷积和池化,采用softmax 激活函数计算并判断人脸分类,从而检测出图片中是否包含一张或多张人脸,根据神经网络回归问题定位算法对已检测到的人脸采用矩形框进行位置标定;对图片进行灰度化,提取人脸特征,对得到的特征点进行选取,利用仿射变换进行人脸校正;将特征数值化,按照神经网络中相似度计算方法对校准后的人脸与自身的训练数据库中的人脸进行比对,判断被检测的人脸是否能被识别。其算法流程图如图1 所示。
图1 人脸识别算法流程
深度学习是机器学习的一个分支,基于对大量数据集的训练,学习表征这些数据的最佳特征。基于卷积神经网络(CNN)的深度学习方法是一类包含卷积计算且具有深度结构的前馈神经网络算法,已广泛应用在人脸特征提取及识别方面[4]。该原理是对人脸图像进行裁剪后输入到输入层,输出与对应剪裁矩阵大小相同的二维向量;在卷积层输入数据,用卷积核作为一个滑动窗口在图像矩阵上滑动,将与卷积核相似的特征放大,卷积核提取向量的特征,然后池化降低卷积层输出特征向量规模,经过若干个卷积和池化层后,最终通过全连接层输出人脸的特征,实现人脸比对[5]。
OpenCV 库是跨平台的计算机视觉库,其自带的人脸检测分类器基于HAAR 算法,通过对创建灰度图像直方图均衡化,采用HaarDetectObjects 针对级联分类器检测人脸标定矩形区域,收集所需数据并训练分类器[6]。通过实验发现,使用分类器文件有漏检和误检现象,因此该研究使用Dlib 库进行人脸检测和识别,调用OpenCV 库的图像处理函数对图片进行图像化处理。
Dlib 库包含大量机器学习算法和图形模型算法并支持数值算法[7],使用该库其实是调用对应的神经元网络结构,再把预先训练好的参数传给该网络。它包括人脸检测器、已训练好的人脸关键点检测器和人脸识别模型,提供Python 接口,方便调用。使用Dlib 深度学习人脸识别技术构建,在户外脸部检测数据库准确率为99.38%。
使用Dlib 库实现人脸识别前期环境配置较多,相对繁琐,但安装所需软件及库是必备的,要遵循配置次序,开发环境配置如图2 所示。
图2 开发环境配置
Dlib 库的安装依赖于编译环境CMake 和Boost库。其使用的库需编译成静态库,要预安装CMake,将它的bin 路径配置到系统环境变量并测试安装正确性。Boost 库可以提高开发效率,运行bootstrap.bat会生成 三个文 件:b2.exe、bjam.exe、project-config.jam,在cmd 中当前目录运行并编译后生成bin.v2 和stage 子目录,将已安装完成的boost 文件添加到环境变量BOOST_LIBRARYDIR 和BOOST_ROOT 中[8]。
安装Dlib 前,先在Python37Libsite-packages 下安装wheel,便于Python 模块安装。在cmd 中将当前路径定位到dlib 目录下,执行:pip install dlib 进行安装,使用pip list 在列表中查看是否成功安装。采用Dlib 做人脸识别,所需其他库可执行pip install+库名称安装在如上目录。
人脸检测是人脸识别的预处理,为了能在复杂场景中检测到是否有人脸,将人脸图像的位置和区域准确标定出来,在人脸识别时必须首先进行人脸检测。这一过程首先进行图像输入扫描,从静态图片或动态视频每帧图像中检测人脸,然后实施人脸判别,如果查找到人脸,对人脸所在区域进行全局检测,按输入的图像信息标定出所有人脸的位置,输出人脸框坐标[9]。
该文使用基于卷积神经网络的人脸检测原理,在进行人脸检测时,通过调用Dlib 库中人脸识别库face_recognition 和图像处理库opencv-python,利用Dlib库正向人脸检测器dlib.get_frontal_face_detector()来实现。face_detector()是基于HOG(方向梯度直方图)+回归树的方法,对颜色空间归一化,划分检测窗口成大小相同的细胞单元,利用梯度信息反映图像目标的边缘信息并通过局部梯度的大小将图像局部的外观和形状特征化,结合了线性分类器、图像金字塔和滑动窗口检测方案[10]。采用Dlib 中enumerate(faces)函数查找并计算图片中的人脸数目,通过循环算法,遍历所有人脸并标定人脸区域、获取矩形框的坐标并输出(如图3)。
图3 人脸检测结果
为了对检测到的人脸图像获取更多信息,需要进行特征点定位。人脸特征点定位是计算机对人脸图像分析的一种技术,通过定位可获取人脸面部外轮廓边界点、眉毛、眼睛、鼻尖、嘴角等部位特征点,可以精确指明人脸位置。利用Dlib 库训练好的人脸关键点检测器模型进行68 特征点标定并存入各点坐标,利用OpenCV 进行图像化处理,采用cv2.circle()函数在人脸上画出68 个点,cv2.putText()函数标出数字序号1-68。遍历人脸标定点坐标前,将读入的图片加载为数组后转化为灰度图片,在OpenCV 中图像是按反序BGR 颜色通道存储,与训练集采用的传统RGB 颜色通道不同,要通过平均法实施转化,使同一个像素位置的三个通道的值都相等[11],采用cv2.cvtColor(pic,cv2.COLOR_RGB2GRAY)实现颜色空间的转换。每张静态人脸图片和视频中每帧图片都能标记出68 个特征点[12],如图4 所示。
图4 静态和动态人脸检测及特征点定位
图片中的人脸可能存在多种姿态,如抬头、正脸、侧脸等,要提取到正确的人脸特征,需要对人脸进行对齐操作,摆正人脸,使其处于图像中央,尽量消除误差,输出的人脸特征更具可比性,提升比对的精度和准确率,减小比对时计算的压力。通常以标定的68 个特征点为基准,选取部分特征点,通过仿射变换矩阵实施人脸校正。这种校正方式对倾斜人脸信息提高有一定帮助,侧脸因缺少部分脸部信息不能实现正面化[13]。
进行人脸校正前,根据68 个特征点标定信息,可以定位出校正所用到的五个关键点(左眼,右眼,鼻尖,嘴的左角,嘴的右角)为(36,45,30,48,54)[14],以此为基础计算出偏离角度和中心点坐标,通过仿射变换函数进行角度矫正,不断迭代直到算法收敛。图像的仿射变换是通过一系列原子变换复合来实现,它是从二维坐标到二维坐标之间的线性变化且保持了图形的“平直性”和“平行性”。使用getRotationMatrix2D(center,angle,scale)函数获得变换矩阵M,center 表示旋转的中心点,angle 表示旋转角度,scale 表示缩放因子,获得的矩阵如公式(1):
其中,α=scale×cos(angle),β=scale×sin(angle),(center.x,center.y)表示旋转轴心。进行仿射变换算法思路:首先,计算参数,然后,进行仿射矩阵计算,最后,以此仿射矩阵为参数,采用warpAffine()函数进行仿射变换。实现效果如图5 所示。
图5 人脸校准
将矫正后的人脸送入人脸分类识别网络中,提取分类网络中的某个层作为人脸的特征层,得到人脸特征。通过卷积神经网络进行量化和计算特征产生128D 特征向量,用数字化代表每张人脸。每张人脸图片是由一定的像素构成,每个像素具有R、G、B三个通道,每个像素取值范围是0~255 字节,累计矩阵字节数作为输入数据,在深度学习中是生成一个近似函数f*(x),把输入数据转化为可用作特征分类的多个数值组成的向量特征值。
该文使用Dlib 已训练好的深度残差网络(ResNet)模型接口dlib_face_recognition_resnet_model_v1.dat,它是人脸特征提取的分类网络,利用它可以将人脸图像转换为128D 特征向量,通过return_128d_features()返回值列表。这样使相似人脸比较相近,不相似人脸比较远[15]。
一个人不同时期的照片是有差异的,裁截的人脸做检测有可能降低识别率,要想得出可靠的特征向量,需计算128D 特征向量的平均值(如式(2)),形成此人的平均脸方便辨识,以排除部分照片将人脸某部分特征放大或缩小,将结果保存为M行128 列的CSV 文件。
其中,xi表示第i个人脸的一维向量,M表示人脸采样数,φ表示平均脸向量。
人脸识别是通过将待识别人脸的特征和测试库中人脸特征做相似度比对,根据人脸相似程度进行身份信息判断。128D 特征向量提取后,根据待识别人脸的特征矩阵和数据训练库中人脸特征矩阵计算欧式距离,当距离小于指定阈值,其特征相似性较高,则认为是同一人;当距离大于指定阈值,其特征相似性较低,则认为不是同一人,通过多次迭代,若结果始终不是同一人,则认为在数据库中找不到此人。一般来说,欧氏距离越大,两个特征值相似度越低,属于同一个人的可能性越小。当比对身份为1∶N时,N(N表示数据库中的人脸数)越大表示数据库中特征向量越多,人脸识别效率越低。
在识别人脸目标时,需要进行集合内特征比对,采用欧氏距离计算特征向量间的相似性,设两个向量分别为x、y,n=128,其欧氏距离计算公式[16]如下:
Dlib 库中采用face_recognition.face_distance(tpk_encodings,img_test_encoding)作为接口计算欧氏距离,采用face_recognition.compare_faces()人脸匹配函数对待测图片和测试库中图片编码列表进行比对,该函数根据阈值确认是否为同一人脸,默认判别阈值为0.6,阈值过高,人脸比对通过率低,经反复测试此处阈值修改为0.4。主要算法思想:导入face_recognition,使用FOR 循环加载同一测试库文件夹下所有图片及待测图片,将所有加载图片像素转化为人脸面部编码,采用循环算法计算欧氏距离并比对待测图片与测试库中所有图片的相似性,用逻辑值表达结果。关键代码:
其中,face_distances 表示比较的面部的欧氏距离,results 是一个True/False 数组,表示待测图像的面部与已知测试库数组中每个人的匹配结果。结果发现,待测人脸与第二张图片中人脸欧氏距离为0.223 201<0.4,即待测图片与该图中是同一个人,执行结果如图6 所示。
图6 欧氏距离计算及比对结果
文中提出了采用Python+Dlib 方法进行人脸识别,有效克服了OpenCV 的漏检、误检等问题,算法简便,其优势在于使用开源库作为Python 接口,对于静态图片、动态视频及实时摄像头视频均可较好地实现人脸检测和识别,效率和精度较高。对于侧脸、偏转较大、颜色与环境较相似的人脸检测算法及检测耗时长等问题要做进一步研究,以提高检测效果和检测效率。