写点什么

如何应用 MTCNN 和 FaceNet 模型实现人脸检测及识别

  • 2018-05-29
  • 本文字数:4482 字

    阅读完需:约 15 分钟

人脸检测与人脸识别

人脸检测是对人脸进行识别和处理的第一步,主要用于检测并定位图片中的人脸,返回高精度的人脸框坐标及人脸特征点坐标。人脸识别会进一步提取每个人脸中所蕴涵的身份特征,并将其与已知的人脸进行对比,从而识别每个人脸的身份。目前人脸检测 / 识别的应用场景逐渐从室内演变到室外,从单一限定场景发展到广场、车站、地铁口等场景,人脸检测 / 识别面临的要求也越来越高,比如:人脸尺度多变、数量冗大、姿势多样包括俯拍人脸、戴帽子口罩等的遮挡、表情夸张、化妆伪装、光照条件恶劣、分辨率低甚至连肉眼都较难区分等。随着深度学习的发展,基于深度学习技术的人脸检测 / 识别方法取得了巨大的成功,本文主要介绍人脸检测的深度学习模型 MTCNN 和人脸识别的深度学习模型 FaceNet。

2016 年 Kaipeng Zhang, Zhanpeng Zhang, Zhifeng Li, Yu Qiao 提出了人脸检测 MTCNN(Multi-task Cascaded Convolutional Networks)模型。该模式是一种 Multi-task 的人脸检测框架,使用 3 个 CNN 级联算法结构,将人脸检测和人脸特征点检测同时进行,检测效果如下图所示:

Google 工程师 Florian Schroff,Dmitry Kalenichenko,James Philbin 提出了人脸识别 FaceNet 模型,该模型没有用传统的 softmax 的方式去进行分类学习,而是抽取其中某一层作为特征,学习一个从图像到欧式空间的编码方法,然后基于这个编码再做人脸识别、人脸验证和人脸聚类等。人脸识别效果如下图所示,其中横线上表示的数字是人脸间的距离,当人脸距离小于 1.06 可看作是同一个人。

MTCNN 模型

MTCNN 是多任务级联 CNN 的人脸检测深度学习模型,该模型中综合考虑了人脸边框回归和面部关键点检测。MTCNN 的网络整体架构如下图所示:

首先照片会按照不同的缩放比例,缩放成不同大小的图片,形成图片的特征金字塔。PNet 主要获得了人脸区域的候选窗口和边界框的回归向量。并用该边界框做回归,对候选窗口进行校准,然后通过非极大值抑制(NMS)来合并高度重叠的候选框。RNet 将经过PNet 的候选框在RNet 网络中训练,然后利用边界框的回归值微调候选窗体,再利用NMS 去除重叠窗体。ONet 功能与RNet 作用类似,只是在去除重叠候选窗口的同时,同时显示五个人脸关键点定位。

MTCNN 人脸检测的训练数据可以从 http://mmlab.ie.cuhk.edu.hk/projects/WIDERFace/ 地址下载。该数据集有 32,203 张图片,共有 93,703 张脸被标记,如下图所示:

标记文件的格式如下所示:

复制代码
#文件名
File name
#标记框的数量
Number of bounding box

#其中 x1,y1 为标记框左上角的坐标,w,h 为标记框的宽度,blur, expression, illumination, invalid, occlusion, pose 为标记框的属性,比如是否模糊,光照情况,是否遮挡,是否有效,姿势等。

x1, y1, w, h, blur, expression, illumination, invalid, occlusion, pose

人脸关键点检测的训练数据可从 http://mmlab.ie.cuhk.edu.hk/archive/CNN_FacePoint.htm 地址下载。该数据集包含 5,590 张 LFW 数据集的图片和 7,876 张从网站下载的图片。如下所示:

标记文件的格式为:

#第一个数据为文件名,第二和第三个数据为标记框左上角坐标,第四和第五个数据为标记框长宽,第六和第七个数据为左眼标记点,第八和第九个数据为右眼标记点,第十和第十一个数据为左嘴标记点,最后两个坐标为右嘴标记点。

