浅谈PCA 人脸识别

http://blog.csdn.net/silence1214/article/details/7991577


前几天讨论班我讲了基于PCA的人脸识别,当时我自己其实也只是知道这个算法流程,然后基于该算法利用c++实现了,效果还不错。后来跟师兄一起讨论的时候,才发现这个PCA还是有相当深刻的意义。

PCA的算法:矩阵C=AAT,A的每一列是一张人脸(将一张人脸图片用一个列向量表示,即对于128*128的图片,将视为16384维的列向量),A的列数就是图片的张数。算法就是求矩阵C的特征向量,每个向量称之为特征脸[1]。为了简单,只取其中部分的特征向量,这些特征向量对应于某些特征值,通常是前M个大的特征值。这样便得到了M个特征向量。接下来就是将每张图片在这M个特征向量上做投影,得到一个M维的权重向量w=(w1,…wM),一个人可能有多张图片,于是将对应于这个人的权重向量做一个平均作为这个人的权重向量。然后对于每个新来的人脸,先求得一个权重向量,然后与人脸库中每个人的权重向量做比较,如果小于某个阈值,则认为他是人脸库中的这个人;否则视为unknown。当然,文章中还给出了另外一个判断一张图像是否是人脸的方法,这里不再讨论。对于计算的时候我们实际上求的是ATA,至于二者的关系,可以参考文章[1],因为与后面讨论的关系不大,这里不细说了。

有个上述简介,我们就大概知道了PCA到底是怎么做的了。刨根问底一下,C到底是什么,C的特征向量又到底是什么,对应于特征值大的特征向量有有什么意义。

1.C到底是什么?我们先看一下C的(i,j)元素是什么。很简单,就是A的第i行与AT的第j列的乘积。那么A的第i行又是什么呢?就是每张图片的第i个像素构成的一个向量。则C的(i,j)元素就是每张图片的第i个像素构成的向量与每张图片的第j个像素构成的向量的乘积。回忆一下概率论中的协方差cov(x,y)=E((x-x-)(y- y-)),这里x是x的平均。如果我们把图片的第i个像素视为一个随机变量Xi,那么人脸库中的每张人脸的第i个像素的取值即为这个随机变量的所有取值。根据注(注:A的每一列是一张人脸,这里的人脸是每张人脸减去了所有人脸的平均后的人脸),A的第i行的每个值都已经减去了Xi的均值,因此C的(i,j)元素就是随机变量Xi与Xj的协方差。到此,我们已经知道C是什么了

         2.C的特征向量是什么。我们知道对C求特征向量是找到一个可逆矩阵Q,使得Q-1CQ是一个对角阵D,D的元素即为特征值,Q中的每一列即为特征向量,与特征值所在的列一一对应。注意,因为C是实对称阵,故必然可以对角化。由于C是对称的,C的特征向量是正交的,因此Q便是一个正交阵,故Q-1即为QT。先从简单的角度来看,假设C已经是一个对角阵了,并且对角元素依次递减。即随机变量Xi与Xj(i!=j)时是不相关的,而Xi的方差则随着i的增大而减小。也就是前几个像素是方差比较大的像素,即在第一个像素上,每张图片的值变化最大,第二个像素次之,依此类推。举个例子,假设第一个像素表示人脸的额头上的某个点(也许你会问,第一个像素不是图片的最左上角的那个像素吗?为什么会是额头上的某个点,后面会说明为什么可以这么假设),而在这个点上,有些人有痣,有些人没有,那么这一点的方差就会比相邻的额头上的其他点大,因为其他点上,每个人的额头都差不多,因此其像素值也差不多,方差就小了。现在来考虑QTAATQ=D,这里依然假设D中的元素依次递减。对于QTA,QT的每一行是一个特征向量,QT的第i行与A的每一列相乘得到QTA的每一行,从矩阵的角度也可以看作是用QT对A做一个变换。记住这里的QTA可以看做前面讨论的A,那么变换的结果就是使得QTA前面的行对应的是方差大的像素,而且这个变换会把方差最大的放到了第一行(因为D的降序排列),这里也就解释了为什么前面那个例子可以认为第一个像素是额头上的某个点,因为做了变换。我们选择了QT的前M行作为特征向量,因为他们对应了前M个大的特征值。这里可以举一个直观但是不一定恰当的例子,人的头发部分对应的那些像素,经过QT变换后回到某个像素上,那么这个像素会是QTA中的哪个位置呢,我认为应该是QTA的列中靠下面的像素,因为在头发这个像素的地方每个人基本都是头发(这句话很别扭,我是想说,对于比较正规的人脸库,即每张人脸不会有太大的变化,某个人头发的对应的那几个像素对于其他人来说也都是头发,因此变换后这个像素对于每个人都差不多,方差小,固然会在比较靠后的位置了)。QTA的每一列的前M个元素对应的就是每张人脸的权重向量w。因此每张人脸的权重向量的同一个分量可以看作是新的像素,这些新的像素对应着方差依次减小的像素。对于一张新来的人脸,让他在特征向量上作投影得到权重向量,在这些方差大的像素处,如果跟某个人的比较接近,则认为是这个人,这个也是合理的。至此,也许没能讲清楚特征向量是什么,但我想对应于特征值大的特征向量有什么意义这一点也交代的差不多了。

         3.2中交代了说了,这里想不到有什么需要补充的了。

         理解了这几个问题之后,PCA简洁明了(这本来就是的)而又有深刻意义了。我突然发现原来看似简单的理论其实水深的很,o(︶︿︶)o !我看文章实在是不够认真,如果没有师兄提问,估计我也不会去想这个问题。再次感谢WF师兄。

 

