FaceNet算法-理论学习篇

@WP20190228

==============目 录============

一、LFW数据集简介

二、FaceNet算法简介

  FaceNet算法=MTCNN模型+FaceNet模型

三、FaceNet算法理论

  3.1 MTCNN人脸检测与对齐模型

  3.2 FaceNet人脸比对模型

四、FaceNet的基本使用

  4.1 FaceNet环境安装

  4.2 使用1-评估预训练模型的准确率

    4.2.1 处理数据集(对齐数据集)

    4.2.2 解压下载已训练模型

    4.2.2 评估模型准确率

  4.3 使用4-FaceNet测试“人脸比对”效果

  4.4 使用2-MTCNN进行人脸检测

  4.5 使用3-训练自己的FaceNet模型

五、主要函数作用说明

六、其他

==============正 文============

前言

与传统的生物识别技术相比,人脸识别具有更为简便、准确、经济及可扩展性良好等众多优势,可广泛应用于安全验证、监控、控制等各个方面。

一,人脸相关的任务有以下几种:

  1.人脸检测(将图片中包含的人脸进行初步定位,以及关键点如眼睛、鼻子、嘴巴等更精细的定位,文章封面即为典型人脸检测结果);

  2.人脸跟踪(视频中跟踪人脸位置变化);

  3.人脸验证(输入两张人脸,判定是否属于同一人);

  4.人脸识别(输入一张人脸,判断其属于人脸数据库全部记录中具体哪一人);

  5.人脸聚类(输入一批人脸,将属于同一人的自动归为一类);

二,严格定义上的人脸识别分为四个步骤:

  ①人脸检测:从图片中准确定位到人脸。

  ②人脸矫正(对齐): 检测到的人脸,可能角度不是很正,需要使其对齐。

  ③对矫正后的人脸进行特征提取。

  ④对两张人脸图像的特征向量进行对比,计算相似度。

一、LFW数据集介绍

1. LFW数据集是由美国马萨诸塞大学阿姆斯特分校计算机视觉实验室整理的人脸检测数据集,是评估人脸识别算法效果的公开测试数据集,全称为带标签的自然人脸数据库(Labeled Faces in the Wild);

2. LFW数据库内每张图片命名方式为“lfw/name/name_xxxx.jpg”,这里“xxxx”是前面补零的四位图片编号。例如,前美国总统乔治•W•布什的第10张图片为“lfw/George_W_Bush/George_W_Bush_0010.jpg”。

3. LFW数据库 总共有 13233 张 JPEG 格式图片,属于 5749 个不同人。每张图片尺寸都是 250x250;

4. 原图像大小为250*250, 后续会将待检测所使用的数据集校准为和预训练模型所使用的数据集大小一致(160*160),转换后的数据集存储在lfw_160文件夹内;

二、FaceNet算法简介

1.论文《FaceNet: A Unified Embedding for Face Recognition and Clustering》。

2.FaceNet算法的提出:由Google工程师Florian Schroff,Dmitry Kalenichenko,James Philbin提出的人脸识别模型,发表于CVPR 2015。

3.FaceNet论文实验结果:主要是利用相同人脸在不同角度等姿态的照片下有高内聚性、不同人脸有低耦合性,提出的一种人脸识别方法,在LFW数据集上准确度达到99.63%,在 youtube人脸数据集上准确度 95.12%,比以往准确度提升了将近30%。

4.FaceNet的特点:没有用传统的softmax的方式去进行分类学习,而是抽取其中某一层作为特征,学习一个从图像到欧式空间的编码方法,然后基于这个编码再做人脸识别、人脸验证和人脸聚类等。

5.FaceNet的理论思想:是把人脸图像映射到一个多维空间,通过空间距离表示人脸的相似度。同一个人脸图像的空间距离比较小,不同人脸图像的空间距离比较大,这样通过人脸图像的空间映射就可以实现人脸识别。即,通过CNN将人脸映射到欧式空间的特征向量上,计算不同图片人脸特征的距离。通过相同人脸的距离总是小于不同人脸的距离,这一先验知识训练网络,进而可以直接对比2个人脸经过它的网络映射之后的欧式距离,判断是否为同一人。

