PCA实训报告

春季学期的实训报告,也是最后一次实训课了。

把报告发上来,算是对这一学年学习降维算法的总结。

PCA代码哪天有空再弄上来,流程图的图片也下次再弄吧


更正:报告里关于LGBP的地方数据都有误,应该是40*56*50=132160

懒得一个个改了,以后有空再改吧


1       实训内容

    本学期的实训课程的主要任务为用PCA对人脸图片进行分级降维。总体流程如图1所示,首先将待降维的人脸图像经过LGBP,每张图片获得一个13万维的向量。确定分级降维的层次后,多次调用PCA算法处理数据,最后得到降维后的低维矩阵,也就是特征提取的过程。这次的任务与前两个学期是相通的,难度和复杂程度略有增加。之前一直是在学习降维算法,这次是在应用之前学过的内容,真正实现对人脸图片的操作。

由于我之前主要负责KLDA算法,因此这学期我又重新学习了PCA算法,并且将其在C++中实现了,其中求特征值特征向量的部分原本计划调用OpenCV中的函数,但由于配置问题还没有调用成功。最后特征值和特征向量使用了网络上一段代码求得。时间原因,这学期的任务我只完成了PCA的部分,分层降维的代码还没有完善。

这一学期的课程形式依旧与前两个学期类似,每周固定时间与导师见面讨论问题,小组成员互相交流,共同完成任务。在每周与导师的见面交流中,很多问题和疑惑得到了解决,包括对算法的理解和编程上问题。导师提出代码要多写多练,在编程初期遇到些小错误,很长时间发现不了都是正常的,不要因为出错就停止编程。

1.1  软件配置

这次的PCA算法中需要对协方差矩阵求特征值和特征向量,因此导师建议我们直接调用OpenCV中现有的函数。OpenCV的全称是Open Source Computer VisionLibrary,是一个免费的跨平台的计算机视觉库,可用于开发实时的图像处理、计算机视觉以及模式识别程序[1]。配合OpenCV使用的还有Visual Studio2010,VS是一个强大的开发工具集,包括了整个软件生命周期中所需要的大部分工具,如UML工具、代码管控工具、集成开发环境(IDE)等等[2]

在配置vs和OpenCV时,研究生学长给了我们很大的帮助。在这一过程中,我了解了使用库函数最重要的一点就是路径,必须告诉编译器在哪里寻找头文件。


之前配置失败是因为执着于用以下代码调用cv.h:

1 #include <cv.h>


但这其实是OpenCV库重组成模块之前的格式。在添加好OpenCV库的头文件路径后,调用头文件的格式应该为:

1 #include .hpp>

2 #includeimgproc/imgproc.hpp>

3 #includehighgui.hpp>



经过配置路径,OpenCV函数已经可以顺利通过编译了。但在运行时,VS提示远程调试监视器的版本不附,因此最终还是不能使用OpenCV中的函数。但在这个过程中我发现了很多以前不曾注意的事情,比如头文件的路径,编译平台的选择,x64与x86处理器的关系等,收获很大。

1.2  LGBP

Gabor滤波器在图像的特征提取中有很多的应用,因为Gabor小波核非常类似于哺乳动物简单视觉皮层感受野,显示出理想的空间局部性和方向选择性,因此被成功的应用于许多人脸识别系统中[3],局域二值模式(Local Binary Patterns,LBP)算子可以提取图像边缘、角点等局部变化特征,但是只能进行单一尺度处理,对于多方面、多尺度包含的表情细节信息却无能为力[4]。而局域Gabor二值模式(Local Gabor Binary Patterns,LGBP)就是融合了Gabor滤波器与LBP算子的优点,既有LBP算子对威力图像的微小特征,如亮点、暗点、边缘等信息敏感的优点,又有Gabor滤波器对图像进行多尺度多方向提取特征的优点[5]

LGBP方法的主要步骤如下:

1.对人脸图像提取多方向多尺度的Gabor特征;

2.对提取到的Gabor特征进行LBP编码;

3.对编码后的结果提取局部直方图特征,实现特征降维;

4.将各子区域的局部直方图特征进行串联,形成人脸表情特征向量。

这一部分的代码是导师提供的,在VS中运行的结果每张图是一个132986维的向量。每张图都被分成了46张子图,每张子图又是一个56*59维的矩阵,如图2所示。

2       程序设计

2.1  构造协方差矩阵

PCA算法中有一步是需要构造协方差矩阵来求特征值和特征向量。

当待降维数小于图片数时,可以直接用差值矩阵乘以差值矩阵的转置,即构造协方差矩阵;

1    for(i=0;i


当代降维数远大于图片数时,由于数据量太大,就不适合再用来构造协方差矩阵了。应该用来构造协方差矩阵。用所得的特征向量和差值矩阵相乘,来近似特征向量


1    for(i=0;i

1    highereigenvector=new double*[dim];
2    for(i=0;i


2.2  动态内存分配

动态分配内存建立二维数组,这是一个很简单的概念。但我开始在建立时循环变量出错,导致程序莫名崩溃,困扰了我很久。最后还是导师把发现了错误,帮我改正了。

1  data=new double*[number];	  //number为图片数,dim为维数
2   	for(i=0;i


3       体会

在实现PCA代码时我发现了很多有意思的事情。在调试代码的过程中,我发现了不同算法之间的差异。C++经典的三重循环矩阵乘法与matlab的直接矩阵乘法有均值为6.0883e-004的误差,求特征值特征向量的函数与matlab的误差约为1.4072。可以看出不同的代码,不同的算法的结果和精度是不完全相同的,以后要更加注意算法的选择。

测试数据时,用13万维的数据直接调用PCA会产生很大的运算量。由于我的电脑运算速度的限制,图片数超过3张时就会崩溃,看来需要一个更加优化的算法才能解决高维计算。

这一学期的实训课程我感到非常充实,每周都有小任务。而且真正学会并理解了PCA算法,在老师的指导下还优化了自己的编程风格,学到了有关结构化编程的知识。学的知识越多,觉得好的思想越多,感觉自己欠缺的也就更多。


参 考 文 献

[1]   OpenCV[G/OL], http://zh.wikipedia.org/w/index.php?title=OpenCV&oldid=30099554.2014,2,8

[2]   Microsoft Visual Studio[G/OL], http://zh.wikipedia.org/w/index.php?title=Microsoft_Visual_Studio&oldid=31123806.2014,4,27

[3]   唱轶钲, Gabor特征判别分析人脸识别方法的误配准鲁棒性分析:计算机工程与应用, 2005, 5:56-59

[4]   于明, 基于LGBP特征和稀疏表示的人脸表情识别, 计算机工程与设计, 2013, 34(5), 1787-1791

[5]   徐红侠, 基于Gabor和局域二值模式的人脸表情识别[硕士学位论文], 南京理工大学, 计算机应用技术, 2008


你可能感兴趣的:(c++,pca,c++)