0.写在前面
从OpenCV2.4开始,加入了新的类FaceRecognizer,我们可以使用它便捷地进行人脸识别实验。因为opencv3里人脸识别的实验已经转移到contrib里的face模块中,因为opencv3需要额外编译contrib,我电脑还没有编译这个模块。所以本实验还是继续用opencv2.4,可以直接使用facerecognizer。
本实验采用的编程环境为:opencv3.0+VS2013。
FaceRecognizer这个类目前包含三种人脸识别方法:基于PCA变换的人脸识别(EigenFaceRecognizer),也叫特征脸方法、基于Fisher变换的人脸识别(FisherFaceRecognizer)、基于局部二值模式的人脸识别(LBPHFaceRecognizer)。对于像我这样的人脸识别初学者,对人脸识别理论了解得不是很透彻,但并不影响对函数的使用,下面就EigenFaceRecognizer来详细的谈一下opencv人脸识别的实现。
我这里用的是ORL人脸数据库,英国剑桥实验室拍摄的,有40位志愿者的人脸,在不同表情不同光照下每位志愿者拍摄10张,共有400张图片,大小为112*92
1.算法介绍
实现特征脸的过程其实就是主成分分析(Principal Component Analysis,PCA)的一个过程。
1.1PCA
首先介绍一下主成分分析,PCA是一个常用的降维方法。
首先我们思考一下,对于正交属性空间的样本点,如何用一个超平面对所有样本进行恰当的表达?我们可以想到,若存在这样的超平面,那么它应该有这样的性质:
(1)最近重构性:样本点到这个超平面的距离都足够近;
(2)最大可分性:样本点在这个超平面上的投影能尽可能分开;
PCA算法要求满足上面两个条件,但是从这两点出发,推导后有殊途同归的结果,我这里推导过程省略,结果是对于原空间的d维所有数据样本X,只需要对协方差矩阵X*X.T进行特征值分解,将求得的特征值从大到小排序,再取前d'个特征值对应的特征向量,这些特征向量构成的矩阵就是将原空间从d维降到d'维的投影矩阵W。
1.2 Eigenface
我们有了PCA的理论,现在来看看如何把PCA运用到人脸识别上。包含人脸的图像区域看作是一种随机向量,图像中较大特征值的基底W具有与人脸相似的形状,因此又称为特征脸。利用这些基底W的线性组合可以描述、表达和逼近人脸图像,因此可以进行人脸识别与合成。现在我们有了投影矩阵(基底)W,然后我们把训练集所有样本投影到这个超平面上,然后测试的时候把测试图片也投到超平面上,与测试图片欧式距离最小的那个样本的编号,就是最大概率的哪个人的人脸。
具体步骤如下(如果用opencv库,这些步骤都可以通过函数一步调用实现):
(1)获取包含M张人脸图像的集合S。在我们的例子里有400张人脸图像。每张图像可以转换成一个N维的向量(一个像素一个像素的排成一列)然后把这M个向量放到一个集合S里(N*M)。
(2)在获取到人脸向量集合S后,计算得到平均图像Ψ (把集合S里面的向量遍历一遍进行累加,然后取平均值)。这里注意Ψ 也是一个N维向量(N*1),我们只是让S的每列相加,也就是分别求每副图片的平均值。
(3)计算每张图像和平均图像的差值Φ (N*M) ,就是用S集合里的每一列减去步骤二中的平均值的对应列,也就是每副图片减去自己图片的平均值。
(4)计算如下协方差矩阵的特征向量:
然后找到前k个特征向量Uk。
(5)这K个特征向量组成的矩阵设为w。将偏差矩阵转置乘以w,得到协方差矩阵的特征向量。
(6)现在我们有了投影矩阵W,可以把训练集所有样本投影到超平面(特征脸空间)上。
(6)输入新的人脸图像,转换成一维向量,将其映射到特征脸空间,得到一组关于该人脸的特征数据;
(7)通过检查图像与人脸空间的距离判断它是否是人脸;
(8)若为人脸,根据权值模式判断它是否为数据库中的某个人,并做出具体的操作。
3.工程实现
3.1 准备数据
我这里用的是ORL人脸数据库,英国剑桥实验室拍摄的,有40位志愿者的人脸,在不同表情不同光照下每位志愿者拍摄10张,共有400张图片