6.FaceNet测试使用:因为FaceNet只需要计算人脸特征,然后计算距离使用阈值即可判定两张人脸照片是否属于相同的个体,所以在使用FaceNet时可以使用已经训练好的模型,也可以自己训练模型,最后根据两幅人像的欧几里得距离去判断两个人像的相似程度:两个人像之间的欧几里得距离越近,说明它们越相似。从初级应用的角度来看,已经训练好的模型已经足够强大,我们只需将一个基准图片与待分类图片通过FaceNet模型比较欧几里得距离,即可完成人脸识别任务。

6.FaceNet人脸比对的判断:该算法主要用于验证人脸是否为同一个人,通过“人脸识别这个人是谁”完成人脸比对。判断依据是“两幅人像的欧几里得距离”,如给定一个阈值a=1,那么:当特征距离等于0的时候,认为是同一张图片(同一个人);当特征距离小于1的时候,认为是同一个人;特征距离大于1的时候,认为不是同一个人。

7.FaceNet数据集:(1)训练数据,包括10575个人,共453453张图片,可以从http://www.cbsr.ia.ac.cn/english/CASIA-WebFace-Database.html 下载。(2)验证数据集包含13000张图片,可以从http://vis-www.cs.umass.edu/lfw/ 地方下载,大约180M。训练数据中,目录名是人名,目录下的文件是对应人的照片。

8.FaceNet算法常用实现任务:人脸识别。人脸识别包括:人脸检测和人脸识别。其中,人脸检测方法很多,如Dilb,OpenCV,OpenFace人脸检测等等,这里使用MTCNN进行人脸检测,一方面是因为其检测精度确实不错;另一方面facenet工程中,已经提供了用于人脸检测的mtcnn接口,在facenet工程中的位置是align/detect_face.py。所以,FaceNet包含(1)MTCNN模型---人脸检测与人脸对齐;(2)FaceNet模型---人脸比对。

总结:FaceNet算法 = MTCNN模型 + FaceNet模型

三、FaceNet算法理论

参考个人觉得比较好的博客《如何应用MTCNN和FaceNet模型实现人脸检测及识别》和《利用MTCNN和facenet实现人脸检测和人脸识别》,非常感谢博主。

(注:http://www.uml.org.cn/ai/201806124.asp 和 https://blog.csdn.net/guyuealian/article/details/84896733 )

3.1 MTCNN人脸检测与对齐模型

(1)MTCNN的简介:

MTCNN全称: Multi-task convolutional neural network(多任务卷积神经网络),是一种Multi-task的人脸检测框架,将人脸区域检测与人脸关键点检测放在了一起,基于cascade框架。

论文原名: 《Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks》,发表在arXiv上,是2016年4月份的文章。论文使用3个CNN级联的方式,总体可分为PNet、RNet、和ONet三层网络结构。

MTCNN可实现两个任务: 人脸检测与人脸关键点检测, 由三个级联的轻量级CNN完成:PNet,RNet和Onet。图像数据先后经这三个网络的处理,最终输出人脸检测和关键点检测结果。本算法从三个方面对CNN检测器进行训练:人脸分类(人脸、非人脸的分类)、边界框回归、地标定位(关键点定位)。

(https://github.com/kpzhang93/MTCNN_face_detection_alignment)

开源资源:

论文链接:https://arxiv.org/ftp/arxiv/papers/1604/1604.02878.pdf 

Github链接(tf版本):https://github.com/AITTSMD/MTCNN-Tensorflow

论文中使用的两个公开数据集:

Wider(http://mmlab.ie.cuhk.edu.hk/projects/WIDERFace/ )它有以下几个特点:

1) 人脸检测基准数据集

2) 包含32203个图像和393703个人脸图像

3) 尺度,姿势,闭塞,表达,装扮,光照等变化大