lfw_5590\Abbas_Kiarostami_0001.jpg 75 165 87 177 106.750000 108.250000 143.750000 108.750000 131.250000 127.250000 106.250000 155.250000 142.750000 155.250000

PNet 的网络结构是一个全卷积的神经网络结构,如下图所:

该训练网络的输入是一个12*12 大小的图片,所以训练前需要生成PNet 网络的训练数据。训练数据可以通过和Guarantee True Box 的IOU 的计算生成一系列的bounding box。可以通过滑动窗口或者随机采样的方法获取训练数据,训练数据分为三种正样本,负样本,中间样本。其中正阳本是生成的滑动窗口和Guarantee True Box 的IOU 大于0.65,负样本是IOU 小于0.3,中间样本是IOU 大于0.4 小于0.65。

然后把bounding box resize 成12*12 大小的图片,转换成12*12*3 的结构,生成PNet 网络的训练数据。训练数据通过10 个3*3*3 的卷积核,2*2 的Max Pooling(stride=2)操作,生成10 个5*5 的特征图。接着通过16 个3*3*10 的卷积核,生成16 个3*3 的特征图。接着通过32 个3*3*16 的卷积核,生成32 个1*1 的特征图。最后针对32 个1*1 的特征图,可以通过2 个1*1*32 的卷积核,生成2 个1*1 的特征图用于分类;4 个1*1*32 的卷积核,生成4 个1*1 的特征图用于回归框判断;10 个1*1*32 的卷积核,生成10 个1*1 的特征图用于人脸轮廓点的判断。

RNet 的模型结构如下所示:

模型输入为24*24 大小的图片,通过28 个3*3*3 的卷积核和3*3(stride=2)的max pooling 后生成28 个11*11 的特征图;通过48 个3*3*28 的卷积核和3*3(stride=2)的max pooling 后生成48 个4*4 的特征图;通过64 个2*2*48 的卷积核后,生成64 个3*3 的特征图;把3*3*64 的特征图转换为128 大小的全连接层;对回归框分类问题转换为大小为2 的全连接层;对bounding box 的位置回归问题,转换为大小为4 的全连接层;对人脸轮廓关键点转换为大小为10 的全连接层。

ONet 是 MTCNN 中的最后一个网络,用于做网络的最后输出。ONet 的训练数据生成类似于 RNet,检测数据为图片经过 PNet 和 RNet 网络后,检测出来的 bounding boxes,包括正样本,负样本和中间样本。ONet 的模型结构如下所示:

模型输入是一个48*48*3 大小的图片,通过32 个3*3*3 的卷积核和3*3(stride=2)的max pooling 后转换为32 个23*23 的特征图;通过64 个3*3*32 的卷积核和3*3(stride=2)的max pooling 后转换为64 个10*10 的特征图;通过64 个3*3*64 的卷积核和3*3(stride=2)的max pooling 后转换为64 个4*4 的特征图;通过128 个2*2*64 的卷积核转换为128 个3*3 的特征图;通过全链接操作转换为256 大小的全链接层;最好生成大小为2 的回归框分类特征;大小为4 的回归框位置的回归特征;大小为10 的人脸轮廓位置回归特征。

MTCNN 模型推理

MTCNN 的 Inference 流程如下图所示:

由原始图片和 PNet 生成预测的 bounding boxes。输入原始图片和 PNet 生成的 bounding box,通过 RNet,生成校正后的 bounding box。输入元素图片和 RNet 生成的 bounding box,通过 ONet,生成校正后的 bounding box 和人脸面部轮廓关键点。执行过程如下所示:

  1. 首先读入要检测的图片:image = cv2.imread(imagepath)
  2. 加载训练好的模型参数,构建检测对象:detector = MtcnnDetector
  3. 执行推理操作:all_boxes,landmarks = detector.detect_face(image)
  4. 绘制目标框:cv2.rectangle(image, box,(0,0,255))

FaceNet 模型

