createPCAModel.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #include <opencv2/opencv.hpp>
  2. #include <dirent.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. using namespace cv;
  6. using namespace std;
  7. // Read jpg files from the directory
  8. void readImages(string dirName, vector<Mat> &images)
  9. {
  10. cout << "Reading images from " << dirName;
  11. // Add slash to directory name if missing
  12. if (!dirName.empty() && dirName.back() != '/')
  13. dirName += '/';
  14. DIR *dir;
  15. struct dirent *ent;
  16. int count = 0;
  17. //image extensions
  18. string imgExt = "jpg";
  19. vector<string> files;
  20. if ((dir = opendir (dirName.c_str())) != NULL)
  21. {
  22. /* print all the files and directories within directory */
  23. while ((ent = readdir (dir)) != NULL)
  24. {
  25. if(strcmp(ent->d_name,".") == 0 || strcmp(ent->d_name,"..") == 0 )
  26. {
  27. continue;
  28. }
  29. string fname = ent->d_name;
  30. if (fname.find(imgExt, (fname.length() - imgExt.length())) != std::string::npos)
  31. {
  32. string path = dirName + fname;
  33. Mat img = imread(path);
  34. if(!img.data)
  35. {
  36. cout << "image " << path << " not read properly" << endl;
  37. }
  38. else
  39. {
  40. // Convert images to floating point type
  41. img.convertTo(img, CV_32FC3, 1/255.0);
  42. images.push_back(img);
  43. // A vertically flipped image is also a valid face image.
  44. // So lets use them as well.
  45. Mat imgFlip;
  46. flip(img, imgFlip, 1);
  47. images.push_back(imgFlip);
  48. }
  49. }
  50. }
  51. closedir (dir);
  52. }
  53. // Exit program if no images are found
  54. if(images.empty())exit(EXIT_FAILURE);
  55. cout << "... " << images.size() / 2 << " files read"<< endl;
  56. }
  57. // Create data matrix from a vector of images
  58. static Mat createDataMatrix(const vector<Mat> &images)
  59. {
  60. cout << "Creating data matrix from images ...";
  61. // Allocate space for all images in one data matrix.
  62. // The size of the data matrix is
  63. //
  64. // ( w * h * 3, numImages )
  65. //
  66. // where,
  67. //
  68. // w = width of an image in the dataset.
  69. // h = height of an image in the dataset.
  70. // 3 is for the 3 color channels.
  71. Mat data(static_cast<int>(images.size()), images[0].rows * images[0].cols * 3, CV_32F);
  72. // Turn an image into one row vector in the data matrix
  73. for(unsigned int i = 0; i < images.size(); i++)
  74. {
  75. // Extract image as one long vector of size w x h x 3
  76. Mat image = images[i].reshape(1,1);
  77. // Copy the long vector into one row of the destm
  78. image.copyTo(data.row(i));
  79. }
  80. cout << " DONE" << endl;
  81. return data;
  82. }
  83. int main(int argc, char **argv)
  84. {
  85. // Directory containing images
  86. string dirName = "images/";
  87. // Read images in the directory
  88. vector<Mat> images;
  89. readImages(dirName, images);
  90. // Size of images. All images should be the same size.
  91. Size sz = images[0].size();
  92. Mat szMat = (Mat_<double>(3,1) << sz.height, sz.width, 3);
  93. // Create data matrix for PCA.
  94. Mat data = createDataMatrix(images);
  95. // Calculate PCA of the data matrix
  96. cout << "Calculating PCA ...";
  97. cout.flush();
  98. PCA pca(data, Mat(), PCA::DATA_AS_ROW);
  99. cout << " DONE"<< endl;
  100. // Copy mean vector
  101. Mat meanVector = pca.mean;
  102. // Copy eigen vectors.
  103. Mat eigenVectors = pca.eigenvectors;
  104. // Write size, mean and eigenvectors to file
  105. string filename("pcaParams.yml");
  106. cout << "Writing size, mean and eigenVectors to " << filename << " ... ";
  107. cout.flush();
  108. FileStorage file = FileStorage(filename, FileStorage::WRITE);
  109. file << "mean" << meanVector;
  110. file << "eigenVectors" << eigenVectors;
  111. file << "size" << szMat;
  112. file.release();
  113. cout << "DONE" << endl;
  114. }