使用OpenCV和Python进行人脸识别


介绍

  人脸识别是什么?或识别是什么?当你看到一个苹果时,你的大脑会立刻告诉你这是一个苹果。在这个过程中,你的大脑告诉你这是一个苹果水果,用简单的语言来说就是识别。那么什么是人脸识别呢?我肯定你猜对了。当你看着你的朋友走在街上或他的照片时,你会认出他是你的朋友保罗。有趣的是,当你看你的朋友或他的照片时,你首先要看他的脸,然后再看其他东西。你想过为什么要这么做吗?这是为了让你看他的脸就能认出他来。好吧,这是你的面部识别。

  但真正的问题是人脸识别是如何工作的?它非常简单和直观。举一个现实生活中的例子,当你在生活中第一次遇见一个人,你不认识他,对吧?当他和你说话或握手时,你看着他的脸、眼睛、鼻子、嘴巴、颜色和整体的表情。这是你通过收集面部数据来学习或训练那个人的面部识别。然后他告诉你他叫保罗。此时,你的大脑知道它刚刚学到的面部数据属于保罗。现在你的头脑已经训练好了,准备在保罗的脸上做面部识别。下次当你在照片中看到保罗或他的脸时,你会立刻认出他。这就是人脸识别的工作原理。你遇到保罗的次数越多,你的大脑就会收集到更多关于他的信息,尤其是他的脸,你就越能识别他。

  下一个问题是如何用OpenCV编码人脸识别,毕竟这是你阅读这篇文章的唯一原因,对吧?那么,好吧。你可能会说我们的大脑可以很容易地做这些事情,但是把它们编码到电脑里是很困难的吗?别担心,不是的。多亏了OpenCV,编码人脸识别变得越来越容易。人脸识别的编码步骤与我们在上面的实际示例中讨论的一样。

  ·训练数据收集:收集您想要识别的人的面部数据(本例中为面部图像)

  ·识别器的训练:将人脸数据(以及每个人脸的相应名称)输入人脸识别器,使其能够学习。

  ·识别:输入这些人的新面孔,看看你刚训练过的人脸识别器是否识别他们

 

OpenCV带有内置的人脸识别器,你所要做的就是给它输入人脸数据。这很简单,一旦我们完成了编码,它就会看起来很简单。

 

如果您需要这篇文章程序的话,请点击这段话,进行下载!

OpenCV面部识别器

  OpenCV有三个内置的人脸识别器,多亏了OpenCV干净的编码,你可以通过改变一行代码来使用它们中的任何一个。下面是这些人脸识别器的名称和它们的OpenCV调用

  1、EigenFaces人脸识别器识别器 - cv2.face.createEigenFaceRecognizer()

  2、FisherFaces人脸识别器识别器 - cv2.face.createFisherFaceRecognizer()

   3、局部二值模式直方图(LBPH)人脸识别器 - cv2.face.createLBPHFaceRecognizer()

  现在我们有三个人脸识别器,但是你知道该用哪一个吗?什么时候用吗?或者哪个更好?我猜你不知道。那么,接下来我们将深入研究每一个识别器。

 EigenFaces面部识别器

  这个算法考虑的事实是,并不是脸的所有部分都同样重要,或同样有用。当你看一个人的时候,你会通过他独特的特征认出他/她,比如眼睛、鼻子、脸颊、前额以及他们之间的差异。所以你实际上关注的是最大变化的区域(数学上说,这个变化是方差)。例如,从眼睛到鼻子有一个显著的变化,从鼻子到嘴也是如此。当你看多张脸的时候你可以通过看脸的这些部分来比较它们因为这些部分是脸最有用和最重要的组成部分。重要的是,它们捕捉到人脸之间的最大变化,这种变化可以帮助你区分不同的人脸,这就是特征人脸识别系统的工作原理。

  EignFaces人脸识别器将所有人的训练图像作为一个整体,并试图提取重要和有用的成分(捕捉最大方差/变化的成分),并丢弃其余的成分。这样,它不仅从训练数据中提取重要的组件,而且通过丢弃不重要的组件来节省内存。它提取的这些重要成分被称为主成分。

  我所用主成分,方差,高变化区域,可互换的有用特征等术语,它们的性质基本上是一样的东西。
  以下是显示从面部列表中提取的主要组件的图像。

主成分

source

  你可以看到,主分量实际上表示面的,这些面被称为特征面,也就是算法的名字。

  这就是特征面识别器自身的训练方式(通过提取主成分),它还记录了哪个主成分属于哪个人。在上面的图像中需要注意的一点是特征面算法也将光照作为一个重要的组成部分。

  在随后的识别过程中,当你向算法输入新图像时,它也会在该图像上重复同样的过程。它从新映像中提取主组件,并将该组件与它在训练期间存储的组件列表进行比较,并找到匹配最好的组件,并返回与该最佳匹配组件关联的person标签。

  轻松+容易,对吧? 下一个比这个更容易。

