source: proiecte/PPPP/eigenface2/pca_p.c @ 131

Last change on this file since 131 was 131, checked in by (none), 14 years ago

lala

File size: 10.0 KB
Line 
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#include "eigenface.h"
29
30//// Global variables
31IplImage ** faceImgArr        = 0; // array of face images
32CvMat    *  personNumTruthMat = 0; // array of person numbers
33int nTrainFaces               = 0; // the number of training images
34int nEigens                   = 0; // the number of eigenvalues
35IplImage * pAvgTrainImg       = 0; // the average image
36IplImage ** eigenVectArr      = 0; // eigenvectors
37CvMat * eigenValMat           = 0; // eigenvalues
38CvMat * projectedTrainFaceMat = 0; // projected training faces
39
40IplImage ** eigenPics      = 0; // eigenvectors
41char eig_name[20];
42
43//// Function prototypes
44void learn();
45void recognize();
46void doPCA();
47void storeTrainingData();
48int  loadTrainingData(CvMat ** pTrainPersonNumMat);
49int  findNearestNeighbor(float * projectedTestFace);
50int  loadFaceImgArray(char * filename);
51void convertToUImage(IplImage *fImg, IplImage *uImg);
52
53//////////////////////////////////
54// learn()
55//
56void learn(char * filename)
57{
58        int i, offset;
59
60        // load training data
61        nTrainFaces = loadFaceImgArray(filename);
62        if( nTrainFaces < 2 )
63        {
64                fprintf(stderr,
65                        "Need 2 or more training faces\n"
66                        "Input file contains only %d\n", nTrainFaces);
67                return;
68        }
69
70        // do PCA on the training faces
71        doPCA();
72
73        // project the training images onto the PCA subspace
74        projectedTrainFaceMat = cvCreateMat( nTrainFaces, nEigens, CV_32FC1 );
75        offset = projectedTrainFaceMat->step / sizeof(float);
76        for(i=0; i<nTrainFaces; i++)
77        {
78                //int offset = i * nEigens;
79                cvEigenDecomposite(
80                        faceImgArr[i],
81                        nEigens,
82                        eigenVectArr,
83                        0, 0,
84                        pAvgTrainImg,
85                        //projectedTrainFaceMat->data.fl + i*nEigens);
86                        projectedTrainFaceMat->data.fl + i*offset);
87                //~ calcDecomp(
88                        //~ faceImgArr[i],
89                        //~ nEigens,
90                        //~ eigenVectArr,
91                        //~ pAvgTrainImg,
92                        //~ //projectedTrainFaceMat->data.fl + i*nEigens);
93                        //~ projectedTrainFaceMat->data.fl + i*offset);
94        }
95       
96        // store the recognition data as an xml file
97        storeTrainingData();
98}
99
100
101//////////////////////////////////
102// recognize()
103//
104void recognize(IplImage *faceImg)
105{
106        int i, nTestFaces  = 0;         // the number of test images
107        CvMat * trainPersonNumMat = 0;  // the person numbers during training
108        float * projectedTestFace = 0;
109        int iNearest, nearest, truth;
110
111        // load test images and ground truth for person number
112        //nTestFaces = loadFaceImgArray("test.txt");
113        //printf("%d test faces loaded\n", nTestFaces);
114
115        // load the saved training data
116        if( !loadTrainingData( &trainPersonNumMat ) ) return;
117
118        // project the test images onto the PCA subspace
119        projectedTestFace = (float *)cvAlloc( nEigens*sizeof(float) );
120
121        // project the test image onto the PCA subspace
122        cvEigenDecomposite(
123                faceImg,
124                nEigens,
125                eigenVectArr,
126                0, 0,
127                pAvgTrainImg,
128                projectedTestFace);
129        //~ calcDecomp(
130                //~ faceImg,
131                //~ nEigens,
132                //~ eigenVectArr,
133                //~ pAvgTrainImg,
134                //~ projectedTestFace);
135
136        iNearest = findNearestNeighbor(projectedTestFace);
137        nearest  = trainPersonNumMat->data.i[iNearest];
138
139        printf("nearest = %d\n", nearest);
140}
141
142
143//////////////////////////////////
144// loadTrainingData()
145//
146int loadTrainingData(CvMat ** pTrainPersonNumMat)
147{
148        CvFileStorage * fileStorage;
149        int i;
150
151        // create a file-storage interface
152        fileStorage = cvOpenFileStorage( "facedata.xml", 0, CV_STORAGE_READ );
153        if( !fileStorage )
154        {
155                fprintf(stderr, "Can't open facedata.xml\n");
156                return 0;
157        }
158
159        nEigens = cvReadIntByName(fileStorage, 0, "nEigens", 0);
160        nTrainFaces = cvReadIntByName(fileStorage, 0, "nTrainFaces", 0);
161        *pTrainPersonNumMat = (CvMat *)cvReadByName(fileStorage, 0, "trainPersonNumMat", 0);
162        eigenValMat  = (CvMat *)cvReadByName(fileStorage, 0, "eigenValMat", 0);
163        projectedTrainFaceMat = (CvMat *)cvReadByName(fileStorage, 0, "projectedTrainFaceMat", 0);
164        pAvgTrainImg = (IplImage *)cvReadByName(fileStorage, 0, "avgTrainImg", 0);
165        eigenVectArr = (IplImage **)cvAlloc(nTrainFaces*sizeof(IplImage *));
166        for(i=0; i<nEigens; i++)
167        {
168                char varname[200];
169                sprintf( varname, "eigenVect_%d", i );
170                eigenVectArr[i] = (IplImage *)cvReadByName(fileStorage, 0, varname, 0);
171        }
172
173        // release the file-storage interface
174        cvReleaseFileStorage( &fileStorage );
175
176        return 1;
177}
178
179
180//////////////////////////////////
181// storeTrainingData()
182//
183void storeTrainingData()
184{
185        CvFileStorage * fileStorage;
186        int i;
187
188        // create a file-storage interface
189        fileStorage = cvOpenFileStorage( "facedata.xml", 0, CV_STORAGE_WRITE );
190
191        // store all the data
192        cvWriteInt( fileStorage, "nEigens", nEigens );
193        cvWriteInt( fileStorage, "nTrainFaces", nTrainFaces );
194        cvWrite(fileStorage, "trainPersonNumMat", personNumTruthMat, cvAttrList(0,0));
195        cvWrite(fileStorage, "eigenValMat", eigenValMat, cvAttrList(0,0));
196        cvWrite(fileStorage, "projectedTrainFaceMat", projectedTrainFaceMat, cvAttrList(0,0));
197        cvWrite(fileStorage, "avgTrainImg", pAvgTrainImg, cvAttrList(0,0));
198        for(i=0; i<nEigens; i++)
199        {
200                char varname[200];
201                sprintf( varname, "eigenVect_%d", i );
202                cvWrite(fileStorage, varname, eigenVectArr[i], cvAttrList(0,0));
203        }
204
205        // release the file-storage interface
206        cvReleaseFileStorage( &fileStorage );
207}
208
209
210//////////////////////////////////
211// findNearestNeighbor()
212//
213int findNearestNeighbor(float * projectedTestFace)
214{
215        //double leastDistSq = 1e12;
216        double leastDistSq = DBL_MAX;
217        int i, iTrain, iNearest = 0;
218
219        for(iTrain=0; iTrain<nTrainFaces; iTrain++)
220        {
221                double distSq=0;
222
223                for(i=0; i<nEigens; i++)
224                {
225                        float d_i =
226                                projectedTestFace[i] -
227                                projectedTrainFaceMat->data.fl[iTrain*nEigens + i];
228                        distSq += d_i*d_i / eigenValMat->data.fl[i];  // Mahalanobis
229                        //distSq += d_i*d_i; // Euclidean
230                }
231
232                if(distSq < leastDistSq)
233                {
234                        leastDistSq = distSq;
235                        iNearest = iTrain;
236                }
237        }
238
239        return iNearest;
240}
241
242
243//////////////////////////////////
244// doPCA()
245//
246void doPCA()
247{
248        int i;
249        CvTermCriteria calcLimit;
250        CvSize faceImgSize;
251
252        // set the number of eigenvalues to use
253        nEigens = nTrainFaces-1;
254
255        // allocate the eigenvector images
256        faceImgSize.width  = faceImgArr[0]->width;
257        faceImgSize.height = faceImgArr[0]->height;
258        eigenVectArr = (IplImage**)cvAlloc(sizeof(IplImage*) * nEigens);
259        eigenPics = (IplImage**)cvAlloc(sizeof(IplImage*) * nEigens);
260        for(i=0; i<nEigens; i++) {
261                eigenVectArr[i] = cvCreateImage(faceImgSize, IPL_DEPTH_32F, 1);
262                eigenPics[i] = cvCreateImage(faceImgSize, IPL_DEPTH_8U, 1);
263        }
264       
265        // allocate the eigenvalue array
266        eigenValMat = cvCreateMat( 1, nEigens, CV_32FC1 );
267
268        // allocate the averaged image
269        pAvgTrainImg = cvCreateImage(faceImgSize, IPL_DEPTH_32F, 1);
270
271        // set the PCA termination criterion
272        calcLimit = cvTermCriteria( CV_TERMCRIT_ITER, nEigens, 1);
273
274        // compute average image, eigenvalues, and eigenvectors
275        //~ cvCalcEigenObjects(
276                //~ nTrainFaces,
277                //~ (void*)faceImgArr,
278                //~ (void*)eigenVectArr,
279                //~ CV_EIGOBJ_NO_CALLBACK,
280                //~ 0,
281                //~ 0,
282                //~ &calcLimit,
283                //~ pAvgTrainImg,
284                //~ eigenValMat->data.fl);
285        calcEigenFaces(
286                nTrainFaces,
287                faceImgArr,
288                eigenVectArr,
289                nEigens,
290                pAvgTrainImg,
291                eigenValMat->data.fl);
292
293        cvNormalize(eigenValMat, eigenValMat, 1, 0, CV_L1, 0);
294       
295        for(i=0; i<nEigens; i++)
296        {       
297                convertToUImage(eigenVectArr[i], eigenPics[i]);
298                sprintf(eig_name,"eigen_%d.jpg", i);
299                cvSaveImage(eig_name,eigenPics[i]);
300        }
301}
302
303
304//////////////////////////////////
305// loadFaceImgArray()
306//
307int loadFaceImgArray(char * filename)
308{
309        FILE * imgListFile = 0;
310        char imgFilename[512];
311        int iFace, nFaces=0;
312
313
314        // open the input file
315        if( !(imgListFile = fopen(filename, "r")) )
316        {
317                fprintf(stderr, "Can\'t open file %s\n", filename);
318                return 0;
319        }
320
321        // count the number of faces
322        while( fgets(imgFilename, 512, imgListFile) ) ++nFaces;
323        rewind(imgListFile);
324
325        // allocate the face-image array and person number matrix
326        faceImgArr        = (IplImage **)cvAlloc( nFaces*sizeof(IplImage *) );
327        personNumTruthMat = cvCreateMat( 1, nFaces, CV_32SC1 );
328
329        // store the face images in an array
330        for(iFace=0; iFace<nFaces; iFace++)
331        {
332                // read person number and name of image file
333                fscanf(imgListFile,
334                        "%d %s", personNumTruthMat->data.i+iFace, imgFilename);
335                // load the face image
336                faceImgArr[iFace] = cvLoadImage(imgFilename, CV_LOAD_IMAGE_GRAYSCALE);
337
338                if( !faceImgArr[iFace] )
339                {
340                        fprintf(stderr, "Can\'t load image from %s\n", imgFilename);
341                        return 0;
342                }
343        }
344
345        fclose(imgListFile);
346
347        return nFaces;
348}
349
350void convertToUImage(IplImage *fImg, IplImage *uImg) {
351        int i;
352        float *bf;
353        uchar *bu;
354        CvSize size;
355       
356        cvGetImageRawData(fImg, (uchar**)&bf, NULL, &size);
357        cvGetImageRawData(uImg, (uchar**)&bu, NULL, NULL);
358       
359        // Find the Maximum and Minimum of the pixel values
360        float max, min;
361        max = min = 0.0;
362        for(i=0; i< size.width * size.height; i++) {
363                if(max < bf[i])
364                        max = bf[i];
365                if(min > bf[i])
366                        min = bf[i];
367        }
368
369        // Normalize the eigenface values between 0 and 255
370        for(i = 0; i< size.width * size.height; i++) {
371                bu[i] = (uchar)(( 255 * (( bf[i] - min)/ (max- min)) ));
372        }
373}
374
375//////////////////////////////////
376// printUsage()
377//
378void printUsage()
379{
380        printf("Usage: eigenface <command>\n",
381               "  Valid commands are\n"
382               "    train\n"
383               "    test\n");
384}
Note: See TracBrowser for help on using the repository browser.