[1]Eigenfaces for Recognition. Matthew Turk,Alex Pentland 1991

注:A的每一列是一张人脸,这里的人脸是每张人脸减去了所有人脸的平均后的人脸






PCA人脸识别过程

1:一共有N个人脸,每个人脸按照像素从左到右,从上到下,计算出来每个人脸的相像素个数M,则形成人脸矩阵M*N,接着对这个矩阵每行的值减去均值形成新的矩阵,然后对这个矩阵求它的协方差矩阵,继续对协方差矩阵求前m个值最大的特征向量(特征向量是M*1的),然后形成Feature Vectures(M*m)的。记这个矩阵为A

2:对人脸库的每个人的脸(一个人可能有多个人脸图,此时对这个人的多个人脸图做平均分别对A求投影,这个投影出来形成权重矩阵(1*m),图形库中一共有N个人脸,那么也就有N个1*m的权重矩阵。

3:新来的图片,(用相同的方法:对A求投影)计算权重矩阵(1*m),然后和N个1*m的权重矩阵求距离,距离哪个最近就确定为哪个人脸。



在PCA中是对数据矩阵X(m*n)来做的降维,我事先是把m作为一个图片的全部维度,n代表样本,于是按照XX'来找特征向量等,由于一个图片最少也有1000+的像素,但是1000+的方阵在matlab中只要以计算就会是内存溢出,我正纳闷之际,看了别人的matlab源代码发现都是用X'来做的,也就是用X'X来计算协方差矩阵的。(但是这又跟上面描述的那两段有出入,搞笑。。。)

维基百科中对PCA中这个X的描述,竟然是这么描述的:


对于一个人的10副图,每一副图片按照从上到下,从左到右组成一个行向量,这个行向量的维度为n。a1,a2,...a10组成一个10*n的矩阵A。接下来说一下用matlab做的过程:
1:计算A的没列的平均值meanA矩阵,这个矩阵的大小是1*n的。
2:计算A的协方差矩阵,直接利用matlab的命令covImages = cov(A),得到的协方差矩阵为n*n的。
3:计算covImages的特征值和特征向量,利用命令[V, D] = eig(covImages),这样直接把covImages的特征向量和特征值放在了V和D中,由于covImages是一个对称矩阵,所以D中的对角线元素师按照从小到大的,而我们PCA要的是特征值较大的那个,所以为了取得方便,我们做如下变换D = flipud(diag(D)),同时V = fliplr(V)。此时D是一个n*1的矩阵,从上到下按照从打到小排列的,V是其中与D中每一个值对应的特征向量。根据PCA的定义,我们取最大特征值对应的特征向量也就是eigenFace = V(,:1)作为特征脸(主成分方向就是特征脸)
4:计算人脸在特征脸上的投影,由于这个人有10副图,任意选一个都可以来计算投影,我们选择第一个吧,记firstFace = A(:,1)-meanA,来计算first
Face在投影上的一个权重Weight=eigenFace'*meanA'。
5:以上过程可以叫做是我们叫做人脸识别的学习阶段,主要就是为了获取每一个人的Weight。
6:新来一副图片,让这个图片分别减去所以学习到的meanA,然后计算在对应eigenFace上的投影权重Weight-i,比较Weight-i与所有Weight的欧氏距离,选取最近的或者一定阈值范围内的即可。

你可能感兴趣的:(浅谈PCA 人脸识别)