FaceNet 主要用于验证人脸是否为同一个人,通过人脸识别这个人是谁。FaceNet 的主要思想是把人脸图像映射到一个多维空间,通过空间距离表示人脸的相似度。同个人脸图像的空间距离比较小,不同人脸图像的空间距离比较大。这样通过人脸图像的空间映射就可以实现人脸识别,FaceNet 中采用基于深度神经网络的图像映射方法和基于 triplets(三联子)的 loss 函数训练神经网络,网络直接输出为 128 维度的向量空间。

FaceNet 的训练数据可以从 http://www.cbsr.ia.ac.cn/english/CASIA-WebFace-Database.html 下载,该训练数据包括 10575 个人,共 453453 张图片。验证数据集可以从 http://vis-www.cs.umass.edu/lfw/ 地方下载,该数据集包含 13,000 张图片。训练数据的组织结构如下所示,其中目录名是人名,目录下的文件是对应人的照片。

复制代码
Aaron_Eckhart
Aaron_Eckhart_0001.jpg
Aaron_Guiel
Aaron_Guiel_0001.jpg
Aaron_Patterson
Aaron_Patterson_0001.jpg
Aaron_Peirsol
Aaron_Peirsol_0001.jpg
Aaron_Peirsol_0002.jpg
Aaron_Peirsol_0003.jpg
Aaron_Peirsol_0004.jpg
...

接着对该训练数据中每个图片进行预处理,通过 MTCNN 模型把人脸检测出来,生成 FaceNet 的训练数据,如下图所示:

形成相应的数据结构如下所示:

复制代码
Aaron_Eckhart
Aaron_Eckhart_0001_face.jpg
Aaron_Guiel
Aaron_Guiel_0001_face.jpg
……

FaceNet 的网络结构如下图所示:

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

下图为 FaceNet 中采用的 Inception 架构的深度卷积神经网络:

模型结构的末端使用 triplet loss 来直接分类。triplet loss 的启发是传统 loss 函数趋向于将有一类特征的人脸图像映射到同一个空间。而 triplet loss 尝试将一个个体的人脸图像和其它人脸图像分开。三元组其实就是三个样例,如 (anchor, pos, neg),利用距离关系来判断。即在尽可能多的三元组中,使得 anchor 和 pos 正例的距离,小于 anchor 和 neg 负例的距离,如下图所示:

用数学公式可以表示为:

模型在每个 Mini Batch 的训练时,为了计算 triplet Loss 值,需要选定合理的 triplet 三元组。如果采用暴力的方法从所有样本中找出离他最近的反例和离它最远的正例,然后进行优化,查找时间太长,并且还会由于错误标签图像导致训练收敛困难。可采用在线生成 triplet 的方式,在每个 mini-batch 中,生成 triplet 的时候,找出所有的 anchor-pos 对,然后对每个 anchor-pos 对找出其 hard neg 样本。主要流程如下所示:

  1. 在 mini-batch 开始的时候,从训练数据集中抽样人脸照片。比如每一个 batch 抽样多少人,每个人抽样多少张图片,这样会得到要抽样的人脸照片。
  2. 计算这些抽样图片在网络模型中得到的 embedding,这样通过计算图片的 embedding 之间的欧式距离得到三元组了。
  3. 根据得到的三元组,计算 triplet-loss,进行模型优化,更新 embedding。

FaceNet 模型推理

FaceNet 模型推理流程如下所示:

  1. 通过 MTCNN 人脸检测模型,从照片中提取人脸图像。
  2. 把人脸图像输入到 FaceNet,计算 Embedding 的特征向量。
  3. 比较特征向量间的欧式距离,判断是否为同一人,例如当特征距离小于 1 的时候认为是同一个人,特征距离大于 1 的时候认为是不同人。

总结

本文首先介绍了人脸检测和人脸识别,人脸检测用于定位图片中的人脸,人脸识别用于识别人脸的身份。然后讲解了 MTCNN 模型的主要思想,并对 MTCNN 的关键技术进行分析,主要包括训练数据,网络架构,PNet,RNet,ONet 及模型推理。接着讲解了 FaceNet 模型的主要思想及关键技术包括训练数据,网络结构,损失方程及 Triplet 的选择。用户可应用 MTCNN 及 FaceNet 模型架构到工业领域中相关人脸检测及识别场景。

