应用PCA算法提取特征脸,重构人脸图像,并利用SVM算法进行人脸识别

「爱情、让人受尽委屈。」 2022-05-28 13:07 283阅读 0赞
  1. //--应用PCA进行特征提取,并重构人脸图像--//
  2. #include<highgui.h>
  3. #include<cv.h>
  4. #include<windows.h>
  5. #include<iostream>
  6. #include<stdio.h>
  7. #include<cxcore.h>
  8. #include<ml.h>
  9. using namespace cv;
  10. using namespace std;
  11. char adr[100];
  12. vector<Mat>pFrameMat;
  13. Mat pDataMat;
  14. CvMat *pData;
  15. CvMat *pAvgMat;
  16. CvMat *pEigValueMat;
  17. CvMat *pEigVectorMat;
  18. float labels[200];
  19. CvMat labelsMat;
  20. Mat ReadFaces(const vector<Mat>&pSrcImage,int pType);
  21. vector<Mat> LoadFacesSample();
  22. Mat NormImage_0_255(const Mat&pFrame);
  23. int main(int argc,char**argv)
  24. {
  25. cvNamedWindow("原始人脸图像",CV_WINDOW_AUTOSIZE);
  26. cvNamedWindow("平均脸图像",CV_WINDOW_AUTOSIZE);
  27. cvNamedWindow("主成分1人脸图像",CV_WINDOW_AUTOSIZE);
  28. cvNamedWindow("主成分2人脸图像",CV_WINDOW_AUTOSIZE);
  29. cvNamedWindow("重构人脸图像1",CV_WINDOW_AUTOSIZE);
  30. cvNamedWindow("重构人脸图像2",CV_WINDOW_AUTOSIZE);
  31. cvNamedWindow("重构人脸图像3",CV_WINDOW_AUTOSIZE);
  32. IplImage *pImage =cvLoadImage("F:\\人脸识别\\ORL人脸数据库\\s1\\1.bmp",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
  33. for(int i=0;i<200;i++)
  34. {
  35. labels[i] =(float)(i/5);
  36. }
  37. labelsMat =cvMat(200,1,CV_32FC1,labels); //所有训练人脸样本数据的分类标记,共40类,0-39
  38. pFrameMat =LoadFacesSample(); //获取所有人脸样本组成的矩阵
  39. pDataMat =ReadFaces(pFrameMat,CV_32FC1); //获取每个人脸样本转换成列向量的图像矩阵
  40. CvMat *pData =cvCreateMat(pDataMat.rows,pDataMat.cols,CV_32FC1); //转换后的所有人脸样本的矩阵
  41. CvMat *pAvgMat =cvCreateMat(1,pDataMat.cols,CV_32FC1); //所有人脸样本的平均向量
  42. CvMat *pEigValueMat =cvCreateMat(1,min(pDataMat.rows,pDataMat.cols),CV_32FC1); //人脸样本的特征值
  43. CvMat *pEigVectorMat =cvCreateMat(min(pDataMat.rows,pDataMat.cols),pDataMat.cols,CV_32FC1); //人脸样本的特征向量
  44. CvMat temp =pDataMat;
  45. cvCopy(&temp,pData); //将Mat类型的图像矩阵转换成CvMat类型
  46. cvCalcPCA( pData, pAvgMat, pEigValueMat, pEigVectorMat, CV_PCA_DATA_AS_ROW ); //计算出平均脸,特征值,特征向量
  47. CvMat *pEigResults1 =cvCreateMat(pDataMat.rows,50,CV_32FC1); //选取前50个特征向量
  48. CvMat *pEigResults2 =cvCreateMat(pDataMat.rows,100,CV_32FC1); //选取前100个特征向量
  49. CvMat *pEigResults3 =cvCreateMat(pDataMat.rows,150,CV_32FC1); //选取前150个特征向量
  50. cvProjectPCA( pData,pAvgMat,pEigVectorMat,pEigResults1);
  51. cvProjectPCA( pData,pAvgMat,pEigVectorMat,pEigResults2);
  52. cvProjectPCA( pData,pAvgMat,pEigVectorMat,pEigResults3); //计算PCA变换后的投影系数(降维的人脸样本) 系数个数=特征向量个数
  53. CvMat *pReconMat1=cvCreateMat(pDataMat.rows,pDataMat.cols,CV_32FC1);
  54. CvMat *pReconMat2=cvCreateMat(pDataMat.rows,pDataMat.cols,CV_32FC1);
  55. CvMat *pReconMat3=cvCreateMat(pDataMat.rows,pDataMat.cols,CV_32FC1);
  56. cvBackProjectPCA( pEigResults1,pAvgMat,pEigVectorMat,pReconMat1);
  57. cvBackProjectPCA( pEigResults2,pAvgMat,pEigVectorMat,pReconMat2);
  58. cvBackProjectPCA( pEigResults3,pAvgMat,pEigVectorMat,pReconMat3); //计算所有经过PCA变换后的重构人脸矩阵
  59. Mat a(pAvgMat,true);
  60. Mat pAvg =NormImage_0_255(a.row(0)).reshape(1, pFrameMat[0].rows);
  61. IplImage imgAvgTmp = pAvg;
  62. IplImage *pAvgImage = cvCloneImage(&imgAvgTmp); //将平均脸向量转换成IplImage型的图像
  63. Mat b(pEigVectorMat,true);
  64. Mat pEig1 =NormImage_0_255(b.row(0).reshape(1,pFrameMat[0].rows));
  65. Mat pEig2 =NormImage_0_255(b.row(1).reshape(1,pFrameMat[0].rows));
  66. IplImage imgEigTmp1 = pEig1;
  67. IplImage imgEigTmp2 = pEig2;
  68. IplImage *pEigImage1 = cvCloneImage(&imgEigTmp1); //将第一个主成分脸转换成IplImage型的图像
  69. IplImage *pEigImage2 = cvCloneImage(&imgEigTmp2); //将第二个主成分脸转换成IplImage型的图像
  70. Mat c(pReconMat1,true);
  71. Mat pRecon1 =NormImage_0_255(c.row(0).reshape(1,pFrameMat[0].rows));
  72. IplImage imgRecTmp1 =pRecon1;
  73. IplImage *pReconImage1 = cvCloneImage(&imgRecTmp1); //选取50个特征向量重构第一个人脸样本的图像
  74. Mat d(pReconMat2,true);
  75. Mat pRecon2 =NormImage_0_255(d.row(0).reshape(1,pFrameMat[0].rows));
  76. IplImage imgRecTmp2 =pRecon2;
  77. IplImage *pReconImage2 = cvCloneImage(&imgRecTmp2); //选取100个特征向量重构第一个人脸样本的图像
  78. Mat h(pReconMat3,true);
  79. Mat pRecon3 =NormImage_0_255(h.row(0).reshape(1,pFrameMat[0].rows));
  80. IplImage imgRecTmp3 =pRecon3;
  81. IplImage *pReconImage3 = cvCloneImage(&imgRecTmp3); //选取150个特征向量重构第一个人脸样本的图像
  82. CvSVMParams params;
  83. params.svm_type = CvSVM::C_SVC;
  84. //params.kernel_type = CvSVM::LINEAR; //线性核函数
  85. params.kernel_type = CvSVM::RBF; //径向基核函数
  86. params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6); // 迭代条件
  87. CvSVM SVM;
  88. SVM.train(pEigResults1,&labelsMat,NULL,NULL,params);
  89. Mat e(pEigResults1,true);
  90. float reponse =SVM.predict(e.row(60));
  91. cout<<"分类前样本所属类别:"<<12<<endl;
  92. cout<<"分类前样本所属类别:"<<reponse<<endl; //用支持向量机分类器对测试样本进行分类,显示分类标签号
  93. cvShowImage("原始人脸图像",pImage);
  94. cvShowImage("平均脸图像",pAvgImage);
  95. cvShowImage("主成分1人脸图像",pEigImage1);
  96. cvShowImage("主成分2人脸图像",pEigImage2);
  97. cvShowImage("重构人脸图像1",pReconImage1);
  98. cvShowImage("重构人脸图像2",pReconImage2);
  99. cvShowImage("重构人脸图像3",pReconImage3); //显示人脸图像
  100. cvWaitKey(0);
  101. cvReleaseImage(&pImage);
  102. cvReleaseImage(&pAvgImage);
  103. cvReleaseImage(&pEigImage1);
  104. cvReleaseImage(&pEigImage2);
  105. cvReleaseImage(&pReconImage1);
  106. cvReleaseImage(&pReconImage2);
  107. cvReleaseImage(&pReconImage3); //释放内存
  108. cvDestroyWindow("原始人脸图像");
  109. cvDestroyWindow("平均脸图像");
  110. cvDestroyWindow("主成分1人脸图像");
  111. cvDestroyWindow("主成分2人脸图像");
  112. cvDestroyWindow("重构人脸图像1");
  113. cvDestroyWindow("重构人脸图像2");
  114. cvDestroyWindow("重构人脸图像3"); //销毁窗口
  115. return 0;
  116. }
  117. //--将样本矩阵转换成行向量,把所有样本人脸转换成矩阵--//
  118. Mat ReadFaces(const vector<Mat>&pSrcImage,int pType)
  119. {
  120. size_t n =pSrcImage.size(); //获取样本个数
  121. if(n==0) return Mat();
  122. size_t pDim =pSrcImage[0].total(); //获取样本维数
  123. Mat pData =Mat(n,pDim,pType); //建n行pData列空矩阵
  124. for(int i=0;i<n;i++)
  125. {
  126. if(pSrcImage[i].empty())
  127. {
  128. string error_message = format("Image number %d was empty, please check your input data.", i);
  129. CV_Error(CV_StsBadArg, error_message);
  130. }
  131. // 确保数据能被reshape
  132. if(pSrcImage[i].total() != pDim)
  133. {
  134. string error_message = format("Wrong number of elements in matrix #%d! Expected %d was %d.", i, pDim, pSrcImage[i].total());
  135. CV_Error(CV_StsBadArg, error_message);
  136. }
  137. Mat pRowData =pData.row(i);
  138. if(pSrcImage[i].isContinuous())
  139. {
  140. pSrcImage[i].reshape(1,1).convertTo(pRowData,pType,1,0);
  141. }
  142. else
  143. {
  144. pSrcImage[i].clone().reshape(1,1).convertTo(pRowData,pType,1,0);
  145. }
  146. }
  147. return pData;
  148. }
  149. //--将多个样本人脸转换成向量--//
  150. vector<Mat> LoadFacesSample()
  151. {
  152. vector<Mat> pImageMat;
  153. for(int i=1;i<=40;i++)
  154. {
  155. for(int j=1;j<=5;j++)
  156. {
  157. sprintf(adr,"F:\\人脸识别\\ORL人脸数据库\\s%d\\%d.bmp",i,j);
  158. pImageMat.push_back(imread(adr,IMREAD_GRAYSCALE));
  159. }
  160. }
  161. return pImageMat;
  162. }
  163. //--将图像归一化为8位深度的图像--//
  164. Mat NormImage_0_255(const Mat&pFrame)
  165. {
  166. Mat pDst;
  167. switch(pFrame.channels())
  168. {
  169. case 1:
  170. normalize(pFrame,pDst,0,255,NORM_MINMAX,CV_8UC1);
  171. break;
  172. case 3:
  173. normalize(pFrame,pDst,0,255,NORM_MINMAX,CV_8UC3);
  174. break;
  175. default:
  176. pFrame.copyTo(pDst);
  177. break;
  178. }
  179. return pDst;
  180. }

20180406143645400

发表评论

表情:
评论列表 (有 0 条评论,283人围观)

还没有评论,来说两句吧...

相关阅读