//--应用PCA进行特征提取,并重构人脸图像--//
#include
#include
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;
char adr[100];
vectorpFrameMat;
Mat pDataMat;
CvMat *pData;
CvMat *pAvgMat;
CvMat *pEigValueMat;
CvMat *pEigVectorMat;
float labels[200];
CvMat labelsMat;
Mat ReadFaces(const vector&pSrcImage,int pType);
vector LoadFacesSample();
Mat NormImage_0_255(const Mat&pFrame);
int main(int argc,char**argv)
{
cvNamedWindow("原始人脸图像",CV_WINDOW_AUTOSIZE);
cvNamedWindow("平均脸图像",CV_WINDOW_AUTOSIZE);
cvNamedWindow("主成分1人脸图像",CV_WINDOW_AUTOSIZE);
cvNamedWindow("主成分2人脸图像",CV_WINDOW_AUTOSIZE);
cvNamedWindow("重构人脸图像1",CV_WINDOW_AUTOSIZE);
cvNamedWindow("重构人脸图像2",CV_WINDOW_AUTOSIZE);
cvNamedWindow("重构人脸图像3",CV_WINDOW_AUTOSIZE);
IplImage *pImage =cvLoadImage("F:\\人脸识别\\ORL人脸数据库\\s1\\1.bmp",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
for(int i=0;i<200;i++)
{
labels[i] =(float)(i/5);
}
labelsMat =cvMat(200,1,CV_32FC1,labels); //所有训练人脸样本数据的分类标记,共40类,0-39
pFrameMat =LoadFacesSample(); //获取所有人脸样本组成的矩阵
pDataMat =ReadFaces(pFrameMat,CV_32FC1); //获取每个人脸样本转换成列向量的图像矩阵
CvMat *pData =cvCreateMat(pDataMat.rows,pDataMat.cols,CV_32FC1); //转换后的所有人脸样本的矩阵
CvMat *pAvgMat =cvCreateMat(1,pDataMat.cols,CV_32FC1); //所有人脸样本的平均向量
CvMat *pEigValueMat =cvCreateMat(1,min(pDataMat.rows,pDataMat.cols),CV_32FC1); //人脸样本的特征值
CvMat *pEigVectorMat =cvCreateMat(min(pDataMat.rows,pDataMat.cols),pDataMat.cols,CV_32FC1); //人脸样本的特征向量
CvMat temp =pDataMat;
cvCopy(&temp,pData); //将Mat类型的图像矩阵转换成CvMat类型
cvCalcPCA( pData, pAvgMat, pEigValueMat, pEigVectorMat, CV_PCA_DATA_AS_ROW ); //计算出平均脸,特征值,特征向量
CvMat *pEigResults1 =cvCreateMat(pDataMat.rows,50,CV_32FC1); //选取前50个特征向量
CvMat *pEigResults2 =cvCreateMat(pDataMat.rows,100,CV_32FC1); //选取前100个特征向量
CvMat *pEigResults3 =cvCreateMat(pDataMat.rows,150,CV_32FC1); //选取前150个特征向量
cvProjectPCA( pData,pAvgMat,pEigVectorMat,pEigResults1);
cvProjectPCA( pData,pAvgMat,pEigVectorMat,pEigResults2);
cvProjectPCA( pData,pAvgMat,pEigVectorMat,pEigResults3); //计算PCA变换后的投影系数(降维的人脸样本) 系数个数=特征向量个数
CvMat *pReconMat1=cvCreateMat(pDataMat.rows,pDataMat.cols,CV_32FC1);
CvMat *pReconMat2=cvCreateMat(pDataMat.rows,pDataMat.cols,CV_32FC1);
CvMat *pReconMat3=cvCreateMat(pDataMat.rows,pDataMat.cols,CV_32FC1);
cvBackProjectPCA( pEigResults1,pAvgMat,pEigVectorMat,pReconMat1);
cvBackProjectPCA( pEigResults2,pAvgMat,pEigVectorMat,pReconMat2);
cvBackProjectPCA( pEigResults3,pAvgMat,pEigVectorMat,pReconMat3); //计算所有经过PCA变换后的重构人脸矩阵
Mat a(pAvgMat,true);
Mat pAvg =NormImage_0_255(a.row(0)).reshape(1, pFrameMat[0].rows);
IplImage imgAvgTmp = pAvg;
IplImage *pAvgImage = cvCloneImage(&imgAvgTmp); //将平均脸向量转换成IplImage型的图像
Mat b(pEigVectorMat,true);
Mat pEig1 =NormImage_0_255(b.row(0).reshape(1,pFrameMat[0].rows));
Mat pEig2 =NormImage_0_255(b.row(1).reshape(1,pFrameMat[0].rows));
IplImage imgEigTmp1 = pEig1;
IplImage imgEigTmp2 = pEig2;
IplImage *pEigImage1 = cvCloneImage(&imgEigTmp1); //将第一个主成分脸转换成IplImage型的图像
IplImage *pEigImage2 = cvCloneImage(&imgEigTmp2); //将第二个主成分脸转换成IplImage型的图像
Mat c(pReconMat1,true);
Mat pRecon1 =NormImage_0_255(c.row(0).reshape(1,pFrameMat[0].rows));
IplImage imgRecTmp1 =pRecon1;
IplImage *pReconImage1 = cvCloneImage(&imgRecTmp1); //选取50个特征向量重构第一个人脸样本的图像
Mat d(pReconMat2,true);
Mat pRecon2 =NormImage_0_255(d.row(0).reshape(1,pFrameMat[0].rows));
IplImage imgRecTmp2 =pRecon2;
IplImage *pReconImage2 = cvCloneImage(&imgRecTmp2); //选取100个特征向量重构第一个人脸样本的图像
Mat h(pReconMat3,true);
Mat pRecon3 =NormImage_0_255(h.row(0).reshape(1,pFrameMat[0].rows));
IplImage imgRecTmp3 =pRecon3;
IplImage *pReconImage3 = cvCloneImage(&imgRecTmp3); //选取150个特征向量重构第一个人脸样本的图像
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
//params.kernel_type = CvSVM::LINEAR; //线性核函数
params.kernel_type = CvSVM::RBF; //径向基核函数
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6); // 迭代条件
CvSVM SVM;
SVM.train(pEigResults1,&labelsMat,NULL,NULL,params);
Mat e(pEigResults1,true);
float reponse =SVM.predict(e.row(60));
cout<<"分类前样本所属类别:"<<12<&pSrcImage,int pType)
{
size_t n =pSrcImage.size(); //获取样本个数
if(n==0) return Mat();
size_t pDim =pSrcImage[0].total(); //获取样本维数
Mat pData =Mat(n,pDim,pType); //建n行pData列空矩阵
for(int i=0;i LoadFacesSample()
{
vector pImageMat;
for(int i=1;i<=40;i++)
{
for(int j=1;j<=5;j++)
{
sprintf(adr,"F:\\人脸识别\\ORL人脸数据库\\s%d\\%d.bmp",i,j);
pImageMat.push_back(imread(adr,IMREAD_GRAYSCALE));
}
}
return pImageMat;
}
//--将图像归一化为8位深度的图像--//
Mat NormImage_0_255(const Mat&pFrame)
{
Mat pDst;
switch(pFrame.channels())
{
case 1:
normalize(pFrame,pDst,0,255,NORM_MINMAX,CV_8UC1);
break;
case 3:
normalize(pFrame,pDst,0,255,NORM_MINMAX,CV_8UC3);
break;
default:
pFrame.copyTo(pDst);
break;
}
return pDst;
}