作者|Jerin Paul
编译|Flin
来源|towardsdatascience

这是一个繁忙的市场场景;七月的烈日在头顶上照耀。炎热的天气并没有阻止顾客的到来。在人群不知情的情况下,一个怀有恶意的人藏在他们中间。他披着一层正常的外衣,走着去实现他的邪恶目的。

在一个角落里,一个监控摄像头会定期扫描这个区域,这时它会瞥见这个家伙。它会立刻认出看到的每一张脸,而且碰巧这家伙是一个通缉犯。几毫秒之内,他附近的警察就得到了警报,他们开始着手消除这一威胁。

这个故事曾经出现在科幻小说中,但现在情况大不相同了。事实上,中国使用人工智能监控工具来监视本国公民。智能手机的创造者也在积极地使用人脸识别来验证手机用户的身份。

人脸识别有很多不同的应用程序,不管你希望它用于什么目的,在本文中,我将指导你创建一个自定义的人脸识别程序。你将建立一个小应用程序,可以在视频剪辑或网络摄像头中识别你选择的人脸。

就像你看到的那样,这就是我们要得到的效果图。

在本文中,我们将建立一个自定义的人脸识别程序。这篇文章很容易理解,同时也让你对这个机器学习项目的理论知识方面有所启发。

这是一个全面的、互动性强的人脸识别初学指南。接下来,我们将创建一个自定义的人脸识别程序,该程序能够检测和识别视频或实时网络摄像头中的人脸。

目录

专业提示:如果你想快速完成任务,请跳过理论部分,直接进入第2部分。

  1. Facenet

    i. Facenet是什么?

    ii. Facenet是如何工作的?

    iii. 三重损失

  2. 我们开始构建吧!

    i. 先决条件

    ii. 下载数据

    iii. 下载Facenet

    iv. 对齐

    v. 获得预先训练的模型

    vi. 用我们的数据训练模型

    vii. 在视频源上测试我们的模型

  3. 缺点
  4. 结论
  5. 参考文献

Facenet

在这个项目中,我们将使用一个名为Facenet的系统来为我们做人脸识别程序。

 Facenet是什么?

Facenet是由Florian Schroff、Dmitry Kalenichenko和James Philbin构建的系统。他们也为此写了一篇论文。

它直接从人脸图像中学习图像到欧式空间上点的映射,其中距离直接对应于人脸相似度的度量。一旦创建了这些嵌入,就可以使用这些嵌入作为特征来完成人脸识别和验证等过程。

 Facenet是如何工作的?

