source: proiecte/PPPP/eigenface2/eigenface.c @ 108

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

new eigenface

File size: 9.7 KB
Line 
1#include <stdio.h>
2#include <string.h>
3#include <math.h>
4#include "cv.h"
5#include "cvaux.h"
6#include "highgui.h"
7
8#define ROTATE(a,i,j,k,l) g=a[i*n + j];h=a[k*n + l];a[i*n + j]=g-s*(h+g*tau);\
9a[k*n + l]=h+s*(g-h*tau);
10
11/*
12Computes all eigenvalues and eigenvectors of a real symmetric matrix a[1..n][1..n]. On
13output, elements of a above the diagonal are destroyed. d[1..n] returns the eigenvalues of a.
14v[1..n][1..n] is a matrix whose columns contain, on output, the normalized eigenvectors of
15a. nrot returns the number of Jacobi rotations that were required.
16*/
17void jacobi(float *a, int n, float d[], float *v, int *nrot)
18{
19        int j,iq,ip,i;
20        float tresh,theta,tau,t,sm,s,h,g,c,*b,*z;
21       
22        b = (float *) malloc(n * sizeof(float));
23        z = (float *) malloc(n * sizeof(float));
24       
25        for (ip=0;ip<n;ip++) {                                                                                                                  // Initialize to the identity matrix.
26                for (iq=0;iq<n;iq++) v[ip*n + iq]=0.0;
27                        v[ip*n + ip]=1.0;
28        }
29        for (ip=0;ip<n;ip++) {                                                                                                                  // Initialize b and d to the diagonal of a.
30                b[ip]=d[ip]=a[ip*n + ip];                                                                                                               
31                z[ip]=0.0;                                                                                                                              // This vector will accumulate terms of the form t*a[pq] as in equation (11.1.14).
32        }
33       
34        *nrot=0;
35        for (i=1;i<=50;i++) {
36                sm=0.0;
37                for (ip=0;ip<n-1;ip++) {                                                                                                                // Sum off-diagonal elements.
38                        for (iq=ip+1;iq<n;iq++)
39                        sm += fabs(a[ip*n + iq]);
40                }
41                if (sm == 0.0) {                                                                                                                        // The normal return, which relies on quadratic convergence to machine underflow.
42                        free(z);
43                        free(b);
44                        return;
45                }
46                if (i < 4)
47                        tresh=0.2*sm/(n*n);                                                                                                             // ...on the first three sweeps.
48                else
49                        tresh=0.0;                                                                                                                      // ...thereafter.
50                for (ip=0;ip<n-1;ip++) {
51                        for (iq=ip+1;iq<n;iq++) {
52                                g=100.0*fabs(a[ip*n + iq]);
53                                if (i > 4 && (float)(fabs(d[ip])+g) == (float)fabs(d[ip])                                               // After four sweeps, skip the rotation if the off-diagonal element is small.
54                                        && (float)(fabs(d[iq])+g) == (float)fabs(d[iq]))
55                                        a[ip*n + iq]=0.0;
56                                else if (fabs(a[ip*n + iq]) > tresh) {
57                                        h=d[iq]-d[ip];
58                                        if ((float)(fabs(h)+g) == (float)fabs(h))
59                                                t=(a[ip*n + iq])/h;                                                                                     // t = 1/(2*theta)
60                                        else {
61                                                theta=0.5*h/(a[ip*n + iq]);                                                                     // Equation (11.1.10).
62                                                t=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
63                                                if (theta < 0.0) t = -t;
64                                        }
65                                       
66                                        c=1.0/sqrt(1+t*t);
67                                        s=t*c;
68                                        tau=s/(1.0+c);
69                                        h=t*a[ip*n + iq];
70                                        z[ip] -= h;
71                                        z[iq] += h;
72                                        d[ip] -= h;
73                                        d[iq] += h;
74                                        a[ip*n + iq]=0.0;
75                                       
76                                        for (j=0;j<=ip-1;j++) {                                                                                         // Case of rotations 1 <= j < p.
77                                                ROTATE(a,j,ip,j,iq)
78                                        }
79                                        for (j=ip+1;j<=iq-1;j++) {                                                                              // Case of rotations p < j < q.
80                                                ROTATE(a,ip,j,j,iq)
81                                        }
82                                        for (j=iq+1;j<n;j++) {                                                                                  // Case of rotations q < j <= n.
83                                                ROTATE(a,ip,j,iq,j)
84                                        }
85                                        for (j=0;j<n;j++) {
86                                                ROTATE(v,j,ip,j,iq)
87                                        }
88                                       
89                                        ++(*nrot);
90                                }
91                        }
92                }
93               
94                for (ip=0;ip<n;ip++) {
95                        b[ip] += z[ip];
96                        d[ip]=b[ip];                                                                                                                    // Updte d with the sum of t*a[pq],
97                        z[ip]=0.0;                                                                                                                      // and reinitialize z.
98                }
99        }
100       
101        printf("Too many iterations in routine jacobi\n");
102}
103
104/*
105Given the eigenvalues d[1..n] and eigenvectors v[1..n][1..n] as output from jacobi
106(x11.1) or tqli (x11.3), this routine sorts the eigenvalues into descending order, and rearranges
107the columns of v correspondingly. The method is straight insertion.
108*/
109void eigsrt(float d[], float *v, int n) 
110{
111        int k,j,i;
112        float p;
113        for (i=0;i<n-1;i++) {
114                p=d[k=i];
115                for (j=i+1;j<n;j++)
116                        if (d[j] >= p) p=d[k=j];
117                if (k != i) {
118                        d[k]=d[i];
119                        d[i]=p;
120                        for (j=0;j<n;j++) {
121                                p=v[j*n + i];
122                                v[j*n + i]=v[j*n + k];
123                                v[j*n + k]=p;
124                        }
125                }
126        }
127}
128
129void calcMeanImage(int nFaces, uchar** faceArr, int faceStep, 
130                                        CvSize size, float* avg, int avgStep) 
131{
132        int i,j,k;
133        float m = 1.0f / (float) nFaces;
134        float* bf = avg;
135       
136        for( i = 0; i < size.height; i++, bf += avgStep)
137                for( j = 0; j < size.width; j++ )
138                        bf[j] = 0.f;
139       
140        for( i = 0; i < nFaces; i++ )
141        {
142                uchar* bu = faceArr[i];
143                bf  = avg;
144                for( k = 0; k < size.height; k++, bf += avgStep, bu += faceStep )
145                        for( j = 0; j < size.width; j++ )
146                                bf[j] += bu[j];
147        }
148       
149        bf = avg;
150        for( i = 0; i < size.height; i++, bf += avgStep)
151                for( j = 0; j < size.width; j++ ) {
152                        bf[j] *= m;
153                }
154}
155
156void calcCovarMatrix(int nFaces, uchar** faceArr, int faceStep, CvSize size, 
157                                float* avg, int avgStep, float *covarMatrix) 
158{
159        int i, j;
160       
161        for( i = 0; i < nFaces; i++ )
162        {
163                uchar *bu = faceArr[i];
164
165                for( j = i; j < nFaces; j++ )
166                {
167                        int k, l;
168                        float w = 0.f;
169                        float *a = avg;
170                        uchar *bu1 = bu;
171                        uchar *bu2 = faceArr[j];
172
173                        for( k = 0; k < size.height;
174                             k++, bu1 += faceStep, bu2 += faceStep, a += avgStep )
175                        {
176                                for( l = 0; l < size.width - 3; l += 4 )
177                                {
178                                        float f = a[l];
179                                        uchar u1 = bu1[l];
180                                        uchar u2 = bu2[l];
181
182                                        w += (u1 - f) * (u2 - f);
183                                        f = a[l + 1];
184                                        u1 = bu1[l + 1];
185                                        u2 = bu2[l + 1];
186                                        w += (u1 - f) * (u2 - f);
187                                        f = a[l + 2];
188                                        u1 = bu1[l + 2];
189                                        u2 = bu2[l + 2];
190                                        w += (u1 - f) * (u2 - f);
191                                        f = a[l + 3];
192                                        u1 = bu1[l + 3];
193                                        u2 = bu2[l + 3];
194                                        w += (u1 - f) * (u2 - f);
195                                }
196                                for( ; l < size.width; l++ )
197                                {
198                                        float f = a[l];
199                                        uchar u1 = bu1[l];
200                                        uchar u2 = bu2[l];
201
202                                        w += (u1 - f) * (u2 - f);
203                                }
204                        }
205
206                        covarMatrix[i * nFaces + j] = covarMatrix[j * nFaces + i] = w;
207                }
208        }
209}
210
211void calcEigenFaces(int nFaces, IplImage** facesArr, IplImage** eigArr,  int iter,
212                                IplImage *avg,  float *eigVals) 
213{
214        int i,j,k,l, p;
215        float *covarMat, *ev;
216       
217        float *avg_data;
218        int avg_step = 0, eig_step = 0;
219        CvSize size;
220       
221        cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &size );
222       
223        avg_step = avg_step/4;
224        uchar **faces = (uchar **) cvAlloc( sizeof( uchar * ) * nFaces );
225        float **eigs = (float **) cvAlloc( sizeof( float * ) * iter );
226        int face_step = 0;
227       
228        for( i = 0; i < nFaces; i++ )
229        {
230                IplImage *face = facesArr[i];
231                uchar *face_data;
232
233                cvGetImageRawData( face, (uchar **) &face_data, &face_step, NULL);
234                faces[i] = face_data;
235        }
236       
237       
238        for( i = 0; i < iter; i++ )
239        {
240                IplImage *eig = eigArr[i];
241                float *eig_data;
242
243                cvGetImageRawData( eig, (uchar **) & eig_data, NULL, NULL);
244                eigs[i] = eig_data;
245        }
246       
247        calcMeanImage( nFaces, 
248                                faces, 
249                                face_step, 
250                                size, 
251                                avg_data, 
252                                avg_step );
253       
254        covarMat = (float *) cvAlloc( sizeof( float ) * nFaces * nFaces );
255       
256        //~ calcCovarMatrix( nFaces,
257                                //~ faces,
258                                //~ avg_step,
259                                //~ size,
260                                //~ avg_data,
261                                //~ avg_step,
262                                //~ covarMat );
263       
264        //~ for ( i = 0; i < nFaces; i++ )
265        //~ {
266                //~ for ( j = 0; j < nFaces; j++ )
267                //~ {
268                        //~ printf("%f ", covarMat[i*nFaces+j]);
269                //~ }
270                //~ printf("\n");
271        //~ }
272       
273        cvCalcCovarMatrixEx( nFaces,  facesArr, 0, 0, NULL, NULL, avg, covarMat );
274       
275        printf("\n");
276        for ( i = 0; i < nFaces; i++ ) 
277        {
278                for ( j = 0; j < nFaces; j++ ) 
279                {
280                        printf("%f ", covarMat[i*nFaces+j]);
281                }
282                printf("\n");
283        }
284        printf("\n");
285       
286        ev = (float *) cvAlloc( sizeof( float ) * nFaces * nFaces );
287       
288        int nrot=0;
289        jacobi(covarMat, nFaces, eigVals, ev, &nrot);
290        eigsrt(eigVals, ev, nFaces);
291        //JacobiEigens_32f(covarMat, ev, eigVals, nFaces, 0);
292               
293        for ( j = 0; j < nFaces; j++ ) 
294        {
295                printf("%f ", eigVals[j]);
296        }
297        printf("\n\n");
298       
299        for ( i = 0; i < nFaces; i++ ) 
300        {
301                for ( j = 0; j < nFaces; j++ ) 
302                {
303                        printf("%f ", ev[i*nFaces+j]);
304                }
305                printf("\n");
306        }
307       
308        for( i = 0; i < iter; i++ )
309                eigVals[i] = (float) (1.0 / sqrt( (double)eigVals[i] ));
310       
311        for( i = 0; i < iter; i++ ) 
312        {
313                float *be = eigs[i];
314
315                for( k = 0; k < size.height; k++, be += avg_step )
316                        for( l = 0; l < size.width; l++ )
317                                be[l] = 0.0f;
318        }
319
320        for( k = 0; k < nFaces; k++ )
321        {
322                uchar *bv = faces[k];
323               
324                for( i = 0; i < iter; i++ )
325                {
326                        float v = eigVals[i] * ev[k * nFaces + i];
327                        // float v = ev[i * nFaces + k];
328                        float *be = eigs[i];
329                        uchar *bu = bv;
330
331                        float *bf = avg_data;
332
333                        for( p = 0; p < size.height; p++, bu += face_step,
334                                bf += avg_step, be += avg_step )
335                        {
336                                for( l = 0; l < size.width - 3; l += 4 )
337                                {
338                                        float f = bf[l];
339                                        uchar u = bu[l];
340
341                                        be[l] += v * (u - f);
342                                        f = bf[l + 1];
343                                        u = bu[l + 1];
344                                        be[l + 1] += v * (u - f);
345                                        f = bf[l + 2];
346                                        u = bu[l + 2];
347                                        be[l + 2] += v * (u - f);
348                                        f = bf[l + 3];
349                                        u = bu[l + 3];
350                                        be[l + 3] += v * (u - f);
351                                }
352                                for( ; l < size.width; l++ )
353                                        be[l] += v * (bu[l] - bf[l]);
354                        }
355                } 
356        }
357       
358        for( i = 0; i < iter; i++ )
359                eigVals[i] = 1.f / (eigVals[i] * eigVals[i]);
360}
361
362void calcDecomp( IplImage* face, int nEigens, IplImage** eigArr, IplImage *avg,  float*  coeffs )
363{
364        int i, j, k;
365        float w = 0.0f;
366       
367        float *avg_data;
368        uchar *face_data;
369        int avg_step = 0, face_step = 0;
370        CvSize size;
371       
372        cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &size );
373        cvGetImageRawData( face, &face_data, &face_step, NULL);
374        avg_step = avg_step/4;
375       
376        float **eigs = (float **) cvAlloc( sizeof( float * ) * nEigens );
377        for( i = 0; i < nEigens; i++ )
378        {
379                IplImage *eig = eigArr[i];
380                float *eig_data;
381
382                cvGetImageRawData( eig, (uchar **) & eig_data, NULL, NULL );
383                eigs[i] = eig_data;
384        }
385       
386        for( k = 0; k < nEigens; k++ )
387        {
388                float *be = eigs[k];
389                uchar *bu = face_data;
390                float *bf = avg_data;
391               
392                for( i = 0; i < size.height; i++,  bu+= face_step, 
393                        be += avg_step, bf += avg_step )
394                {
395                        for( j = 0; j < size.width - 4; j += 4 )
396                        {
397                                float o = (float) bu[j];
398                                float e = be[j];
399                                float a = bf[j];
400
401                                w += e * (o - a);
402                                o = (float) bu[j + 1];
403                                e = be[j + 1];
404                                a = bf[j + 1];
405                                w += e * (o - a);
406                                o = (float) bu[j + 2];
407                                e = be[j + 2];
408                                a = bf[j + 2];
409                                w += e * (o - a);
410                                o = (float) bu[j + 3];
411                                e = be[j + 3];
412                                a = bf[j + 3];
413                                w += e * (o - a);
414                        }
415                        for( ; j < size.width; j++ )
416                                w += be[j] * ((float) bu[j] - bf[j]);
417                }
418               
419                //~ if( w < -1.0e29f )
420                        //~ return CV_NOTDEFINED_ERR;
421                coeffs[i] = w;
422        }
423}
Note: See TracBrowser for help on using the repository browser.