人脸识别《一》opencv人脸识别之收集人脸并学习

Posted xiaobai_xiaokele

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了人脸识别《一》opencv人脸识别之收集人脸并学习相关的知识,希望对你有一定的参考价值。

     收集人脸就是把刚完成预处理的人脸放入到预处理人脸数组中,同时往数组中放入一个标签(明确这张人脸所属的人)。例如,你可以使用第一个人的10张预处理人脸,10张第二个人的预处理的人脸,那么人脸识别算法的输入就会是一个包含20个预处理的人脸数组以及一个有20个整数的数组(前十个数字是0后10个数字是1)。

       人脸识别算法会学习如何区分不同人的人脸。这就涉及到训练阶段以及收集人脸作为训练数据集。人脸识别算法完成训练之后,就可以保存生成的知识到一个文件或者内存中,之后使用它来识别相机面前的人脸。这就是测试阶段,如果你直接对相机输入使用它,那预处理人脸会被认为是测试图像,如果你使用多张图测试(图像文件夹),那就被认为是测试集。

        提供一个能够覆盖测试集中可能出现的各种类型数据的训练集是非常重要的。例如,如果你只测试证件照那种,那么你就可以只提供证件照图像作为训练集,但是如果一个人会往左或者向上看,那你就应该保证训练集会包含这种数据,否则人脸识别算法会对无法识别它们,因为它们的脸差异很大。这同样适用于其他因素例如表情(例如,如果训练集中的一个人总是笑,但是测试集中的确实不笑的)或者是光线方向(例如训练集中左边光线强但是测试集中是右边光线强)那人脸识别算法就会识别困难,但是无法确定能够移除这些因素,特别是人脸的朝向,对人脸元素有非常大的位置影响。

        【注意】获得覆盖多种不同现实情况的好的训练集的一个方式就是对于每个人都旋转她的头包括正面,向左看,向上看,向右看,向下看。然后头向一边倾斜然后向上向下,同时也改变面部表情,例如交替笑容,生气,自然。如果收集人脸时每个人都遵循这种方式,那么人脸识别就能有非常大的概率识别出现实情况下的每个人。

        为了获得更好的结果,应该换位置和方向再一次执行,例如选择相机180度,从相机的相反方向走进然后重复整个过程,这样训练集就会包括非常多不同的光线条件。

       通常情况下,每个人有100个训练人脸会比10个给出更好地结果,但是如果所有100个都看起来差不多一样,那就仍然给不出好的效果,因为训练集拥有能够覆盖测试集的多种变化数据是非常重要的,而不是拥有大量数据的脸。所以为了保障训练集中的脸不是全都一样,我们应该增加一个明显的延迟在收集到的人脸中。例如如果一个相机每秒30帧,那么当人没有来得及转身的时候,几秒就会收集100多张人脸,所以最好是在人移动人脸的时候每秒收集一张。另外一个简单的方法来改善训练集中的变化就是只收集那种跟之前收集的人脸有明显不同的人脸。

收集预处理人脸来训练

       为了保证收集新人脸图至少间隔了1S,用getTickCount()来计算。

       为了比较两张图之间的相似性,逐像素的,使用L2相对误差,从一张图减去另一张图,求和平方值,然后再求平方根,所以如果人移动了,结果数值就很大,没有移动结果数值就很小。

       还可以使用镜像增加训练集,并且为了提醒已经新增加了训练集,可以通过显示图像的颜色变化。

训练人脸识别系统

       收集足够多的人脸之后,就可以使用ML算法来训练系统进行人脸识别。最简单的就是特征脸或者是ANN,特征脸倾向于比ANN优异,尽管她很简单,它也能像很多复杂人脸识别算法那样执行的很好,所以作为初学者的首选。

        任何想要继续深入人脸识别系统的读者都应该学习一下理论:

•  Eigenfaces (also referred to as Principal Component Analysis(PCA)
•  Fisherfaces (also referred to as Linear Discriminant Analysis(LDA)
•  Other classic face recognition algorithms (many are available at http://www.face-rec.org/algorithms/)
•  Newer face recognition algorithms in recent Computer Vision research papers (such as CVPR and ICCV at http://www.cvpapers.com/), as there are hundreds of face recognition papers published each year

       在本书中使用它们不需要理解它们,因为opencv提供了cv::Algorithm作为一个简单通用的方法来执行几个不同的算法。可以使用Algorithm::getList()来获得可用的算法。

OpenCV v2.4.1中提供的算法包括如下:
•  FaceRecognizer.Eigenfaces: Eigenfaces, also referred to as PCA, first used by Turk and Pentland in 1991.
•  FaceRecognizer.Fisherfaces: Fisherfaces, also referred to as LDA, invented by Belhumeur, Hespanha and Kriegman in 1997.
•  FaceRecognizer.LBPH: Local Binary Pattern Histograms, invented by Ahonen, Hadid and Pietikäinen in 2004.

【注意】更多关于人脸识别算法的实现包括文档,实例以及Python版本都可以在Philipp Wagner's website at http://bytefish.de/blog以及http://bytefish.de/dev/libfacerec/上找到。

        这些算法包含在opencv的contrib模块的FaceRecognizer类中。由于动态链接,有可能你的程序链接到contrib模型但是运行时没有实际加载成功(如果被认为是不需要的)。所以推荐获取FaceRecognizer算法之前首先调用cv::initModule_contrib()函数。这个函数只在opencv2.4.1以及更高级版本中可用,所以要保证你至少在编译时期的人脸识别算法可用。

        为了使用人脸识别算法需要首先用 cv::Algorithm::create<FaceRecognizer>()创建FaceRecognizer对象,然后使用model->train(preprocessedFaces, faceLabels);实际调用整个人脸识别训练算法。

观察学习到的知识

       其实这个不是必须的,但是是非常有帮助的,观察通过学习训练数据人脸识别算法产生的内部数据结构,尤其是你懂得所选算法背后的理论并且想要验证它是否有效或者是找出为什么没有期望中的有效。内部数据结构对于不同的算法来说可能不同,但是幸运的是,它们对于Eigenfaces以及Fisherfaces来说是一样的,所以只观察这两个。它们都是基于1D特征向量矩阵(当作为2D图像观察时,它们看起来就像是人脸),因此通常使用Eigenfaces算法把特征向量看做是Eigenfaces或者使用Fisherfaces算法时当做Fisherfaces。

        用简单的术语,Eigenfaces的基本思想是它计算一系列特殊图像(eigenface)并且混合比例(特征值),当以不同的方式混合时可以生成训练集中的每一张图像但是也可以被用来区分训练集中的每张图像。例如,如果训练集中的一些人脸拥有胡子而其他没有,那么就至少有一个eigenface显示有胡子,所以对于这个eigenface有胡子的训练人脸图像就会拥有一个高混合比例值来显示它有胡子,而没有胡子的图像则具有比较低的混合比例值。如果训练集有5个人每个人10张脸,那么就会有100个eigenface以及特征值来区分训练集中的这100个人脸,实际上它们会进行排序这样前面一些eigenface以及eigenvalue就会使最能够区分的,而最后的一些eigenface以及eigenvalue会是随机像素噪声它们不能够区分数据。所以实际上通常是去除一些最后的eigenface以及eigenvalue仅仅保留前50。

        与上面对比的,Fisherfaces的基本思想是不计算训练集中每个图像的eigenvector以及eigenvalue,只对每个人计算出一个特殊的eigenvector以及eigenvalue。所以在前面的例子中5个人每人20张人脸图,Eigenface会计算100个eigenface和eigenvalue而Fisherfaces只计算5个eigenface和eigenvalue。

       为了能够获得Eigenfaces以及Fisherfaces算法的内部数据结构,必须使用cv::Algorithm::get()函数来在运行时获取,编译时无法获得它们。数据结构被用作内部数学计算的一部分而不是图像处理,所以它们通常被存储为浮点数在0.0到1.0的范围,而不是8位无符号字符像素值域为0-255,就像普通图像那样。另外,它们经常作为一个1D行或者列矩阵或者是它们组成一个大的矩阵的许多1D的行或者列。所以你显示许多这些内部数据结构之前,你必须把它们转换成正确的矩形形状并且转换为0-255的8位uchar像素。因为矩阵数据可能是0.0-1.0或者是-1.0到1.0的或者是其他,可以使用cv::normalize()以及参数cv::NORM_MINMAX来保证不管输入范围是什么,输出范围都是0-255。

平均脸

     Eigenfaces以及Fisherfaces算法都会首先计算平均脸,也就是所有训练数据的算术平均,这样就可以从每个人脸图像去除平均图像来获得更好的人脸识别效果。

特征值,Eigenfaces以及Fisherfaces

       

以上是关于人脸识别《一》opencv人脸识别之收集人脸并学习的主要内容,如果未能解决你的问题,请参考以下文章

人脸识别《一》opencv人脸识别之人脸检测

OpenCV实践之路——人脸识别之三识别自己的脸

OpenCV — 人脸识别

OpenCV — 人脸识别

人脸识别《一》opencv人脸识别之预处理

OpenCV实践之路——人脸识别之二模型训练