PCA主成分分析法的原理与应用

来源:互联网 发布:金融网络销售 编辑:程序博客网 时间:2024/05/17 04:38

PCA简介:

主成分分析(Principal Component Analysis, 简称PCA)是一种常用的基于变量协方差矩阵对信息进行处理、压缩和抽提的有效方法。PCA方法由于其在降维和特征提取方面的有效性,在人脸识别领域得到了广泛的应用。PCA方法的基本原理是:利用K-L变换抽取人脸的主要成分,构成特征脸空间,识别时将测试图像投影到此空间,得到一个投影系数矩阵,再通过分类器进行分类识别。

PCA主要用途:

PCA主要用于数据降维,在一个图像矩阵中,有些元素特征不明显,不能用来做识别,而有些元素特征很明显,表现在方差很大(某个元素的方差可以度量其相对于整个样本的离散性),这些元素常常作为图像识别的依据。PCA的作用就是去除那些方差较小,特征不明显的维,保留方差较大,有利于识别的维。这样降低了图像矩阵的维数,减小了运算量。

PCA降维的过程:

协方差矩阵公式:

协方差(i,j)=(第i维的所有元素-第i维的均值)*(第j维的所有元素-第j维的均值)

假设:样本集有5张图片,每张图片尺寸为270*200=54000。

A(54000*5): 每一列表示一张图片的所有列的串联,共5列。

E(54000*54000): A按维度计算的协方差组成的矩阵。

V(54000*5): E的特征向量组成的矩阵,每一列表示一个特征向量,且按对应的特征值从大到小排列。E*V=a*V,a为特征值。

U(54000*4): V的前四列组成的矩阵,即保留四个主成分。

UT(4*54000): U的转置矩阵。

D(4*5): 降维后的矩阵,D(4*5)= UT(4*54000)*A(54000*5),从样本空间映射到协方差矩阵特征向量空间。

PCA降维C++代码及测试:

源代码下载路径(Qt工程):http://download.csdn.net/detail/u013752202/9225027 

#include "opencv2\opencv.hpp"#include <QApplication>#include <QDebug>using namespace cv;/*把多张同样大小的图像平铺到一张图像上*/void mergeImage(vector<Mat> src,Mat &srcAll,int cols){    Mat src0=src[0];    int line=src.size()/cols;    src.size()%cols?line++:line;    srcAll.create(src0.rows*line,src0.cols*cols,src0.type());    for(int i=0;i<src.size();i++){        Mat temp=src[i];        int x=(i%cols)*temp.cols;        int line=i/cols;        int y=line*temp.rows;        int w=temp.cols;        int h=temp.rows;        Mat ROI=srcAll(Rect(x,y,w,h));        temp.copyTo(ROI);    }}int main(int argc,char **argv){        vector<Mat> src;    //加载样本集    Mat src1=imread("huang.jpg",0);    Mat src2=imread("yang.jpg",0);    Mat src3=imread("zheng.jpg",0);    Mat src4=imread("he.jpg",0);    Mat src5=imread("fan.jpg",0);    src.push_back(src1);    src.push_back(src2);    src.push_back(src3);    src.push_back(src4);    src.push_back(src5);    //mat数组用来存放读取进来的所有图片的数据,其中mat的每一列对应1张图片,该实现在下面的for函数中    //把src[i]的所有列串联起来并保存在mat中的第i列    int total=src1.rows*src1.cols;    Mat mat(total,src.size(),CV_32FC1);    for(int i=0; i<src.size();i++){        Mat colIMG = mat.col(i);        src[i].reshape(1,total).col(0).convertTo(colIMG,CV_32FC1,1/255.0);    }    //构造pca数据结构    //pca.eigenvectors中的每一行代表输入数据协方差矩阵一个特征向量,    //且是按照该协方差矩阵的特征值从大到小进行排序的    int features = 5;//保留协方差矩阵特征向量的个数,即经过PCA后的维数    PCA pca(mat,Mat(),CV_PCA_DATA_AS_COL,features);    qDebug()<<"pca.eigenvectors.rows"<<pca.eigenvectors.rows            <<"pca.eigenvectors.cols"<<pca.eigenvectors.cols;    Mat featureFace1t;    normalize(pca.eigenvectors.row(0),featureFace1t,1.0,0.0,NORM_MINMAX);    Mat featureFace1=featureFace1t.reshape(1, src[0].rows);//第一个特征向量脸    Mat featureFace2t;    normalize(pca.eigenvectors.row(1),featureFace2t,1.0,0.0,NORM_MINMAX);    Mat featureFace2=featureFace2t.reshape(1, src[0].rows);//第二个特征向量脸    Mat featureFace3t;    normalize(pca.eigenvectors.row(2),featureFace3t,1.0,0.0,NORM_MINMAX);    Mat featureFace3=featureFace3t.reshape(1, src[0].rows);//第三个特征向量脸    Mat featureFace4t;    normalize(pca.eigenvectors.row(3),featureFace4t,1.0,0.0,NORM_MINMAX);    Mat featureFace4=featureFace4t.reshape(1, src[0].rows);//第四个特征向量脸    Mat featureFace5t;    normalize(pca.eigenvectors.row(4),featureFace5t,1.0,0.0,NORM_MINMAX);    Mat featureFace5=featureFace5t.reshape(1, src[0].rows);//第五个特征向量脸    //求降维后的矩阵    Mat pcaDst=pca.project(mat);    qDebug()<<"pcaDst.rows: "<<pcaDst.rows            <<"pcaDst.cols: "<<pcaDst.cols;    //转换并显示    Mat featureFace1s(src1.size(),src1.type());    featureFace1.convertTo(featureFace1s,src1.type(),255,0);    src.push_back(featureFace1s);    Mat featureFace2s(src1.size(),src1.type());    featureFace2.convertTo(featureFace2s,src1.type(),255,0);    src.push_back(featureFace2s);    Mat featureFace3s(src1.size(),src1.type());    featureFace3.convertTo(featureFace3s,src1.type(),255,0);    src.push_back(featureFace3s);    Mat featureFace4s(src1.size(),src1.type());    featureFace4.convertTo(featureFace4s,src1.type(),255,0);    src.push_back(featureFace4s);    Mat featureFace5s(src1.size(),src1.type());    featureFace5.convertTo(featureFace5s,src1.type(),255,0);    src.push_back(featureFace5s);    Mat srcAll;    mergeImage(src,srcAll,5);    imshow("FaceShow",srcAll);    waitKey(0);    return 0;}<strong></strong>

运行结果分析:

第一行:样本图片,共5张

第二行:协方差矩阵特征向量的前5个,按对应的特征值大小排列。

从第二行可以看出,越前面的特征是越大的特征向量特征越明显,区分度越高!




0 0
原创粉丝点击