FisherFaces人脸识别器

  该算法是改进后的FisherFaces人脸识别算法。FisherFaces人脸识别器同时查看所有人的训练面,并从所有人的训练面中找到主要的组成部分。通过从所有的人脸中捕获主要的组成部分,你并没有把注意力集中在区分一个人和另一个人的特征上,而是集中在代表整个训练数据中所有人的所有面孔的特征上。

  这种方法有一个缺点。 例如,考虑下面的面光照变化。

  你知道特征面人脸识别器也认为照明是一个重要的组成部分,对吧?想象一个场景,一个人所有的脸都有非常高的亮度变化(非常暗或者非常亮等等)。特征人脸识别者将会考虑这些光照变化非常有用的特征,并且可能会忽略其他人的面部特征,认为这些特征不太有用。现在所提取的特征特征面只代表一个人的面部特征,而不是所有人的面部特征。

  如何解决这个问题? 我们可以通过调整EigenFaces人脸识别器来解决这个问题,以便从每个人的脸部分别提取有用的特征,而不是提取所有脸部组合的有用特征。 这样,即使一个人的光照变化很大,也不会影响其他人物特征提取过程。 这正是FisherFaces人脸识别器算法的功能。

  Fisherfaces算法不是提取表示所有人员所有面部的有用特征,而是提取可区分一个人和另一个人的有用特征。 通过这种方式,一个人的特征不会占据主导地位(被认为是更有用的特征)而其他人则具有区分一个人和另一个人的特征。

下面是使用Fisherfaces算法提取的特征的图像。

  Fisher Faces

 

   你可以看到提取的特征实际上代表了面孔,这些面被称为Fisher faces,因此算法的名称。

  这里需要注意的一点是,Fisherfaces人脸识别器只会阻止一个人的特征凌驾于另一个人的特征之上,但它仍然认为光照变化是有用的特征。我们知道光照变化不是一个有用的特征来提取,因为它不是真正的脸的一部分。那么,该怎么摆脱这个照明问题?这就是我们的下一个人脸识别器锁解决的问题。

 局部二值模式直方图(LBPH)人脸识别器

  我们知道Eigenfaces和Fisherfaces都受光线影响,在现实生活中,我们无法保证完美的光照条件。 LBPH人脸识别器是克服这个缺点的一种改进。

  这种想法是不看整个图像,而是查找图像的局部特征。 LBPH算法试图找出图像的局部结构,并通过比较每个像素与其相邻像素来实现。

  取一个3x3的窗口,每移动一个图像(图像的每个局部),将中心的像素与相邻像素进行比较。强度值小于或等于中心像素的邻域用1表示,其它邻域用0表示。然后你以顺时针的顺序读取3x3窗口下的0/1值,你会得到一个像11100011这样的二进制模式,这个模式在图像的特定区域是局部的。在整个图像上这样做,就会得到一个局部二进制模式的列表。

LBP标签

  现在你明白为什么这个算法的名字中有局部二进制模式? 因为你得��一个局部二进制模式列表。 现在你可能想知道,LBPH的直方图部分呢? 在获得局部二进制模式列表后,您可以使用二进制到十进制转换将每个二进制模式转换为十进制数(如上图所示),然后对所有这些十进制值进行直方图制作。 样本直方图是像下面这样的。

  样本直方图

 

  我猜这回答了直方图部分的问题。所以最终你会得到训练数据集中每个人脸图像的一个直方图,这意味着如果训练数据集中有100个图像,那么LBPH会在训练后提取100个直方图,并储存起来以便以后识别。记住,算法也会跟踪哪个直方图属于哪个人。

  在识别后期,当您将新图像送入识别器进行识别时,它将生成新图像的直方图,将该直方图与其已有的直方图进行比较,找到最佳匹配直方图并返回与该最佳匹配关联的人员标签 匹配直方图。

  下面是一张脸和它们各自的局部二进制模式图像的列表。您可以看到,LBP图像不受光照条件变化的影响。

  局部人脸

 

  理论部分已经结束,现在是编码部分!准备好开始编写代码了吗?那我们开始吧。

使用OpenCV编码人脸识别

  本教程中的人脸识别过程分为三个步骤。

  1、准备训练数据:在这一步中,我们将读取每个人/主体的训练图像及其标签,从每个图像中检测人脸并为每个检测到的人脸分配其所属人员的整数标签。

  2、训练人脸识别器:在这一步中,我们将训练OpenCV的LBPH人脸识别器,为其提供我们在步骤1中准备的数据。

  3、测试:在这一步中,我们会将一些测试图像传递给人脸识别器,并查看它是否能够正确预测它们

 

 编程工具:

  1. OpenCV 3.2.0.
  2. Python v3.5.
  3. NumPy 

   :Numpy使Python中的计算变得容易。 除此之外,它还包含一个强大的N维数组实现,我们将使用它来将数据作为OpenCV函数的输入。

导入必需的模块

  在开始实际编码之前,我们需要导入所需的编码模块。 所以让我们先导入它们。

  cv2:是Python的OpenCV模块,我们将用它来进行人脸检测和人脸识别。

  os:我们将使用这个Python模块来读取我们的培训目录和文件名。

  numpy:我们将使用此模块将Python列表转换为numpy数组,因为OpenCV人脸识别器接受numpy数组。

#导入OpenCV模块
https://www.linuxboy.net/topicnews.aspx?tid=17

linuxboy的RSS地址:https://www.linuxboy.net/rssFeed.aspx

本文永久更新链接地址:https://www.linuxboy.net/Linux/2019-06/158931.htm

相关内容