Advertisement
Guest User

c

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