学号:17020110019 姓名:高少魁
【嵌牛导读】PCA算法作为一种经典的数据降维算法,可以对数据进行有效的降维。降维具有如下一些优点:使得数据集更易使用、降低算法的计算开销、去除噪声、使得结果容易理解。本文对PCA算法原理进行一些初步的介绍,之后使用matlab工具设计算法,使用ORL人脸数据库,完成一个简单的人脸识别功能。该算法识别准确率达到了90%以上。
【嵌牛鼻子】数据降维 人脸识别 数据挖掘 主成分分析算法
【嵌牛正文】
一、PCA算法介绍
PCA(Principal Components Analysis)即主成分分析,也称主分量分析或主成分回归分析法,是一种无监督的数据降维方法,它通过降维,可以将多个指标转化为具有代表性的几个特征来进行分析。
PCA的主要步骤如下:
1、对于样本数据D=(x1,x2,x3,...,xm),设其维度为n,若使用PCA将其维度降到n’,首先对样本进行去中心化:
2、计算样本的协方差矩阵XXT。
3、对协方差矩阵计算特征值和特征向量。
4、取出最大的n’个特征值对应的特征向量,将特征向量标准化后组成特征矩阵W。
5、对于样本集的每一个样本xi,使用如下公式转化为新的样本:
6、经过上一步计算,即可得到输出的样本集。
二、利用PCA进行人脸识别的原理
要利用此算法进行人脸识别,就要先对人脸图像进行一些预处理。在获得的ORL人脸数据库中,人脸的灰度图片大小为112×92,在读取人脸之后将其转化为1×10304(92×112=10304)的行向量,这样,一张人脸就被转化为一系列的行向量,便于后续的处理。
进行数据预处理后,就可以将人脸图像集使用PCA算法进行处理,通过去中心化得到一张平均值脸,之后计算其协方差矩阵及其特征值和特征向量,再将特征值排序后进行筛选;通过去中心化得到的差分脸矩阵的转置与特征向量相乘,即可得到特征脸,笔者保留了原特征值85%的能量,并取出了对应的特征值组成了特征脸。
得到特征脸之后,就可以使用测试集进行验证了。训练集中每一张图片向量d乘以特征脸即为图片向量在特征脸空间上的投影向量pi,而测试集的图片同样做这个操作,得到投影向量p,此时可以通过计算p与上面所有的pi的欧氏距离,与p的距离最小的pi所对应的训练集人脸即是识别的人脸类别。
三、使用的人脸数据集
笔者的人脸数据集来自ORL数据库,共选取了40个人的人脸图像,每个人有10张不同表情的图片,一共有400张。根据实际应用场景,选取前7张为训练集,后3张为测试集。得到特征脸后,将测试集的人脸传入recognition函数进行识别,得到的类别与真实类别作对比,最后将结果统计,得到识别精确率。
ORL人脸数据库(样例)如下图:
ORL人脸数据库(样例)四、算法设计
笔者使用的语言为matlab。
1、数据加载
由于人脸数据库文件夹的命名非常规律,为’face1’,’face2’等,因此数据加载部分主要是使用循环语句,通过字符串拼接生成每一次要读取的图片的路径,读取图片之后通过rgb2gray函数将其转化为灰度图像(如果原图像为彩色人脸图像的话),之后使用reshape函数将原先为92×112的图像转化为1×10304的行向量,拼接到传出的数据矩阵data中,最后将读取数据结果data返回给调用它的主函数。
2、PCA训练
该部分主要是计算人脸数据的协方差矩阵、特征值、特征向量以及得到特征脸等,由于matlab在这一领域的库函数十分齐全,因此该部分算法设计较为简单。上一步得到的数据集为一个二维矩阵,每一张人脸转化为1×10304的行向量,一共有40×7=280张人脸,因此,数据集为280×10304的矩阵。数据集通过mean函数可以得到平均脸,再将每行表示的人脸减去平均脸,即可得到去中心化的人脸(实验中称为差分脸)。将差分脸乘以其转置可得到协方差矩阵,通过eig函数即可计算其特征值和特征向量。特征向量与差分脸进行计算得到特征脸,通过将特征值排序,保留了85%的能量,将特征值对应的特征脸作为输出,之后的识别步骤,即可将人脸投影到特征脸空间中去以求出两张要对比脸的欧氏距离。
3、人脸识别
程序中的recognition函数为核心的识别程序。根据前文提到的步骤,每张训练集人脸都可以通过特征脸与该人脸向量转置的乘运算得到投影,而测试集图片也经过此步骤得到其在特征脸空间的投影。不难看出,如果在训练集中含有测试集的人脸,那么测试集图片的投影一定与训练集中某个图像投影的欧氏距离很小且与其他不属于测试集类别的人脸图片投影的欧氏距离很大,通过计算欧式距离中的最小值及其索引,即可得到所识别人脸的类别代号(1~40),这样就完成了一次人脸识别。
4、主程序
为了测试此算法的准确性,光靠输出测试集图像和训练集中匹配的人脸图像,通过人工对比是远远不够的,尤其在数据库中含有双胞胎的情况下,人工也会出现错误,因此可以将人脸识别算法输出的该测试集属于的类别与传入的测试集真正属于的类别作比较,如果人脸识别成功,那么两个类别代号一定是相同的。因此,在主程序的设计上,我使用了循环语句,通过人脸类别和某张人脸的不同表情构造了双重循环,每个类别的人脸使用了后三张作为测试集,将某张人脸传入人脸识别函数,输出的类别与实际人脸类别作比较,如果相同则命中的计数加一,最终将命中数除以一共传入的图片数,得到人脸识别正确率。同时,为了使运行者能够直观且具体的看到识别的结果,在类别号为12时,输出了传入的测试图片与识别到的与其最接近的人脸图像。
五、算法运行结果
运行结果与识别精确率可见,在训练集为280张人脸图像,测试集为120张图像时,120张图像正确识别了110张,识别识别精确率达到了91.6667%,识别正确率较高。在程序效率方面,训练数据一共使用了大约5秒,整个程序运行结束使用了约14.5秒,120张测试集进行识别时共用了约9.56秒,平均识别一张人脸需要大约0.08秒,识别速度是较快的。
为了使运行者能够直观且具体的看到识别的结果,在类别号为12时,输出了三组传入的测试图片与识别到的与其最接近的人脸图像,如下图:
(a) (b) (c)通过分析以上结果可以看出,三张测试图片中有两张((a)和(c))被成功识别,输出了与其最相似人脸的类别号12,而第二张(b)识别错误,输出的类别号为40,而通过观察也很容易看出第二张人脸识别错误。
六、算法局限性
(1)数据集只有40个人,一共400张图像,而测试集也只设计了120张,数据集过于小会使识别准确率偏离实际;
(2)280张训练集在训练时间上使用了5秒,但如果训练集进一步增大会影响程序运行速度,因此需要设计更高效的算法使运行效率提高。
网友评论