4) 40%作为训练集,10%用于交叉验证(cross validation),50%作为测试集

5) 无背景边界框

和Celeba(http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html )数据集,它由以下特点:

1) 5个关键点,40个属性值

2) 高清的名人图片

3) 用于人脸检测,5点训练,人脸头部姿势的训练

 

MTCNN的主要步骤:

由于本人没有阅读论文原文,参考网上资源如下,感谢各位博主。

<参考一>如下,

Stage 0:当给定一张照片的时候,将其缩放到不同尺度形成图像金字塔,以达到尺度不变。

Stage 1:使用P-Net是一个全卷积网络,用来生成候选窗和边框回归向量(bounding box regression vectors)。使用Bounding box regression的方法来校正这些候选窗,使用非极大值抑制(NMS)合并重叠的候选框。全卷积网络和Faster R-CNN中的RPN一脉相承。

Stage 2:使用N-Net改善候选窗。将通过P-Net的候选窗输入R-Net中,拒绝掉大部分false的窗口,继续使用Bounding box regression和NMS合并。

Stage 3:最后使用O-Net输出最终的人脸框和特征点位置。和第二步类似,但是不同的是生成5个特征点位置。

<参考二>如下,

Stage1:首先将图像进行不同尺度的变换,构建图像金字塔,以适应不同大小的人脸的进行检测。

Stage2:P-Net,全称为Proposal Network,其基本的构造是一个全连接网络。对上一步构建完成的图像金字塔,通过一个FCN进行初步特征提取与标定边框,并进行Bounding-Box Regression调整窗口与NMS进行大部分窗口的过滤。

Stage3:R-Net,全称为Refine Network,其基本的构造是一个卷积神经网络,相对于第一层的P-Net来说,增加了一个全连接层,因此对于输入数据的筛选会更加严格。在图片经过P-Net后,会留下许多预测窗口,我们将所有的预测窗口送入R-Net,这个网络会滤除大量效果比较差的候选框,最后对选定的候选框进行Bounding-Box Regression和NMS进一步优化预测结果。

Stage4:O-Net,全称为Output Network,基本结构是一个较为复杂的卷积神经网络,相对于R-Net来说多了一个卷积层。O-Net的效果与R-Net的区别在于这一层结构会通过更多的监督来识别面部的区域,而且会对人的面部特征点进行回归,最终输出五个人脸面部特征点。

<参考三>如下,

Stage 1:采用全卷积神经网络,即P-Net,去获得候选窗体和边界回归向量。同时,候选窗体根据边界框进行校准。然后,利用NMS方法去除重叠窗体。

stage 2:R-Net,将经过P-Net确定的包含候选窗体的图片在R-Net网络中 训练,网络最后选用全连接的方式进行训练。利用边界框向量微调候选窗体,再利用NMS去除重叠窗体。

stage 3:O-Net,网络结构比R-Net多一层卷积,功能与R-Net作用一样,只是在去除重叠候选窗口的同时,显示五个人脸关键点定位。

说明:

P-Net输入:待检测的图像。

输出:m*n(最终特征图的尺度)个box坐标回归值以及对应的是否为人脸的得分。经过进一步的计算,得到可能为人脸的box集合。

     中间过程简述:将原图重采样(resample),得到一系列尺寸的待检测图。对于每一张待检测图,输入到PNet,会输出一系列box,去掉那些得分(score)不达标的box,并用非极大值抑制(nms)再去掉一部分box。对于所有尺寸的待测图,都得到类似的box集合。将所有box集合合并,再用nms去除一部分box,余下的就是第一阶段最终的输出。

R-Net输入:第一阶段生成的box,在原图中截取对应的区域,将所有截取得到的图像合 并到一个四维矩阵中,作为RNet的输入。

