Rukmal

NearestTest.cpp

May 6th, 2012
900
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.00 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "cv.h"
  4. #include "cvaux.h"
  5. #include "highgui.h"
  6.  
  7.  
  8. //// Global variables
  9. IplImage ** faceImgArr        = 0; // array of face images
  10. CvMat    *  personNumTruthMat = 0; // array of person numbers
  11. int nTrainFaces               = 0; // the number of training images
  12. int nEigens                   = 0; // the number of eigenvalues
  13. IplImage * pAvgTrainImg       = 0; // the average image
  14. IplImage ** eigenVectArr      = 0; // eigenvectors
  15. CvMat * eigenValMat           = 0; // eigenvalues
  16. CvMat * projectedTrainFaceMat = 0; // projected training faces
  17.  
  18.  
  19. //// Function prototypes
  20. void learn();
  21. void recognize();
  22. void doPCA();
  23. void storeTrainingData();
  24. int  loadTrainingData(CvMat ** pTrainPersonNumMat);
  25. int  findNearestNeighbor(float * projectedTestFace);
  26. int  loadFaceImgArray(char * filename);
  27. void printUsage();
  28.  
  29.  
  30. //////////////////////////////////
  31. // main()
  32. //
  33. void main( int argc, char** argv )
  34. {
  35.     argv[1]="train";  // change to test or train
  36.     if( !strcmp(argv[1], "train") ) learn();
  37.     else if( !strcmp(argv[1], "test") ) recognize();
  38.     else{   printf("Unknown command: %s\n", argv[1]);
  39.         }
  40.     printf("Training phase is completed --> facedata.xml created. \n");
  41. }
  42.  
  43.  
  44. //////////////////////////////////
  45. // learn()
  46. //
  47. void learn()
  48. {   int i, offset;
  49.     // load training data
  50.     nTrainFaces = loadFaceImgArray("train.txt");
  51.     if( nTrainFaces < 2 )
  52.     {       fprintf(stderr,
  53.                 "Need 2 or more training faces\n"
  54.                 "Input file contains only %d\n", nTrainFaces);
  55.         return;
  56.     }
  57.     // do PCA on the training faces
  58.     doPCA();
  59.     // project the training images onto the PCA subspace
  60.     projectedTrainFaceMat = cvCreateMat( nTrainFaces, nEigens, CV_32FC1 );
  61.     offset = projectedTrainFaceMat->step / sizeof(float);
  62.     for(i=0; i<nTrainFaces; i++)    {
  63.         //int offset = i * nEigens;
  64.         cvEigenDecomposite(
  65.             faceImgArr[i],
  66.             nEigens,
  67.             eigenVectArr,
  68.             0, 0,
  69.             pAvgTrainImg,
  70.             //projectedTrainFaceMat->data.fl + i*nEigens);
  71.             projectedTrainFaceMat->data.fl + i*offset);
  72.     }
  73.  
  74.     // store the recognition data as an xml file
  75.     storeTrainingData();
  76. }
  77.  
  78.  
  79. //////////////////////////////////
  80. // recognize()
  81. //
  82. void recognize()
  83. {
  84.     int i, nTestFaces  = 0;         // the number of test images
  85.     CvMat * trainPersonNumMat = 0;  // the person numbers during training
  86.     float * projectedTestFace = 0;
  87.  
  88.     // load test images and ground truth for person number
  89.     nTestFaces = loadFaceImgArray("test.txt");
  90.     printf("%d test faces loaded\n", nTestFaces);
  91.  
  92.     // load the saved training data
  93.     if( !loadTrainingData( &trainPersonNumMat ) ) return;
  94.  
  95.     // project the test images onto the PCA subspace
  96.     projectedTestFace = (float *)cvAlloc( nEigens*sizeof(float) );
  97.     for(i=0; i<nTestFaces; i++)
  98.     {
  99.         int iNearest, nearest, truth;
  100.  
  101.         // project the test image onto the PCA subspace
  102.         cvEigenDecomposite(
  103.             faceImgArr[i],
  104.             nEigens,
  105.             eigenVectArr,
  106.             0, 0,
  107.             pAvgTrainImg,
  108.             projectedTestFace);
  109.  
  110.         iNearest = findNearestNeighbor(projectedTestFace);
  111.         truth    = personNumTruthMat->data.i[i];
  112.         nearest  = trainPersonNumMat->data.i[iNearest];
  113.  
  114.         printf("nearest = %d, Truth = %d\n", nearest, truth);
  115.     }
  116. }
  117.  
  118.  
  119. //////////////////////////////////
  120. // loadTrainingData()
  121. //
  122. int loadTrainingData(CvMat ** pTrainPersonNumMat)
  123. {
  124.     CvFileStorage * fileStorage;
  125.     int i;
  126.  
  127.     // create a file-storage interface
  128.     fileStorage = cvOpenFileStorage( "facedata.xml", 0, CV_STORAGE_READ );
  129.     if( !fileStorage )
  130.     {
  131.         fprintf(stderr, "Can't open facedata.xml\n");
  132.         return 0;
  133.     }
  134.  
  135.     nEigens = cvReadIntByName(fileStorage, 0, "nEigens", 0);
  136.     nTrainFaces = cvReadIntByName(fileStorage, 0, "nTrainFaces", 0);
  137.     *pTrainPersonNumMat = (CvMat *)cvReadByName(fileStorage, 0, "trainPersonNumMat", 0);
  138.     eigenValMat  = (CvMat *)cvReadByName(fileStorage, 0, "eigenValMat", 0);
  139.     projectedTrainFaceMat = (CvMat *)cvReadByName(fileStorage, 0, "projectedTrainFaceMat", 0);
  140.     pAvgTrainImg = (IplImage *)cvReadByName(fileStorage, 0, "avgTrainImg", 0);
  141.     eigenVectArr = (IplImage **)cvAlloc(nTrainFaces*sizeof(IplImage *));
  142.     for(i=0; i<nEigens; i++)
  143.     {
  144.         char varname[200];
  145.         sprintf( varname, "eigenVect_%d", i );
  146.         eigenVectArr[i] = (IplImage *)cvReadByName(fileStorage, 0, varname, 0);
  147.     }
  148.  
  149.     // release the file-storage interface
  150.     cvReleaseFileStorage( &fileStorage );
  151.  
  152.     return 1;
  153. }
  154.  
  155.  
  156. //////////////////////////////////
  157. // storeTrainingData()
  158. //
  159. void storeTrainingData()
  160. {
  161.     CvFileStorage * fileStorage;
  162.     int i;
  163.     // create a file-storage interface
  164.     fileStorage = cvOpenFileStorage( "facedata.xml", 0, CV_STORAGE_WRITE );
  165.  
  166.     // store all the data
  167.     cvWriteInt( fileStorage, "nEigens", nEigens );
  168.     cvWriteInt( fileStorage, "nTrainFaces", nTrainFaces );
  169.     cvWrite(fileStorage, "trainPersonNumMat", personNumTruthMat, cvAttrList(0,0));
  170.     cvWrite(fileStorage, "eigenValMat", eigenValMat, cvAttrList(0,0));
  171.     cvWrite(fileStorage, "projectedTrainFaceMat", projectedTrainFaceMat, cvAttrList(0,0));
  172.     cvWrite(fileStorage, "avgTrainImg", pAvgTrainImg, cvAttrList(0,0));
  173.     for(i=0; i<nEigens; i++)
  174.     {
  175.         char varname[200];
  176.         sprintf( varname, "eigenVect_%d", i );
  177.         cvWrite(fileStorage, varname, eigenVectArr[i], cvAttrList(0,0));
  178.     }
  179.  
  180.     // release the file-storage interface
  181.     cvReleaseFileStorage( &fileStorage );
  182. }
  183.  
  184.  
  185. //////////////////////////////////
  186. // findNearestNeighbor()
  187. //
  188. int findNearestNeighbor(float * projectedTestFace)
  189. {
  190.     //double leastDistSq = 1e12;
  191.     double leastDistSq = DBL_MAX;
  192.     int i, iTrain, iNearest = 0;
  193.  
  194.     for(iTrain=0; iTrain<nTrainFaces; iTrain++)
  195.     {
  196.         double distSq=0;
  197.  
  198.         for(i=0; i<nEigens; i++)
  199.         {
  200.             float d_i =
  201.                 projectedTestFace[i] -
  202.                 projectedTrainFaceMat->data.fl[iTrain*nEigens + i];
  203.             //distSq += d_i*d_i / eigenValMat->data.fl[i];  // Mahalanobis
  204.             distSq += d_i*d_i; // Euclidean
  205.         }
  206.  
  207.         if(distSq < leastDistSq)
  208.         {
  209.             leastDistSq = distSq;
  210.             iNearest = iTrain;
  211.         }
  212.     }
  213.  
  214.     return iNearest;
  215. }
  216.  
  217.  
  218. //////////////////////////////////
  219. // doPCA()
  220. //
  221. void doPCA()
  222. {
  223.     int i;
  224.     CvTermCriteria calcLimit;
  225.     CvSize faceImgSize;
  226.  
  227.     // set the number of eigenvalues to use
  228.     nEigens = nTrainFaces-1;
  229.  
  230.     // allocate the eigenvector images
  231.     faceImgSize.width  = faceImgArr[0]->width;
  232.     faceImgSize.height = faceImgArr[0]->height;
  233.     eigenVectArr = (IplImage**)cvAlloc(sizeof(IplImage*) * nEigens);
  234.     for(i=0; i<nEigens; i++)
  235.         eigenVectArr[i] = cvCreateImage(faceImgSize, IPL_DEPTH_32F, 1);
  236.  
  237.     // allocate the eigenvalue array
  238.     eigenValMat = cvCreateMat( 1, nEigens, CV_32FC1 );
  239.  
  240.     // allocate the averaged image
  241.     pAvgTrainImg = cvCreateImage(faceImgSize, IPL_DEPTH_32F, 1);
  242.  
  243.     // set the PCA termination criterion
  244.     calcLimit = cvTermCriteria( CV_TERMCRIT_ITER, nEigens, 1);
  245.  
  246.     // compute average image, eigenvalues, and eigenvectors
  247.     cvCalcEigenObjects(
  248.         nTrainFaces,
  249.         (void*)faceImgArr,
  250.         (void*)eigenVectArr,
  251.         CV_EIGOBJ_NO_CALLBACK,
  252.         0,
  253.         0,
  254.         &calcLimit,
  255.         pAvgTrainImg,
  256.         eigenValMat->data.fl);
  257.  
  258.     cvNormalize(eigenValMat, eigenValMat, 1, 0, CV_L1, 0);
  259. }
  260.  
  261.  
  262. //////////////////////////////////
  263. // loadFaceImgArray()
  264. //
  265. int loadFaceImgArray(char * filename)
  266. {
  267.     FILE * imgListFile = 0;
  268.     char imgFilename[512];
  269.     int iFace, nFaces=0;
  270.  
  271.  
  272.     // open the input file
  273.     if( !(imgListFile = fopen(filename, "r")) )
  274.     {
  275.         fprintf(stderr, "Can\'t open file %s\n", filename);
  276.         return 0;
  277.     }
  278.  
  279.     // count the number of faces
  280.     while( fgets(imgFilename, 512, imgListFile) ) ++nFaces;
  281.     rewind(imgListFile);
  282.  
  283.     // allocate the face-image array and person number matrix
  284.     faceImgArr        = (IplImage **)cvAlloc( nFaces*sizeof(IplImage *) );
  285.     personNumTruthMat = cvCreateMat( 1, nFaces, CV_32SC1 );
  286.  
  287.     // store the face images in an array
  288.     for(iFace=0; iFace<nFaces; iFace++)
  289.     {
  290.         // read person number and name of image file
  291.         fscanf(imgListFile,
  292.             "%d %s", personNumTruthMat->data.i+iFace, imgFilename);
  293.  
  294.         // load the face image
  295.         faceImgArr[iFace] = cvLoadImage(imgFilename, CV_LOAD_IMAGE_GRAYSCALE);
  296.  
  297.         if( !faceImgArr[iFace] )
  298.         {
  299.             fprintf(stderr, "Can\'t load image from %s\n", imgFilename);
  300.             return 0;
  301.         }
  302.     }
  303.  
  304.     fclose(imgListFile);
  305.  
  306.     return nFaces;
  307. }
Advertisement
Add Comment
Please, Sign In to add comment