Facenet使用卷积层直接从人脸的像素学习。该网络在一个大数据集上进行训练,以实现对光照、姿态和其他可变条件的不变性。该系统是在 Labelled Faces in the wild(http://vis-www.cs.umass.edu/l... 数据集上训练的。这个数据集包含13000多张从网络上收集的不同人脸的图片,每个人脸都有一个名字(标签)。

Facenet从图像中创建128维嵌入,并将其插入特征空间,这样,无论成像条件如何,相同身份之间的特征距离要尽可能的小,而不同身份之间的特征距离要尽可能的大。下图描述了模型体系结构:

模型结构:模型包含一个批处理输入层、一个深入学习架构和一个L2层。这就产生了人脸嵌入。

 三重损失

该系统采用一种特殊的损失函数,称为三重损失。三重损失使同一身份的图像之间的L2距离最小,使不同特征的人脸图像之间的L2距离最大。

该系统采用三重损失,更适合于人脸验证。使用三重损失的动机是它鼓励将一个身份的所有图像投影到嵌入空间中的一个点上。

三重损失:学习前后

创作者们设计了一种高效的三重选择机制,可以一次巧妙地选择三幅图像。这些图像有以下三种类型:

  1. 锚:一个随机的人的图。
  2. 正图:同一个人的另一张图。
  3. 负图:另一个人的图。

测量了两个欧几里德距离:一个是锚和正图之间的距离,我们称之为A;另一个是锚和负图之间的距离,我们称之为B。训练过程旨在减少A并使B最大化,这样相似的图像彼此靠近,不同的图像在嵌入空间中会隔得很远。

 开始构建!

最精彩的部分开始了!我们可以使用Facenet为我们自己选择的人脸创建嵌入,然后训练支持向量机(Support Vector Machine)使用这些嵌入并进行分类。让我们开始建立一个自定义的人脸识别程序吧!

你可以看看这个项目的Github存储库,因为它包含了一个自定义数据集和用于在视频中检测人脸的脚本。

 先决条件

在开始之前,请确保你的系统上安装了以下库:

  1. tensorflow==1.7
  2. scipy
  3. scikit-learn
  4. opencv-python
  5. h5py
  6. matplotlib
  7. Pillow
  8. requests
  9. psutil
 下载数据

在这个项目中,我们将创建一个人脸识别程序,将能够识别90年代情景喜剧《老友记》的核心人物。如果你想识别一组不同的人脸,那么就用你的图像来代替。只需确保遵循类似的目录结构——为要识别的每个身份创建一个文件夹,并将这些文件夹存储在名为“raw”的文件夹中。

数据集目录:注意每个角色如何拥有自己对应的文件夹

在每个文件夹里放上人物的照片。请注意,每张图片只有一张清晰可见的脸。尽管只需要很少的图像,我还是为每个角色添加了20个图像。每个文件夹都有相同数量的图片。你可以从这里下载我创建的《老友记》的数据集。顺便说一下,这是“Chandler”文件夹的样子:

 下载Facenet

现在已经结束收集数据了。请继续下载Facenet repo。下载并提取它,并将“Dataset”文件夹放入其中。

 对齐

该模型的一个问题是它可能会漏掉一些人脸标志,为了解决这个问题,我们必须将数据集中的所有图像对齐,使眼睛和嘴唇在所有图片中显示在同一位置。我们将使用M.T.C.N.N.(多任务C.N.N.)来执行相同的操作,并将所有对齐的图像存储在名为processed的文件夹中。

打开终端/命令提示符并导航到Facenet目录。然后运行align_dataset_mtcn.py以及以下参数。

python src/align_dataset_mtcnn.py \
./Dataset/Friends/raw \
./Dataset/Friends/processed \
--image_size 160 \
--margin 32 \
--random_order \ 
--gpu_memory_fraction 0.25

运行此命令将对齐所有图像并将其存储在各自的文件夹中,然后将所有内容存储在“processed”文件夹中。下图将向你介绍对齐的工作原理:

所有图像都被裁剪并与标准的160x160像素图像对齐。

 获得预先训练的模型

现在,为了在你自己的图像上训练模型,你需要下载预先训练的模型。请从这里下载。

在Facenet根目录中创建一个名为“Models”的文件夹。下载完成后,将zip文件的内容解压缩到名为“facenet”的目录中,并将此文件夹放在“Models”文件夹中。

这个模型是在LFW数据集上训练的,因此所有的人脸嵌入都存储在这些文件中。这使我们有机会冻结图像,并在我们自己的图像上训练它。这样做会将我们提供的所有人脸嵌入到维度空间中。

 用我们的数据训练模型

我们都准备好了!我们有一个预先训练好的模型,我们的自定义数据集已经对齐并准备好了。现在,是时候训练模型了!

python src/classifier.py TRAIN \
./Dataset/Friends/processed \
./Models/facenet/20180402-114759.pb \
./Models/Friends/Friends.pkl \
--batch_size 1000

执行上述命令将加载预先训练的模型并启动训练过程。训练结束后,新图像的嵌入将导出到/Models/Friends/中。

由于我们使用的是预先训练的模型和相对较少的图像数量,因此训练过程很快就结束了。

 在视频源上测试我们的模型

为了测试我们的模型,我使用的是来自《老友记》的视频。你可以用自己的视频来代替,甚至可以用摄像头。在本节中,我们将编写脚本,以便于在视频源中进行人脸识别。

导航到“src”文件夹并创建一个新的python脚本。我给它起名 faceRec.py。

接下来,我们导入所有必需的库。

此脚本只接受一个参数,即视频文件的路径。如果没有提到路径,那么我们将通过网络摄像头传输视频。因此,参数的默认值为0。

我们将初始化一些变量。请确保根据文件夹结构更改路径。

加载自定义分类器。

设置Tensorflow图,然后加载Facenet模型。使用GPU将加快检测和识别过程。

设置输入和输出张量。

pnet、rnet和onet是M.T.C.N.N.的组成部分,将用于检测和对齐人脸。

接下来,我们将创建一个集合和一个来跟踪检测到的每个角色的集合。

设置视频捕获对象。

因此,如果在运行程序时未将VIDEO_PATH作为参数传递,则它将假定默认值为0。如果发生这种情况,视频捕获对象将从网络摄像机流式传输视频。

然后逐帧捕获视频,并且由检测人脸模块在这些帧中检测人脸。找到的人脸数存储在facesu found变量中。

如果找到人脸,那么我们将迭代每个人脸并将边界框的坐标保存在变量bb中。

然后提取、裁剪、缩放、重塑这些人脸并输入字典。

我们将使用该模型来预测人脸的身份。我们提取最佳类概率或置信度。这是衡量我们的模型是如何确定预测的身份属于给定的脸。

最后,我们将在人脸周围画一个边界框,并在边界框旁边写下预测的身份和置信度。如果置信度低于某个阈值,我们将把名字填为未知。

一定要放一个except语句。这将确保成功忽略抛出的任何错误。确保放置except语句。这样做有助于我们忽略错误。

except: pass

显示视频并在过程结束后关闭视频显示窗口。因为每一帧都要经过大量的处理,所以视频回放可能会很慢。

恭喜你,你的耐心得到了回报!我们已经完成了脚本,准备好了!快速启动并执行以下命令以启动人脸识别程序。请确保将要测试的视频的路径作为参数传递,或将其留空以从网络摄像机流式传输视频。

python src/faceRec.py --path ./Dataset/Friends/friends.mp

好吧,这个系统还不完善,还有一些缺点。

 缺点

  1. 系统总是试图将每个人脸都匹配到一个给定的身份中。如果屏幕上出现新人脸,系统将为其分配一个或另一个身份。这个问题可以通过仔细选择一个阈值来解决。
  2. 身份的混淆。在上面的gif中,你可以观察到Joey和Chandler之间的预测有时是如何波动的。而且,置信度得分也很低。使用更多图像训练模型将解决此问题。
  3. 无法在一定距离识别人脸(如果距离很远使得人脸看起来很小)。

 结论

无论是判断你的员工是否出席或在野外寻找违法者,人脸识别技术可以证明是一个真正的保障。这个项目包括创建一个人脸识别程序,可以识别你选择的人脸。你创建了一个自定义数据集,训练了模型,并编写了脚本以在视频剪辑上运行人脸识别系统。然而,也有一些缺点,但我们的系统功能还是比较完整的。

 参考文献

https://arxiv.org/abs/1503.03832

原文链接:https://towardsdatascience.co...

欢迎关注磐创AI博客站:
http://panchuang.net/

sklearn机器学习中文官方文档:
http://sklearn123.com/

欢迎关注磐创博客资源汇总站:
http://docs.panchuang.net/


人工智能遇见磐创
101 声望97 粉丝