输出:对于输入的每个box,输出其对应的坐标回归值以及对应的是否为人脸的得 分。将得分不达标的box去掉,得到第二阶段的box集合。也就是说,第二 阶段是在第一阶段的基础上对box实现进一步分筛选,同时也会以通过回归 将box坐标进行更新,使得其精度更高。

O-Net人脸检测阶段

输入:类似于RNet,但以第二阶段的输出为输入。

输出:类似于RNet。

O-Net人脸关键点检测阶段,

输入:3.1中最终得到的人脸图像。

输出:N*(2*5)个坐标值。其中N是人脸的数目,每个人脸检测5个关键点。

中间过程简述:略。

(2)MTCNN与FaceNet

FaceNet”人脸对齐对齐“的实现,是采用基于深度学习方法的mtcnn人脸检测系统。github上的facenet工程,提供了用于人脸检测的MTCNN接口。

github上的facenet工程,为了便于测试,MTCNN也一放在了工程文件中,在工程中的位置是src/align/detect_face.py,MTCNN的参数模型也保存在align文件夹下,分别是det1.npy,det2.npy,det3.npy。MTCNN的用法是先将网络搭建出来,定位input中的人脸的位置,然后返回自己设置的固定大小的脸部crop,然后再将其输入facenet就可以了。MTCNN目的是为了“人脸检测+定位+对齐”,因为当前的首要任务是让工程能跑起来,并且对其有一个大体的认识,方便后面的学习,具体的实现原理和代码解读,以及物体的检测发展历史,目前的发展方向,各种检测的算法,暂不作笔记。

可见,FaceNet提供训练数据的对齐(align)功能,它能自动完成待训练或者待测试图片的人脸检测并缩放为指定大小尺寸的JPEG数据以供训练或测试。

注:https://blog.csdn.net/guyuealian/article/details/84896733,提供了一个函数,使用MTCNN进行人脸检测的方法,作者建议封装成一个类,方面初始化和单独调用。

 

3.2 FaceNet人脸识别模型

FaceNet,进行人脸识别的流程:

1.通过MTCNN人脸检测模型,从照片中提取人脸图像。

2.把人脸图像输入到FaceNet,计算Embedding的特征向量。

3.比较特征向量间的欧式距离,判断是否为同一人,例如当特征距离小于1的时候认为是同一个人,特征距离大于1的时候认为是不同人。

FaceNet的网络结构如下图所示,其中Batch表示人脸的训练数据,接下来是深度卷积神经网络,然后采用L2归一化操作,得到人脸图像的特征表示,最后为三元组(Triplet Loss)的损失函数。

四、FaceNet的基本使用

4.1 FaceNet环境安装

 环境配置:Ubuntu 18.04 + Tensorflow 1.5.0 + Python 2.7 + OpenCV 3.2.0

 环境安装:略过。(本篇,主要记录理论学习笔记。)

4.2 使用1-评估预训练模型的准确率

4.2.1 处理数据集(对齐数据集)

因为程序中神经网络使用的是谷歌的“inception resnet v1”网络模型,这个模型的输入时160*160的图像,而我们下载的LFW数据集是250*250限像素的图像,所以需要进行图片的预处理。

我们可以下载LFW数据集用来测试这个程序,也为后边的训练函数做好数据准备。

下载链接:http://vis-www.cs.umass.edu/lfw/。下载后解压在data文件夹中。

图片预处理——运行人脸对齐程序(align\align_dataset_mtcnn.py)

在运行时需要输入的参数:

1.input_dir:输入图像的文件夹(facenet/data/lfw),原始数据文件夹。

2.output_dir:输出图像的文件夹(facenet/data/lfw_mtcnn_160),对齐后的文件夹。

3.指定裁剪后图片的大小:--image_size 160 --margin 32 --random_order(如果不指定,默认的裁剪结果是182*182像素的)

执行命令:

$ cd facenet

$ python src/align/align_dataset_mtcnn.py data/lfw/raw data/lfw/lfw_mtcnn_160 --image_size 160 --margin 32

