openCV学习笔记(十六) —— 人脸识别 —— 程序 —— PCA特征脸Eigenfaces、重建人脸

太过爱你忘了你带给我的痛 2021-09-27 06:24 471阅读 0赞

此程序主要来源于F:\personal\data\openCV\opencv_contrib_3.4.1\modules\face\samples\facerec_eigenfaces.cpp

流程

70

  1. 读人脸数据文件
  2. 创建特征脸识别与训练
  3. 识别人脸
  4. 输出中间平均脸、特征脸、重建结果

相关图示

70 1

70 2

程序

  1. /*
  2. 此程序主要来源于F:\personal\data\openCV\opencv_contrib_3.4.1\modules\face\samples\facerec_eigenfaces.cpp
  3. */
  4. #include <opencv2/opencv.hpp>
  5. #include <opencv2/face.hpp>
  6. //#include <fstream>
  7. //#include <iostream>
  8. using namespace std;
  9. using namespace cv;
  10. using namespace cv::face;
  11. Mat normal(Mat& src, Mat& dst)
  12. {
  13. if (src.channels() == 1)
  14. {
  15. normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
  16. }
  17. else
  18. {
  19. normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
  20. }
  21. return dst;
  22. }
  23. void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';')
  24. {
  25. std::ifstream file(filename.c_str(), ifstream::in);
  26. if (!file) {
  27. string error_message = "No valid input file was given, please check the given filename.";
  28. CV_Error(Error::StsBadArg, error_message);
  29. }
  30. string line, path, classlabel;
  31. while (getline(file, line)) {
  32. stringstream liness(line);
  33. getline(liness, path, separator);
  34. getline(liness, classlabel);
  35. if (!path.empty() && !classlabel.empty()) {
  36. images.push_back(imread(path, 0));
  37. labels.push_back(atoi(classlabel.c_str()));
  38. }
  39. }
  40. }
  41. int main()
  42. {
  43. string filename = ".\\face_recg\\face\\at.txt";
  44. vector<Mat> images;
  45. vector<int> labels;
  46. //从文件中读取图像保存到向量中
  47. try {
  48. read_csv(filename, images, labels);
  49. }
  50. catch (Exception& e)
  51. {
  52. cerr << "Error opening file \n" << filename << "\". Reason: " << e.msg << endl;
  53. exit(1);
  54. }
  55. if (images.size() <= 1)
  56. {
  57. cerr << "图像太少,请至少添加两个图片!" << endl;
  58. exit(1);
  59. }
  60. //从第一个图像获取高度,在后面的代码里面需要用到它来重塑原来的图片大小
  61. int height = images[0].rows;
  62. int width = images[0].cols;
  63. printf("height: %d, width: %d\n", height, width);
  64. //最后一个人为测试样本
  65. Mat testSample = images[images.size() - 1];
  66. int testLabel = labels[labels.size() - 1];
  67. images.pop_back();
  68. labels.pop_back();
  69. //训练
  70. Ptr<EigenFaceRecognizer> model = EigenFaceRecognizer::create();
  71. model->train(images, labels);
  72. //识别
  73. int predictedLabel = model->predict(testSample);
  74. printf("actual label: %d, predict label: %d\n", testLabel, predictedLabel);
  75. //获得特征值,特征向量,均值,平均脸
  76. Mat eigenValues = model->getEigenValues();
  77. Mat eigenVector = model->getEigenVectors();
  78. Mat mean = model->getMean();
  79. Mat meanFace = mean.reshape(1, height);
  80. Mat dst;
  81. dst = normal(meanFace, dst);
  82. imshow("MeanFace", dst);
  83. //特征脸
  84. for (int i = 0; i < min(10, eigenVector.cols); i++)
  85. {
  86. Mat ev = eigenVector.col(i).clone();
  87. Mat eigenFace = ev.reshape(1, height);
  88. Mat grayScale;
  89. grayScale = normal(eigenFace, grayScale);
  90. Mat colorFace;
  91. applyColorMap(grayScale, colorFace, COLORMAP_BONE);
  92. imshow(format("eigenFace_%d", i), colorFace);
  93. }
  94. //重建人脸
  95. for (int i = min(10, eigenVector.cols); i < min(300, eigenVector.cols); i += 15)
  96. {
  97. Mat evs = Mat(eigenVector, Range::all(), Range(0, i));
  98. Mat projection = LDA::subspaceProject(evs, mean, images[0].reshape(1, 1));
  99. Mat reconstruction = LDA::subspaceReconstruct(evs, mean, projection);
  100. Mat result = reconstruction.reshape(1, height);
  101. reconstruction = normal(result, reconstruction);
  102. imshow(format("reco_face_%d", i), reconstruction);
  103. }
  104. waitKey(0);
  105. destroyAllWindows();
  106. return 0;
  107. }

发表评论

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

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

相关阅读