参考文献

[1] MTCNN: a Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks.
[2] https://github.com/AITTSMD/MTCNN-Tensorflow
[3] FaceNet: A Unified Embedding for Face Recognition and Clustering
[4] https://github.com/davidsandberg/facenet

作者简介

武维(微信:allawnweiwu):博士,现为 IBM 架构师。主要从事深度学习平台及应用研究,大数据领域的研发工作。

2018-05-29 18:1313032

评论

发布
暂无评论
发现更多内容

TiCDC 6.0 原理之 Sorter 演进

TiDB 社区干货传送门

TiDB 源码解读 6.x 实践

MFC|自绘Static控件

中国好公民st

c++ 7月月更

面试突击64:了解 HTTP 协议吗?

王磊

Java 面试题

CSS Houdini:用浏览器引擎实现高级CSS效果

vivo互联网技术

CSS 前端 引擎 css动画

文盘Rust -- 给程序加个日志

TiDB 社区干货传送门

开发语言

TiFlash 源码解读(四) | TiFlash DDL 模块设计及实现分析

TiDB 社区干货传送门

麒麟v10上部署TiDBv5.1.2生产环境的最佳实践

TiDB 社区干货传送门

实践案例 安装 & 部署

iOS中的多态

NewBoy

ios 前端 移动端 iOS 知识体系 7月月更

不习惯的Vue3起步三 の computed和watch

空城机

vue3.2 7月月更

TiFlash 面向编译器的自动向量化加速

TiDB 社区干货传送门

性能调优 应用适配

TiDB 之 TiCDC6.0 初体验

TiDB 社区干货传送门

迁移 安装 & 部署 6.x 实践

【C语言】进阶指针Four

謓泽

7月月更

利用ECS服务器搭建安防视频监控平台

DS小龙哥

7月月更

更贴心、更好学的Python自动化办公教程!

博文视点Broadview

ORACLE进阶(十三)using实现简化连接查询

No Silver Bullet

oracle 7月月更 using

滴-EventBus快速使用介绍-新手考驾照

芝麻粒儿

android EventBus 7月月更

Qt | 显示网络图片 QNetworkAccessManager

YOLO.

网络 图片 qt 7月月更

Python+JS逆向哪里多?必然是登录逻辑,投资界登录pwd参数解析

梦想橡皮擦

Python 7月月更

CSS 中 ::before 和 ::after 伪元素的几个实际用途

南城FE

CSS 前端 伪元素 7月月更

tidb-dm报警DM_sync_process_exists_with_error排查

TiDB 社区干货传送门

故障排查/诊断

Python|数据可视化——超星学习通助手后台数据的可视化处理

AXYZdong

Python 7月月更

Spring Cloud源码分析之Eureka篇第八章:服务注册名称的来历

程序员欣宸

Java spring SpringCloud Eureka 7月月更

微服务项目中,Spring Security 比 Shiro 强在哪?

冉然学Java

编程 微服务架构 spring security Java’

让秒杀狂欢更从容:大促背后的数据库(下篇)

TiDB 社区干货传送门

作用域与作用域链

是乃德也是Ned

JavaScript 前端 7月月更

百花齐放的家居行业联盟,三翼鸟率先撬动三个赛点

脑极体

一站式 DevOps 平台,让开发大不同

飞算JavaAI开发助手

带你全面了解compaction 的13个问题

TiDB 社区干货传送门

TiDB 底层架构 数据库架构设计

js对象的key到底加不加引号?

南极一块修炼千年的大冰块

7月月更

羊城“论剑”!大湾区百家AI企业共话如何打牢人工智能“长链”的发展根基

极客天地

使用Gitlab Jenkins Docker建立CI部署方案

沃德

程序员 jenkins 7月月更

如何应用MTCNN和FaceNet模型实现人脸检测及识别_语言 & 开发_武维_InfoQ精选文章