$ python src/align/align_dataset_mtcnn.py data/lfw/raw data/lfw/lfw_mtcnn_160 --image_size 160 --margin 32 --random_order --gpu_memory_fraction 0.25 #使用GPU时

进过对齐校准后,在图像输出文件下就会发现图像大小变成160*160。如下图,左边是未处理的图片,右边是处理后的图片,可以看到,左边是人的半身照,右边是人脸照,并且,右边图像的大小是160×160。

4.2.2 解压下载已训练模型

可以参考,链接:https://pan.baidu.com/s/1nvBX233 密码:s0sb

https://download.csdn.net/download/rookie_wei/10609076,解压之后,会的的4个文件。

4.2.2 评估模型准确率

评估模型在数据集的准确率—运行程序(src/validate_on_lfw.py)

$ python src/validate_on_lfw.py data/lfw/lfw/lfw_mtcnn_160  models/20180402-114759

如果不好用,注意使用:模型给绝对路径。

结果示例:

Runnning forward pass on LFW images

Accuracy: 0.992+-0.003

Validation rate: 0.97467+-0.01477 @ FAR=0.00133

Area Under Curve (AUC): 1.000

Equal Error Rate (EER): 0.007

说明,lfw数据集不经过对齐处理,也可以执行上述命令,观察结果。

4.3 使用4-FaceNet测试“人脸比对”效果

人脸比对---运行程序(facenet-master\src\compare.py)

有了模型,就可以执行人脸对比。在compare.py所在目录下放入要对比的人脸图像43.jpg和44.jpg(完全不同的2人脸图);

利用预训练的模型,测试人脸比对效果,执行命令如下:

$ cd facenet

$ python compare.py models\20170511-185253\20170511-185253 43.jpg 44.jpg

$ python compare.py models\20170511-185253\20170511-185253 Cate_Blanchett_0001.png  Cate_Blanchett_0002.png

说明,lfw数据集不经过对齐处理,也可以执行上述命令,观察结果。

4.4 使用2-MTCNN进行人脸检测

MTCNN进行人脸检测和人脸对齐,目前网上已经有很多资源可以学习了。比如利用它进行自己人脸识别库的训练与识别,已经有MTCNN—Caffe、MTCNN—TF版本的工程实现了,个人以后也会动手练习。

这里主要是MTCNN结合facenet,两者结合实现人脸识别。因github上的facenet工程提供了用于人脸检测的MTCNN接口,故直接调用会使用即可。即,上面的图像预处理步骤,执行命令:

$ cd facenet

$ python src/align/align_dataset_mtcnn.py data/lfw/raw data/lfw/lfw_mtcnn_160 --image_size 160 --margin 32

4.5 使用3-训练自己的FaceNet模型

想要训练自己的FaceNet模型,参考“Classifier training of inception resnet v1”。

1.准备数据。

要自己训练模型,先要找一些自己准备的图片。这些准备的图片只是为了训练面部特征的表示,和后面要识别的对象没有关系。建议,可以从你的相册中准备一些图片,或者下载标准的的训练样本(如LFW数据集)。自己准备的数据要满足一定的格式:以人名为文件夹,文件夹内,以人名加编号来存储图像文件。

2.对齐数据。

因为准备的图像可能是比较随意,比如在郊外的一个全身照。这里需要运行 MTCNN算法来检测头像,并缩放到合适的尺寸,以供FaceNet模型进行训练,比如160*160 pixel。官方给了方法,参考大神的博客可以写成align.sh脚本:

---------------------------------------align.sh------------------------------------------

export PYTHONPATH=PYTHONPATH:$(pwd)/src

python src/align/align_dataset_mtcnn.py data/my/raw/ data/my/lfw_160/ –image_size 182 –margin 44

------------------------------------------------------------------------------------------------

这里data/my/raw/目录就是你准备的原始数据的位置,data/my/lfw_160就是对齐后的数据目录。

