source: proiecte/PPPP/eigenface2/eigenface_p.c @ 139

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