3.开始训练数据。

    把官方的方法也写成脚本training.sh,内容如下:

------------------------------------------training.sh-----------------------------------------

export PYTHONPATH=PYTHONPATH:$(pwd)/src

python src/train_softmax.py \

–logs_base_dir ./data/my/logs/facenet/ \

–models_base_dir ./data/my/models/facenet/ \

–data_dir ./data/my/lfw_182/ \

–image_size 160 \

–model_def models.inception_resnet_v1 \

–lfw_dir ./data/lfw/lfw_160/ \

–optimizer ADAM \

–learning_rate -1 \

–max_nrof_epochs 150 \

–keep_probability 0.8 \

–random_crop \

–random_flip \

–use_fixed_image_standardization \

–learning_rate_schedule_file data/learning_rate_schedule_classifier_casia.txt \

–weight_decay 5e-4 \

–embedding_size 512 \

–lfw_distance_metric 1 \

–lfw_use_flipped_images \

–lfw_subtract_mean \

–validation_set_split_ratio 0.05 \

–validate_every_n_epochs 5 \

–prelogits_norm_loss_factor 5e-4

------------------------------------------------------------------------------------------------

其中,

–lfw_dir ./data/lfw/lfw_160/ 参数指定的对齐后的训练数据的位置。

–models_base_dir ./data/my/models/facenet/参数指定了生成的模型的位置。

执行-training.sh,等待漫长的训练过程,静等训练后的模型。

当然,直接使用他人生成好的模型,效果就立竿见影。如前面介绍,直接的应用就是Facenet可以直接对比2个人脸经过它的网络映射之后的欧式距离。有了模型,就可以执行人脸对比。

4.开始训练数据。

$ python src/compare.py models/20170511-185253/20170511-185253 Cate_Blanchett_0001.png Cate_Blanchett_0002.png

其中models/20170511-185253/20170511-185253指下载的facenet训练好的模型,Cate_Blanchett_0001.png 和 Cate_Blanchett_0002.png 是要对比的图像。

参考:

https://blog.csdn.net/ygd11/article/details/80724621?utm_source=blogxgwz7。

https://github.com/davidsandberg/facenet/wiki/Classifier-training-of-inception-resnet-v1。

 

五、主要函数作用说明

facenet/contributed/相关函数:

1、基于mtcnn与facenet的人脸聚类

代码:facenet/contributed/cluster.py(facenet/contributed/clustering.py实现了相似的功能,只是没有mtcnn进行检测这一步)

主要功能:

① 使用mtcnn进行人脸检测并对齐与裁剪

② 对裁剪的人脸使用facenet进行embedding

③ 对embedding的特征向量使用欧式距离进行聚类

2、基于mtcnn与facenet的人脸识别(输入单张图片判断这人是谁)

代码:facenet/contributed/predict.py

主要功能:

① 使用mtcnn进行人脸检测并对齐与裁剪

② 对裁剪的人脸使用facenet进行embedding

③ 执行predict.py进行人脸识别(需要训练好的svm模型)

3、以numpy数组的形式输出人脸聚类和图像标签

代码:facenet/contributed/export_embeddings.py

主要功能:

① 需要对数据进行对齐与裁剪做为输入数据

② 输出embeddings.npy;labels.npy;label_strings.npy

六、其他

综合多篇网络资源,花了两天的时间,自己学习并整理了这篇文章,如有谬误,敬请指出! 十分感谢各位小主,还有很多未列出来的~~~

参考:

https://blog.csdn.net/qq_14845119/article/details/52680940 

https://blog.csdn.net/qq_36782182/article/details/83624357 

https://kpzhang93.github.io/MTCNN_face_detection_alignment/index.html 

https://github.com/kpzhang93/MTCNN_face_detection_alignment/tree/master/code/codes 

https://blog.csdn.net/wshdkf/article/details/79956976

https://blog.csdn.net/guyuealian/article/details/84896733

 

----------文中涉及的图片,未上传---------------

05-04 10:47