Update to 2.0.0 tree from current Fremantle build
[opencv] / src / cvaux / cveigenobjects.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "_cvaux.h"
43
44 CvStatus CV_STDCALL
45 icvJacobiEigens_32f(float *A, float *V, float *E, int n, float eps)
46 {
47     int i, j, k, ind;
48     float *AA = A, *VV = V;
49     double Amax, anorm = 0, ax;
50
51     if( A == NULL || V == NULL || E == NULL )
52         return CV_NULLPTR_ERR;
53     if( n <= 0 )
54         return CV_BADSIZE_ERR;
55     if( eps < 1.0e-7f )
56         eps = 1.0e-7f;
57
58     /*-------- Prepare --------*/
59     for( i = 0; i < n; i++, VV += n, AA += n )
60     {
61         for( j = 0; j < i; j++ )
62         {
63             double Am = AA[j];
64
65             anorm += Am * Am;
66         }
67         for( j = 0; j < n; j++ )
68             VV[j] = 0.f;
69         VV[i] = 1.f;
70     }
71
72     anorm = sqrt( anorm + anorm );
73     ax = anorm * eps / n;
74     Amax = anorm;
75
76     while( Amax > ax )
77     {
78         Amax /= n;
79         do                      /* while (ind) */
80         {
81             int p, q;
82             float *V1 = V, *A1 = A;
83
84             ind = 0;
85             for( p = 0; p < n - 1; p++, A1 += n, V1 += n )
86             {
87                 float *A2 = A + n * (p + 1), *V2 = V + n * (p + 1);
88
89                 for( q = p + 1; q < n; q++, A2 += n, V2 += n )
90                 {
91                     double x, y, c, s, c2, s2, a;
92                     float *A3, Apq = A1[q], App, Aqq, Aip, Aiq, Vpi, Vqi;
93
94                     if( fabs( Apq ) < Amax )
95                         continue;
96
97                     ind = 1;
98
99                     /*---- Calculation of rotation angle's sine & cosine ----*/
100                     App = A1[p];
101                     Aqq = A2[q];
102                     y = 5.0e-1 * (App - Aqq);
103                     x = -Apq / sqrt( (double)Apq * Apq + (double)y * y );
104                     if( y < 0.0 )
105                         x = -x;
106                     s = x / sqrt( 2.0 * (1.0 + sqrt( 1.0 - (double)x * x )));
107                     s2 = s * s;
108                     c = sqrt( 1.0 - s2 );
109                     c2 = c * c;
110                     a = 2.0 * Apq * c * s;
111
112                     /*---- Apq annulation ----*/
113                     A3 = A;
114                     for( i = 0; i < p; i++, A3 += n )
115                     {
116                         Aip = A3[p];
117                         Aiq = A3[q];
118                         Vpi = V1[i];
119                         Vqi = V2[i];
120                         A3[p] = (float) (Aip * c - Aiq * s);
121                         A3[q] = (float) (Aiq * c + Aip * s);
122                         V1[i] = (float) (Vpi * c - Vqi * s);
123                         V2[i] = (float) (Vqi * c + Vpi * s);
124                     }
125                     for( ; i < q; i++, A3 += n )
126                     {
127                         Aip = A1[i];
128                         Aiq = A3[q];
129                         Vpi = V1[i];
130                         Vqi = V2[i];
131                         A1[i] = (float) (Aip * c - Aiq * s);
132                         A3[q] = (float) (Aiq * c + Aip * s);
133                         V1[i] = (float) (Vpi * c - Vqi * s);
134                         V2[i] = (float) (Vqi * c + Vpi * s);
135                     }
136                     for( ; i < n; i++ )
137                     {
138                         Aip = A1[i];
139                         Aiq = A2[i];
140                         Vpi = V1[i];
141                         Vqi = V2[i];
142                         A1[i] = (float) (Aip * c - Aiq * s);
143                         A2[i] = (float) (Aiq * c + Aip * s);
144                         V1[i] = (float) (Vpi * c - Vqi * s);
145                         V2[i] = (float) (Vqi * c + Vpi * s);
146                     }
147                     A1[p] = (float) (App * c2 + Aqq * s2 - a);
148                     A2[q] = (float) (App * s2 + Aqq * c2 + a);
149                     A1[q] = A2[p] = 0.0f;
150                 }               /*q */
151             }                   /*p */
152         }
153         while( ind );
154         Amax /= n;
155     }                           /* while ( Amax > ax ) */
156
157     for( i = 0, k = 0; i < n; i++, k += n + 1 )
158         E[i] = A[k];
159     /*printf(" M = %d\n", M); */
160
161     /* -------- ordering -------- */
162     for( i = 0; i < n; i++ )
163     {
164         int m = i;
165         float Em = (float) fabs( E[i] );
166
167         for( j = i + 1; j < n; j++ )
168         {
169             float Ej = (float) fabs( E[j] );
170
171             m = (Em < Ej) ? j : m;
172             Em = (Em < Ej) ? Ej : Em;
173         }
174         if( m != i )
175         {
176             int l;
177             float b = E[i];
178
179             E[i] = E[m];
180             E[m] = b;
181             for( j = 0, k = i * n, l = m * n; j < n; j++, k++, l++ )
182             {
183                 b = V[k];
184                 V[k] = V[l];
185                 V[l] = b;
186             }
187         }
188     }
189
190     return CV_NO_ERR;
191 }
192
193 /*F///////////////////////////////////////////////////////////////////////////////////////
194 //    Name: icvCalcCovarMatrixEx_8u32fR
195 //    Purpose: The function calculates a covariance matrix for a group of input objects
196 //             (images, vectors, etc.). ROI supported.
197 //    Context:
198 //    Parameters:  nObjects    - number of source objects
199 //                 objects     - array of pointers to ROIs of the source objects
200 //                 imgStep     - full width of each source object row in bytes
201 //                 avg         - pointer to averaged object
202 //                 avgStep     - full width of averaged object row in bytes
203 //                 size        - ROI size of each source and averaged objects
204 //                 covarMatrix - covariance matrix (output parameter; must be allocated
205 //                               before call)
206 //
207 //    Returns: CV_NO_ERR or error code
208 //
209 //    Notes:   
210 //F*/
211 static CvStatus  CV_STDCALL
212 icvCalcCovarMatrixEx_8u32fR( int nObjects, void *input, int objStep1,
213                              int ioFlags, int ioBufSize, uchar* buffer,
214                              void *userData, float *avg, int avgStep,
215                              CvSize size, float *covarMatrix )
216 {
217     int objStep = objStep1;
218
219     /* ---- TEST OF PARAMETERS ---- */
220
221     if( nObjects < 2 )
222         return CV_BADFACTOR_ERR;
223     if( ioFlags < 0 || ioFlags > 3 )
224         return CV_BADFACTOR_ERR;
225     if( ioFlags && ioBufSize < 1024 )
226         return CV_BADFACTOR_ERR;
227     if( ioFlags && buffer == NULL )
228         return CV_NULLPTR_ERR;
229     if( input == NULL || avg == NULL || covarMatrix == NULL )
230         return CV_NULLPTR_ERR;
231     if( size.width > objStep || 4 * size.width > avgStep || size.height < 1 )
232         return CV_BADSIZE_ERR;
233
234     avgStep /= 4;
235
236     if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )    /* ==== USE INPUT CALLBACK ==== */
237     {
238         int nio, ngr, igr, n = size.width * size.height, mm = 0;
239         CvCallback read_callback = ((CvInput *) & input)->callback;
240         uchar *buffer2;
241
242         objStep = n;
243         nio = ioBufSize / n;    /* number of objects in buffer */
244         ngr = nObjects / nio;   /* number of io groups */
245         if( nObjects % nio )
246             mm = 1;
247         ngr += mm;
248
249         buffer2 = (uchar *)cvAlloc( sizeof( uchar ) * n );
250         if( buffer2 == NULL )
251             return CV_OUTOFMEM_ERR;
252
253         for( igr = 0; igr < ngr; igr++ )
254         {
255             int k, l;
256             int io, jo, imin = igr * nio, imax = imin + nio;
257             uchar *bu1 = buffer, *bu2;
258
259             if( imax > nObjects )
260                 imax = nObjects;
261
262             /* read igr group */
263             for( io = imin; io < imax; io++, bu1 += n )
264             {
265                 CvStatus r;
266
267                 r = (CvStatus)read_callback( io, (void *) bu1, userData );
268                 if( r )
269                     return r;
270             }
271
272             /* diagonal square calc */
273             bu1 = buffer;
274             for( io = imin; io < imax; io++, bu1 += n )
275             {
276                 bu2 = bu1;
277                 for( jo = io; jo < imax; jo++, bu2 += n )
278                 {
279                     float w = 0.f;
280                     float *fu = avg;
281                     int ij = 0;
282
283                     for( k = 0; k < size.height; k++, fu += avgStep )
284                         for( l = 0; l < size.width; l++, ij++ )
285                         {
286                             float f = fu[l], u1 = bu1[ij], u2 = bu2[ij];
287
288                             w += (u1 - f) * (u2 - f);
289                         }
290                     covarMatrix[io * nObjects + jo] = covarMatrix[jo * nObjects + io] = w;
291                 }
292             }
293
294             /* non-diagonal elements calc */
295             for( jo = imax; jo < nObjects; jo++ )
296             {
297                 CvStatus r;
298
299                 bu1 = buffer;
300                 bu2 = buffer2;
301
302                 /* read jo object */
303                 r = (CvStatus)read_callback( jo, (void *) bu2, userData );
304                 if( r )
305                     return r;
306
307                 for( io = imin; io < imax; io++, bu1 += n )
308                 {
309                     float w = 0.f;
310                     float *fu = avg;
311                     int ij = 0;
312
313                     for( k = 0; k < size.height; k++, fu += avgStep )
314                     {
315                         for( l = 0; l < size.width - 3; l += 4, ij += 4 )
316                         {
317                             float f = fu[l];
318                             uchar u1 = bu1[ij];
319                             uchar u2 = bu2[ij];
320
321                             w += (u1 - f) * (u2 - f);
322                             f = fu[l + 1];
323                             u1 = bu1[ij + 1];
324                             u2 = bu2[ij + 1];
325                             w += (u1 - f) * (u2 - f);
326                             f = fu[l + 2];
327                             u1 = bu1[ij + 2];
328                             u2 = bu2[ij + 2];
329                             w += (u1 - f) * (u2 - f);
330                             f = fu[l + 3];
331                             u1 = bu1[ij + 3];
332                             u2 = bu2[ij + 3];
333                             w += (u1 - f) * (u2 - f);
334                         }
335                         for( ; l < size.width; l++, ij++ )
336                         {
337                             float f = fu[l], u1 = bu1[ij], u2 = bu2[ij];
338
339                             w += (u1 - f) * (u2 - f);
340                         }
341                     }
342                     covarMatrix[io * nObjects + jo] = covarMatrix[jo * nObjects + io] = w;
343                 }
344             }
345         }                       /* igr */
346
347         cvFree( &buffer2 );
348     }                           /* if() */
349
350     else
351         /* ==== NOT USE INPUT CALLBACK ==== */
352     {
353         int i, j;
354         uchar **objects = (uchar **) (((CvInput *) & input)->data);
355
356         for( i = 0; i < nObjects; i++ )
357         {
358             uchar *bu = objects[i];
359
360             for( j = i; j < nObjects; j++ )
361             {
362                 int k, l;
363                 float w = 0.f;
364                 float *a = avg;
365                 uchar *bu1 = bu;
366                 uchar *bu2 = objects[j];
367
368                 for( k = 0; k < size.height;
369                      k++, bu1 += objStep, bu2 += objStep, a += avgStep )
370                 {
371                     for( l = 0; l < size.width - 3; l += 4 )
372                     {
373                         float f = a[l];
374                         uchar u1 = bu1[l];
375                         uchar u2 = bu2[l];
376
377                         w += (u1 - f) * (u2 - f);
378                         f = a[l + 1];
379                         u1 = bu1[l + 1];
380                         u2 = bu2[l + 1];
381                         w += (u1 - f) * (u2 - f);
382                         f = a[l + 2];
383                         u1 = bu1[l + 2];
384                         u2 = bu2[l + 2];
385                         w += (u1 - f) * (u2 - f);
386                         f = a[l + 3];
387                         u1 = bu1[l + 3];
388                         u2 = bu2[l + 3];
389                         w += (u1 - f) * (u2 - f);
390                     }
391                     for( ; l < size.width; l++ )
392                     {
393                         float f = a[l];
394                         uchar u1 = bu1[l];
395                         uchar u2 = bu2[l];
396
397                         w += (u1 - f) * (u2 - f);
398                     }
399                 }
400
401                 covarMatrix[i * nObjects + j] = covarMatrix[j * nObjects + i] = w;
402             }
403         }
404     }                           /* else */
405
406     return CV_NO_ERR;
407 }
408
409 /*======================== end of icvCalcCovarMatrixEx_8u32fR ===========================*/
410
411
412 static int
413 icvDefaultBufferSize( void )
414 {
415     return 10 * 1024 * 1024;
416 }
417
418 /*F///////////////////////////////////////////////////////////////////////////////////////
419 //    Name: icvCalcEigenObjects_8u32fR
420 //    Purpose: The function calculates an orthonormal eigen basis and a mean (averaged)
421 //             object for a group of input objects (images, vectors, etc.). ROI supported.
422 //    Context:
423 //    Parameters: nObjects  - number of source objects
424 //                input     - pointer either to array of pointers to input objects
425 //                            or to read callback function (depending on ioFlags)
426 //                imgStep   - full width of each source object row in bytes
427 //                output    - pointer either to array of pointers to output eigen objects
428 //                            or to write callback function (depending on ioFlags)
429 //                eigStep   - full width of each eigenobject row in bytes
430 //                size      - ROI size of each source object
431 //                ioFlags   - input/output flags (see Notes)
432 //                ioBufSize - input/output buffer size
433 //                userData  - pointer to the structure which contains all necessary
434 //                            data for the callback functions
435 //                calcLimit - determines the calculation finish conditions
436 //                avg       - pointer to averaged object (has the same size as ROI)
437 //                avgStep   - full width of averaged object row in bytes
438 //                eigVals   - pointer to corresponding eigenvalues (array of <nObjects>
439 //                            elements in descending order)
440 //
441 //    Returns: CV_NO_ERR or error code
442 //
443 //    Notes: 1. input/output data (that is, input objects and eigen ones) may either
444 //              be allocated in the RAM or be read from/written to the HDD (or any
445 //              other device) by read/write callback functions. It depends on the
446 //              value of ioFlags paramater, which may be the following:
447 //                  CV_EIGOBJ_NO_CALLBACK, or 0;
448 //                  CV_EIGOBJ_INPUT_CALLBACK;
449 //                  CV_EIGOBJ_OUTPUT_CALLBACK;
450 //                  CV_EIGOBJ_BOTH_CALLBACK, or
451 //                            CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK.
452 //              The callback functions as well as the user data structure must be
453 //              developed by the user.
454 //
455 //           2. If ioBufSize = 0, or it's too large, the function dermines buffer size
456 //              itself.
457 //
458 //           3. Depending on calcLimit parameter, calculations are finished either if
459 //              eigenfaces number comes up to certain value or the relation of the
460 //              current eigenvalue and the largest one comes down to certain value
461 //              (or any of the above conditions takes place). The calcLimit->type value
462 //              must be CV_TERMCRIT_NUMB, CV_TERMCRIT_EPS or
463 //              CV_TERMCRIT_NUMB | CV_TERMCRIT_EPS. The function returns the real
464 //              values calcLimit->max_iter and calcLimit->epsilon.
465 //
466 //           4. eigVals may be equal to NULL (if you don't need eigen values in further).
467 //
468 //F*/
469 static CvStatus CV_STDCALL
470 icvCalcEigenObjects_8u32fR( int nObjects, void* input, int objStep,
471                             void* output, int eigStep, CvSize size,
472                             int  ioFlags, int ioBufSize, void* userData,
473                             CvTermCriteria* calcLimit, float* avg,
474                             int    avgStep, float  *eigVals )
475 {
476     int i, j, n, iev = 0, m1 = nObjects - 1, objStep1 = objStep, eigStep1 = eigStep / 4;
477     CvSize objSize, eigSize, avgSize;
478     float *c = 0;
479     float *ev = 0;
480     float *bf = 0;
481     uchar *buf = 0;
482     void *buffer = 0;
483     float m = 1.0f / (float) nObjects;
484     CvStatus r;
485
486     if( m1 > calcLimit->max_iter && calcLimit->type != CV_TERMCRIT_EPS )
487         m1 = calcLimit->max_iter;
488
489     /* ---- TEST OF PARAMETERS ---- */
490
491     if( nObjects < 2 )
492         return CV_BADFACTOR_ERR;
493     if( ioFlags < 0 || ioFlags > 3 )
494         return CV_BADFACTOR_ERR;
495     if( input == NULL || output == NULL || avg == NULL )
496         return CV_NULLPTR_ERR;
497     if( size.width > objStep || 4 * size.width > eigStep ||
498         4 * size.width > avgStep || size.height < 1 )
499         return CV_BADSIZE_ERR;
500     if( !(ioFlags & CV_EIGOBJ_INPUT_CALLBACK) )
501         for( i = 0; i < nObjects; i++ )
502             if( ((uchar **) input)[i] == NULL )
503                 return CV_NULLPTR_ERR;
504     if( !(ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK) )
505         for( i = 0; i < m1; i++ )
506             if( ((float **) output)[i] == NULL )
507                 return CV_NULLPTR_ERR;
508
509     avgStep /= 4;
510     eigStep /= 4;
511
512     if( objStep == size.width && eigStep == size.width && avgStep == size.width )
513     {
514         size.width *= size.height;
515         size.height = 1;
516         objStep = objStep1 = eigStep = eigStep1 = avgStep = size.width;
517     }
518     objSize = eigSize = avgSize = size;
519
520     if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
521     {
522         objSize.width *= objSize.height;
523         objSize.height = 1;
524         objStep = objSize.width;
525         objStep1 = size.width;
526     }
527
528     if( ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK )
529     {
530         eigSize.width *= eigSize.height;
531         eigSize.height = 1;
532         eigStep = eigSize.width;
533         eigStep1 = size.width;
534     }
535
536     n = objSize.height * objSize.width * (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) +
537         2 * eigSize.height * eigSize.width * (ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK);
538
539     /* Buffer size determination */
540     if( ioFlags )
541     {
542         int size = icvDefaultBufferSize();
543         ioBufSize = MIN( size, n );
544     }
545
546     /* memory allocation (if necesseay) */
547
548     if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
549     {
550         buf = (uchar *) cvAlloc( sizeof( uchar ) * objSize.width );
551         if( buf == NULL )
552             return CV_OUTOFMEM_ERR;
553     }
554
555     if( ioFlags )
556     {
557         buffer = (void *) cvAlloc( ioBufSize );
558         if( buffer == NULL )
559         {
560             if( buf )
561                 cvFree( &buf );
562             return CV_OUTOFMEM_ERR;
563         }
564     }
565
566     /* Calculation of averaged object */
567     bf = avg;
568     for( i = 0; i < avgSize.height; i++, bf += avgStep )
569         for( j = 0; j < avgSize.width; j++ )
570             bf[j] = 0.f;
571
572     for( i = 0; i < nObjects; i++ )
573     {
574         int k, l;
575         uchar *bu = (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) ? buf : ((uchar **) input)[i];
576
577         if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
578         {
579             CvCallback read_callback = ((CvInput *) & input)->callback;
580
581             r = (CvStatus)read_callback( i, (void *) buf, userData );
582             if( r )
583             {
584                 if( buffer )
585                     cvFree( &buffer );
586                 if( buf )
587                     cvFree( &buf );
588                 return r;
589             }
590         }
591
592         bf = avg;
593         for( k = 0; k < avgSize.height; k++, bf += avgStep, bu += objStep1 )
594             for( l = 0; l < avgSize.width; l++ )
595                 bf[l] += bu[l];
596     }
597
598     bf = avg;
599     for( i = 0; i < avgSize.height; i++, bf += avgStep )
600         for( j = 0; j < avgSize.width; j++ )
601             bf[j] *= m;
602
603     /* Calculation of covariance matrix */
604     c = (float *) cvAlloc( sizeof( float ) * nObjects * nObjects );
605
606     if( c == NULL )
607     {
608         if( buffer )
609             cvFree( &buffer );
610         if( buf )
611             cvFree( &buf );
612         return CV_OUTOFMEM_ERR;
613     }
614
615     r = icvCalcCovarMatrixEx_8u32fR( nObjects, input, objStep1, ioFlags, ioBufSize,
616                                       (uchar *) buffer, userData, avg, 4 * avgStep, size, c );
617     if( r )
618     {
619         cvFree( &c );
620         if( buffer )
621             cvFree( &buffer );
622         if( buf )
623             cvFree( &buf );
624         return r;
625     }
626
627     /* Calculation of eigenvalues & eigenvectors */
628     ev = (float *) cvAlloc( sizeof( float ) * nObjects * nObjects );
629
630     if( ev == NULL )
631     {
632         cvFree( &c );
633         if( buffer )
634             cvFree( &buffer );
635         if( buf )
636             cvFree( &buf );
637         return CV_OUTOFMEM_ERR;
638     }
639
640     if( eigVals == NULL )
641     {
642         eigVals = (float *) cvAlloc( sizeof( float ) * nObjects );
643
644         if( eigVals == NULL )
645         {
646             cvFree( &c );
647             cvFree( &ev );
648             if( buffer )
649                 cvFree( &buffer );
650             if( buf )
651                 cvFree( &buf );
652             return CV_OUTOFMEM_ERR;
653         }
654         iev = 1;
655     }
656
657     r = icvJacobiEigens_32f( c, ev, eigVals, nObjects, 0.0f );
658     cvFree( &c );
659     if( r )
660     {
661         cvFree( &ev );
662         if( buffer )
663             cvFree( &buffer );
664         if( buf )
665             cvFree( &buf );
666         if( iev )
667             cvFree( &eigVals );
668         return r;
669     }
670
671     /* Eigen objects number determination */
672     if( calcLimit->type != CV_TERMCRIT_NUMBER )
673     {
674         for( i = 0; i < m1; i++ )
675             if( fabs( eigVals[i] / eigVals[0] ) < calcLimit->epsilon )
676                 break;
677         m1 = calcLimit->max_iter = i;
678     }
679     else
680         m1 = calcLimit->max_iter;
681     calcLimit->epsilon = (float) fabs( eigVals[m1 - 1] / eigVals[0] );
682
683     for( i = 0; i < m1; i++ )
684         eigVals[i] = (float) (1.0 / sqrt( (double)eigVals[i] ));
685
686     /* ----------------- Calculation of eigenobjects ----------------------- */
687     if( ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK )
688     {
689         int nio, ngr, igr;
690
691         nio = ioBufSize / (4 * eigSize.width);  /* number of eigen objects in buffer */
692         ngr = m1 / nio;         /* number of io groups */
693         if( nObjects % nio )
694             ngr += 1;
695
696         for( igr = 0; igr < ngr; igr++ )
697         {
698             int i, io, ie, imin = igr * nio, imax = imin + nio;
699
700             if( imax > m1 )
701                 imax = m1;
702
703             for( i = 0; i < eigSize.width * (imax - imin); i++ )
704                 ((float *) buffer)[i] = 0.f;
705
706             for( io = 0; io < nObjects; io++ )
707             {
708                 uchar *bu = ioFlags & CV_EIGOBJ_INPUT_CALLBACK ? buf : ((uchar **) input)[io];
709
710                 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
711                 {
712                     CvCallback read_callback = ((CvInput *) & input)->callback;
713
714                     r = (CvStatus)read_callback( io, (void *) buf, userData );
715                     if( r )
716                     {
717                         cvFree( &ev );
718                         if( iev )
719                             cvFree( &eigVals );
720                         if( buffer )
721                             cvFree( &buffer );
722                         if( buf )
723                             cvFree( &buf );
724                         return r;
725                     }
726                 }
727
728                 for( ie = imin; ie < imax; ie++ )
729                 {
730                     int k, l;
731                     uchar *bv = bu;
732                     float e = ev[ie * nObjects + io] * eigVals[ie];
733                     float *be = ((float *) buffer) + ((ie - imin) * eigStep);
734
735                     bf = avg;
736                     for( k = 0; k < size.height; k++, bv += objStep1,
737                          bf += avgStep, be += eigStep1 )
738                     {
739                         for( l = 0; l < size.width - 3; l += 4 )
740                         {
741                             float f = bf[l];
742                             uchar v = bv[l];
743
744                             be[l] += e * (v - f);
745                             f = bf[l + 1];
746                             v = bv[l + 1];
747                             be[l + 1] += e * (v - f);
748                             f = bf[l + 2];
749                             v = bv[l + 2];
750                             be[l + 2] += e * (v - f);
751                             f = bf[l + 3];
752                             v = bv[l + 3];
753                             be[l + 3] += e * (v - f);
754                         }
755                         for( ; l < size.width; l++ )
756                             be[l] += e * (bv[l] - bf[l]);
757                     }
758                 }
759             }                   /* io */
760
761             for( ie = imin; ie < imax; ie++ )   /* calculated eigen objects writting */
762             {
763                 CvCallback write_callback = ((CvInput *) & output)->callback;
764                 float *be = ((float *) buffer) + ((ie - imin) * eigStep);
765
766                 r = (CvStatus)write_callback( ie, (void *) be, userData );
767                 if( r )
768                 {
769                     cvFree( &ev );
770                     if( iev )
771                         cvFree( &eigVals );
772                     if( buffer )
773                         cvFree( &buffer );
774                     if( buf )
775                         cvFree( &buf );
776                     return r;
777                 }
778             }
779         }                       /* igr */
780     }
781
782     else
783     {
784         int k, p, l;
785
786         for( i = 0; i < m1; i++ )       /* e.o. annulation */
787         {
788             float *be = ((float **) output)[i];
789
790             for( p = 0; p < eigSize.height; p++, be += eigStep )
791                 for( l = 0; l < eigSize.width; l++ )
792                     be[l] = 0.0f;
793         }
794
795         for( k = 0; k < nObjects; k++ )
796         {
797             uchar *bv = (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) ? buf : ((uchar **) input)[k];
798
799             if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
800             {
801                 CvCallback read_callback = ((CvInput *) & input)->callback;
802
803                 r = (CvStatus)read_callback( k, (void *) buf, userData );
804                 if( r )
805                 {
806                     cvFree( &ev );
807                     if( iev )
808                         cvFree( &eigVals );
809                     if( buffer )
810                         cvFree( &buffer );
811                     if( buf )
812                         cvFree( &buf );
813                     return r;
814                 }
815             }
816
817             for( i = 0; i < m1; i++ )
818             {
819                 float v = eigVals[i] * ev[i * nObjects + k];
820                 float *be = ((float **) output)[i];
821                 uchar *bu = bv;
822
823                 bf = avg;
824
825                 for( p = 0; p < size.height; p++, bu += objStep1,
826                      bf += avgStep, be += eigStep1 )
827                 {
828                     for( l = 0; l < size.width - 3; l += 4 )
829                     {
830                         float f = bf[l];
831                         uchar u = bu[l];
832
833                         be[l] += v * (u - f);
834                         f = bf[l + 1];
835                         u = bu[l + 1];
836                         be[l + 1] += v * (u - f);
837                         f = bf[l + 2];
838                         u = bu[l + 2];
839                         be[l + 2] += v * (u - f);
840                         f = bf[l + 3];
841                         u = bu[l + 3];
842                         be[l + 3] += v * (u - f);
843                     }
844                     for( ; l < size.width; l++ )
845                         be[l] += v * (bu[l] - bf[l]);
846                 }
847             }                   /* i */
848         }                       /* k */
849     }                           /* else */
850
851     cvFree( &ev );
852     if( iev )
853         cvFree( &eigVals );
854     else
855         for( i = 0; i < m1; i++ )
856             eigVals[i] = 1.f / (eigVals[i] * eigVals[i]);
857     if( buffer )
858         cvFree( &buffer );
859     if( buf )
860         cvFree( &buf );
861     return CV_NO_ERR;
862 }
863
864 /* --- End of icvCalcEigenObjects_8u32fR --- */
865
866 /*F///////////////////////////////////////////////////////////////////////////////////////
867 //    Name: icvCalcDecompCoeff_8u32fR
868 //    Purpose: The function calculates one decomposition coefficient of input object
869 //             using previously calculated eigen object and the mean (averaged) object
870 //    Context:
871 //    Parameters:  obj     - input object
872 //                 objStep - its step (in bytes)
873 //                 eigObj  - pointer to eigen object
874 //                 eigStep - its step (in bytes)
875 //                 avg     - pointer to averaged object
876 //                 avgStep - its step (in bytes)
877 //                 size    - ROI size of each source object
878 //
879 //    Returns: decomposition coefficient value or large negative value (if error)
880 //
881 //    Notes:
882 //F*/
883 static float CV_STDCALL
884 icvCalcDecompCoeff_8u32fR( uchar* obj, int objStep,
885                            float *eigObj, int eigStep,
886                            float *avg, int avgStep, CvSize size )
887 {
888     int i, k;
889     float w = 0.0f;
890
891     if( size.width > objStep || 4 * size.width > eigStep
892         || 4 * size.width > avgStep || size.height < 1 )
893         return -1.0e30f;
894     if( obj == NULL || eigObj == NULL || avg == NULL )
895         return -1.0e30f;
896
897     eigStep /= 4;
898     avgStep /= 4;
899
900     if( size.width == objStep && size.width == eigStep && size.width == avgStep )
901     {
902         size.width *= size.height;
903         size.height = 1;
904         objStep = eigStep = avgStep = size.width;
905     }
906
907     for( i = 0; i < size.height; i++, obj += objStep, eigObj += eigStep, avg += avgStep )
908     {
909         for( k = 0; k < size.width - 4; k += 4 )
910         {
911             float o = (float) obj[k];
912             float e = eigObj[k];
913             float a = avg[k];
914
915             w += e * (o - a);
916             o = (float) obj[k + 1];
917             e = eigObj[k + 1];
918             a = avg[k + 1];
919             w += e * (o - a);
920             o = (float) obj[k + 2];
921             e = eigObj[k + 2];
922             a = avg[k + 2];
923             w += e * (o - a);
924             o = (float) obj[k + 3];
925             e = eigObj[k + 3];
926             a = avg[k + 3];
927             w += e * (o - a);
928         }
929         for( ; k < size.width; k++ )
930             w += eigObj[k] * ((float) obj[k] - avg[k]);
931     }
932
933     return w;
934 }
935
936 /*F///////////////////////////////////////////////////////////////////////////////////////
937 //    Names: icvEigenDecomposite_8u32fR
938 //    Purpose: The function calculates all decomposition coefficients for input object
939 //             using previously calculated eigen objects basis and the mean (averaged)
940 //             object
941 //    Context:
942 //    Parameters:  obj         - input object
943 //                 objStep     - its step (in bytes)
944 //                 nEigObjs    - number of eigen objects
945 //                 eigInput    - pointer either to array of pointers to eigen objects
946 //                               or to read callback function (depending on ioFlags)
947 //                 eigStep     - eigen objects step (in bytes)
948 //                 ioFlags     - input/output flags
949 //                 iserData    - pointer to the structure which contains all necessary
950 //                               data for the callback function
951 //                 avg         - pointer to averaged object
952 //                 avgStep     - its step (in bytes)
953 //                 size        - ROI size of each source object
954 //                 coeffs      - calculated coefficients (output data)
955 //
956 //    Returns: icv status
957 //
958 //    Notes:   see notes for icvCalcEigenObjects_8u32fR function
959 //F*/
960 static CvStatus CV_STDCALL
961 icvEigenDecomposite_8u32fR( uchar * obj, int objStep, int nEigObjs,
962                             void *eigInput, int eigStep, int ioFlags,
963                             void *userData, float *avg, int avgStep,
964                             CvSize size, float *coeffs )
965 {
966     int i;
967
968     if( nEigObjs < 2 )
969         return CV_BADFACTOR_ERR;
970     if( ioFlags < 0 || ioFlags > 1 )
971         return CV_BADFACTOR_ERR;
972     if( size.width > objStep || 4 * size.width > eigStep ||
973         4 * size.width > avgStep || size.height < 1 )
974         return CV_BADSIZE_ERR;
975     if( obj == NULL || eigInput == NULL || coeffs == NULL || avg == NULL )
976         return CV_NULLPTR_ERR;
977     if( !ioFlags )
978         for( i = 0; i < nEigObjs; i++ )
979             if( ((uchar **) eigInput)[i] == NULL )
980                 return CV_NULLPTR_ERR;
981
982     if( ioFlags )               /* callback */
983
984     {
985         float *buffer;
986         CvCallback read_callback = ((CvInput *) & eigInput)->callback;
987
988         eigStep = 4 * size.width;
989
990         /* memory allocation */
991         buffer = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
992
993         if( buffer == NULL )
994             return CV_OUTOFMEM_ERR;
995
996         for( i = 0; i < nEigObjs; i++ )
997         {
998             float w;
999             CvStatus r = (CvStatus)read_callback( i, (void *) buffer, userData );
1000
1001             if( r )
1002             {
1003                 cvFree( &buffer );
1004                 return r;
1005             }
1006             w = icvCalcDecompCoeff_8u32fR( obj, objStep, buffer,
1007                                             eigStep, avg, avgStep, size );
1008             if( w < -1.0e29f )
1009             {
1010                 cvFree( &buffer );
1011                 return CV_NOTDEFINED_ERR;
1012             }
1013             coeffs[i] = w;
1014         }
1015         cvFree( &buffer );
1016     }
1017
1018     else
1019         /* no callback */
1020         for( i = 0; i < nEigObjs; i++ )
1021         {
1022             float w = icvCalcDecompCoeff_8u32fR( obj, objStep, ((float **) eigInput)[i],
1023                                                   eigStep, avg, avgStep, size );
1024
1025             if( w < -1.0e29f )
1026                 return CV_NOTDEFINED_ERR;
1027             coeffs[i] = w;
1028         }
1029
1030     return CV_NO_ERR;
1031 }
1032
1033
1034 /*F///////////////////////////////////////////////////////////////////////////////////////
1035 //    Names: icvEigenProjection_8u32fR
1036 //    Purpose: The function calculates object projection to the eigen sub-space (restores
1037 //             an object) using previously calculated eigen objects basis, mean (averaged)
1038 //             object and decomposition coefficients of the restored object
1039 //    Context:
1040 //    Parameters:  nEigObjs - Number of eigen objects
1041 //                 eigens   - Array of pointers to eigen objects
1042 //                 eigStep  - Eigen objects step (in bytes)
1043 //                 coeffs   - Previously calculated decomposition coefficients
1044 //                 avg      - Pointer to averaged object
1045 //                 avgStep  - Its step (in bytes)
1046 //                 rest     - Pointer to restored object
1047 //                 restStep - Its step (in bytes)
1048 //                 size     - ROI size of each object
1049 //
1050 //    Returns: CV status
1051 //
1052 //    Notes:
1053 //F*/
1054 static CvStatus CV_STDCALL
1055 icvEigenProjection_8u32fR( int nEigObjs, void *eigInput, int eigStep,
1056                            int ioFlags, void *userData, float *coeffs,
1057                            float *avg, int avgStep, uchar * rest,
1058                            int restStep, CvSize size )
1059 {
1060     int i, j, k;
1061     float *buf;
1062     float *buffer = NULL;
1063     float *b;
1064     CvCallback read_callback = ((CvInput *) & eigInput)->callback;
1065
1066     if( size.width > avgStep || 4 * size.width > eigStep || size.height < 1 )
1067         return CV_BADSIZE_ERR;
1068     if( rest == NULL || eigInput == NULL || avg == NULL || coeffs == NULL )
1069         return CV_NULLPTR_ERR;
1070     if( ioFlags < 0 || ioFlags > 1 )
1071         return CV_BADFACTOR_ERR;
1072     if( !ioFlags )
1073         for( i = 0; i < nEigObjs; i++ )
1074             if( ((uchar **) eigInput)[i] == NULL )
1075                 return CV_NULLPTR_ERR;
1076     eigStep /= 4;
1077     avgStep /= 4;
1078
1079     if( size.width == restStep && size.width == eigStep && size.width == avgStep )
1080     {
1081         size.width *= size.height;
1082         size.height = 1;
1083         restStep = eigStep = avgStep = size.width;
1084     }
1085
1086     buf = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
1087
1088     if( buf == NULL )
1089         return CV_OUTOFMEM_ERR;
1090     b = buf;
1091     for( i = 0; i < size.height; i++, avg += avgStep, b += size.width )
1092         for( j = 0; j < size.width; j++ )
1093             b[j] = avg[j];
1094
1095     if( ioFlags )
1096     {
1097         buffer = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
1098
1099         if( buffer == NULL )
1100         {
1101             cvFree( &buf );
1102             return CV_OUTOFMEM_ERR;
1103         }
1104         eigStep = size.width;
1105     }
1106
1107     for( k = 0; k < nEigObjs; k++ )
1108     {
1109         float *e = ioFlags ? buffer : ((float **) eigInput)[k];
1110         float c = coeffs[k];
1111
1112         if( ioFlags )           /* read eigen object */
1113         {
1114             CvStatus r = (CvStatus)read_callback( k, (void *) buffer, userData );
1115
1116             if( r )
1117             {
1118                 cvFree( &buf );
1119                 cvFree( &buffer );
1120                 return r;
1121             }
1122         }
1123
1124         b = buf;
1125         for( i = 0; i < size.height; i++, e += eigStep, b += size.width )
1126         {
1127             for( j = 0; j < size.width - 3; j += 4 )
1128             {
1129                 float b0 = c * e[j];
1130                 float b1 = c * e[j + 1];
1131                 float b2 = c * e[j + 2];
1132                 float b3 = c * e[j + 3];
1133
1134                 b[j] += b0;
1135                 b[j + 1] += b1;
1136                 b[j + 2] += b2;
1137                 b[j + 3] += b3;
1138             }
1139             for( ; j < size.width; j++ )
1140                 b[j] += c * e[j];
1141         }
1142     }
1143
1144     b = buf;
1145     for( i = 0; i < size.height; i++, avg += avgStep, b += size.width, rest += restStep )
1146         for( j = 0; j < size.width; j++ )
1147         {
1148             int w = cvRound( b[j] );
1149
1150             w = !(w & ~255) ? w : w < 0 ? 0 : 255;
1151             rest[j] = (uchar) w;
1152         }
1153
1154     cvFree( &buf );
1155     if( ioFlags )
1156         cvFree( &buffer );
1157     return CV_NO_ERR;
1158 }
1159
1160 /*F///////////////////////////////////////////////////////////////////////////////////////
1161 //    Name: cvCalcCovarMatrixEx
1162 //    Purpose: The function calculates a covariance matrix for a group of input objects
1163 //             (images, vectors, etc.).
1164 //    Context:
1165 //    Parameters:  nObjects    - number of source objects
1166 //                 input       - pointer either to array of input objects
1167 //                               or to read callback function (depending on ioFlags)
1168 //                 ioFlags     - input/output flags (see Notes to
1169 //                               cvCalcEigenObjects function)
1170 //                 ioBufSize   - input/output buffer size
1171 //                 userData    - pointer to the structure which contains all necessary
1172 //                               data for the callback functions
1173 //                 avg         - averaged object
1174 //                 covarMatrix - covariance matrix (output parameter; must be allocated
1175 //                               before call)
1176 //
1177 //    Notes:  See Notes to cvCalcEigenObjects function
1178 //F*/
1179
1180 CV_IMPL void
1181 cvCalcCovarMatrixEx( int  nObjects, void*  input, int  ioFlags,
1182                      int  ioBufSize, uchar*  buffer, void*  userData,
1183                      IplImage* avg, float*  covarMatrix )
1184 {
1185     float *avg_data;
1186     int avg_step = 0;
1187     CvSize avg_size;
1188     int i;
1189
1190     CV_FUNCNAME( "cvCalcCovarMatrixEx" );
1191
1192     __BEGIN__;
1193
1194     cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
1195     if( avg->depth != IPL_DEPTH_32F )
1196         CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1197     if( avg->nChannels != 1 )
1198         CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1199
1200     if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
1201     {
1202         IplImage **images = (IplImage **) (((CvInput *) & input)->data);
1203         uchar **objects = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects );
1204         int img_step = 0, old_step = 0;
1205         CvSize img_size = avg_size, old_size = avg_size;
1206
1207         if( objects == NULL )
1208             CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1209
1210         for( i = 0; i < nObjects; i++ )
1211         {
1212             IplImage *img = images[i];
1213             uchar *img_data;
1214
1215             cvGetImageRawData( img, &img_data, &img_step, &img_size );
1216             if( img->depth != IPL_DEPTH_8U )
1217                 CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1218             if( img_size != avg_size || img_size != old_size )
1219                 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1220             if( img->nChannels != 1 )
1221                 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1222             if( i > 0 && img_step != old_step )
1223                 CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1224
1225             old_step = img_step;
1226             old_size = img_size;
1227             objects[i] = img_data;
1228         }
1229
1230         CV_CALL( icvCalcCovarMatrixEx_8u32fR( nObjects,
1231                                               (void*) objects,
1232                                               img_step,
1233                                               CV_EIGOBJ_NO_CALLBACK,
1234                                               0,
1235                                               NULL,
1236                                               NULL,
1237                                               avg_data,
1238                                               avg_step,
1239                                               avg_size,
1240                                               covarMatrix ));
1241         cvFree( &objects );
1242     }
1243
1244     else
1245
1246     {
1247         CV_CALL( icvCalcCovarMatrixEx_8u32fR( nObjects,
1248                                               input,
1249                                               avg_step / 4,
1250                                               ioFlags,
1251                                               ioBufSize,
1252                                               buffer,
1253                                               userData,
1254                                               avg_data,
1255                                               avg_step,
1256                                               avg_size,
1257                                               covarMatrix ));
1258     }
1259
1260     __END__;
1261 }
1262
1263 /*F///////////////////////////////////////////////////////////////////////////////////////
1264 //    Name: cvCalcEigenObjects
1265 //    Purpose: The function calculates an orthonormal eigen basis and a mean (averaged)
1266 //             object for a group of input objects (images, vectors, etc.).
1267 //    Context:
1268 //    Parameters: nObjects  - number of source objects
1269 //                input     - pointer either to array of input objects
1270 //                            or to read callback function (depending on ioFlags)
1271 //                output    - pointer either to output eigen objects
1272 //                            or to write callback function (depending on ioFlags)
1273 //                ioFlags   - input/output flags (see Notes)
1274 //                ioBufSize - input/output buffer size
1275 //                userData  - pointer to the structure which contains all necessary
1276 //                            data for the callback functions
1277 //                calcLimit - determines the calculation finish conditions
1278 //                avg       - averaged object (has the same size as ROI)
1279 //                eigVals   - pointer to corresponding eigen values (array of <nObjects>
1280 //                            elements in descending order)
1281 //
1282 //    Notes: 1. input/output data (that is, input objects and eigen ones) may either
1283 //              be allocated in the RAM or be read from/written to the HDD (or any
1284 //              other device) by read/write callback functions. It depends on the
1285 //              value of ioFlags paramater, which may be the following:
1286 //                  CV_EIGOBJ_NO_CALLBACK, or 0;
1287 //                  CV_EIGOBJ_INPUT_CALLBACK;
1288 //                  CV_EIGOBJ_OUTPUT_CALLBACK;
1289 //                  CV_EIGOBJ_BOTH_CALLBACK, or
1290 //                            CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK.
1291 //              The callback functions as well as the user data structure must be
1292 //              developed by the user.
1293 //
1294 //           2. If ioBufSize = 0, or it's too large, the function dermines buffer size
1295 //              itself.
1296 //
1297 //           3. Depending on calcLimit parameter, calculations are finished either if
1298 //              eigenfaces number comes up to certain value or the relation of the
1299 //              current eigenvalue and the largest one comes down to certain value
1300 //              (or any of the above conditions takes place). The calcLimit->type value
1301 //              must be CV_TERMCRIT_NUMB, CV_TERMCRIT_EPS or
1302 //              CV_TERMCRIT_NUMB | CV_TERMCRIT_EPS. The function returns the real
1303 //              values calcLimit->max_iter and calcLimit->epsilon.
1304 //
1305 //           4. eigVals may be equal to NULL (if you don't need eigen values in further).
1306 //
1307 //F*/
1308 CV_IMPL void
1309 cvCalcEigenObjects( int       nObjects,
1310                     void*     input,
1311                     void*     output,
1312                     int       ioFlags,
1313                     int       ioBufSize,
1314                     void*     userData,
1315                     CvTermCriteria* calcLimit,
1316                     IplImage* avg, 
1317                     float*    eigVals )
1318 {
1319     float *avg_data;
1320     int avg_step = 0;
1321     CvSize avg_size;
1322     int i;
1323     int nEigens = nObjects - 1;
1324
1325     CV_FUNCNAME( "cvCalcEigenObjects" );
1326
1327     __BEGIN__;
1328
1329     cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
1330     if( avg->depth != IPL_DEPTH_32F )
1331         CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1332     if( avg->nChannels != 1 )
1333         CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1334
1335     if( nEigens > calcLimit->max_iter && calcLimit->type != CV_TERMCRIT_EPS )
1336         nEigens = calcLimit->max_iter;
1337
1338     switch (ioFlags)
1339     {
1340     case CV_EIGOBJ_NO_CALLBACK:
1341         {
1342             IplImage **objects = (IplImage **) (((CvInput *) & input)->data);
1343             IplImage **eigens = (IplImage **) (((CvInput *) & output)->data);
1344             uchar **objs = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects );
1345             float **eigs = (float **) cvAlloc( sizeof( float * ) * nEigens );
1346             int obj_step = 0, old_step = 0;
1347             int eig_step = 0, oldeig_step = 0;
1348             CvSize obj_size = avg_size, old_size = avg_size,
1349
1350                 eig_size = avg_size, oldeig_size = avg_size;
1351
1352             if( objects == NULL || eigens == NULL )
1353                 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1354
1355             for( i = 0; i < nObjects; i++ )
1356             {
1357                 IplImage *img = objects[i];
1358                 uchar *obj_data;
1359
1360                 cvGetImageRawData( img, &obj_data, &obj_step, &obj_size );
1361                 if( img->depth != IPL_DEPTH_8U )
1362                     CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1363                 if( obj_size != avg_size || obj_size != old_size )
1364                     CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1365                 if( img->nChannels != 1 )
1366                     CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1367                 if( i > 0 && obj_step != old_step )
1368                     CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1369
1370                 old_step = obj_step;
1371                 old_size = obj_size;
1372                 objs[i] = obj_data;
1373             }
1374             for( i = 0; i < nEigens; i++ )
1375             {
1376                 IplImage *eig = eigens[i];
1377                 float *eig_data;
1378
1379                 cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
1380                 if( eig->depth != IPL_DEPTH_32F )
1381                     CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1382                 if( eig_size != avg_size || eig_size != oldeig_size )
1383                     CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1384                 if( eig->nChannels != 1 )
1385                     CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1386                 if( i > 0 && eig_step != oldeig_step )
1387                     CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1388
1389                 oldeig_step = eig_step;
1390                 oldeig_size = eig_size;
1391                 eigs[i] = eig_data;
1392             }
1393             CV_CALL( icvCalcEigenObjects_8u32fR( nObjects, (void*) objs, obj_step,
1394                                                  (void*) eigs, eig_step, obj_size,
1395                                                  ioFlags, ioBufSize, userData,
1396                                                  calcLimit, avg_data, avg_step, eigVals ));
1397             cvFree( &objs );
1398             cvFree( &eigs );
1399             break;
1400         }
1401
1402     case CV_EIGOBJ_OUTPUT_CALLBACK:
1403         {
1404             IplImage **objects = (IplImage **) (((CvInput *) & input)->data);
1405             uchar **objs = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects );
1406             int obj_step = 0, old_step = 0;
1407             CvSize obj_size = avg_size, old_size = avg_size;
1408
1409             if( objects == NULL )
1410                 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1411
1412             for( i = 0; i < nObjects; i++ )
1413             {
1414                 IplImage *img = objects[i];
1415                 uchar *obj_data;
1416
1417                 cvGetImageRawData( img, &obj_data, &obj_step, &obj_size );
1418                 if( img->depth != IPL_DEPTH_8U )
1419                     CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1420                 if( obj_size != avg_size || obj_size != old_size )
1421                     CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1422                 if( img->nChannels != 1 )
1423                     CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1424                 if( i > 0 && obj_step != old_step )
1425                     CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1426
1427                 old_step = obj_step;
1428                 old_size = obj_size;
1429                 objs[i] = obj_data;
1430             }
1431             CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
1432                                                  (void*) objs,
1433                                                  obj_step,
1434                                                  output,
1435                                                  avg_step,
1436                                                  obj_size,
1437                                                  ioFlags,
1438                                                  ioBufSize,
1439                                                  userData,
1440                                                  calcLimit,
1441                                                  avg_data,
1442                                                  avg_step,
1443                                                  eigVals   ));
1444             cvFree( &objs );
1445             break;
1446         }
1447
1448     case CV_EIGOBJ_INPUT_CALLBACK:
1449         {
1450             IplImage **eigens = (IplImage **) (((CvInput *) & output)->data);
1451             float **eigs = (float**) cvAlloc( sizeof( float* ) * nEigens );
1452             int eig_step = 0, oldeig_step = 0;
1453             CvSize eig_size = avg_size, oldeig_size = avg_size;
1454
1455             if( eigens == NULL )
1456                 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1457
1458             for( i = 0; i < nEigens; i++ )
1459             {
1460                 IplImage *eig = eigens[i];
1461                 float *eig_data;
1462
1463                 cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
1464                 if( eig->depth != IPL_DEPTH_32F )
1465                     CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1466                 if( eig_size != avg_size || eig_size != oldeig_size )
1467                     CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1468                 if( eig->nChannels != 1 )
1469                     CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1470                 if( i > 0 && eig_step != oldeig_step )
1471                     CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1472
1473                 oldeig_step = eig_step;
1474                 oldeig_size = eig_size;
1475                 eigs[i] = eig_data;
1476             }
1477             CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
1478                                                  input,
1479                                                  avg_step / 4,
1480                                                  (void*) eigs,
1481                                                  eig_step,
1482                                                  eig_size,
1483                                                  ioFlags,
1484                                                  ioBufSize,
1485                                                  userData,
1486                                                  calcLimit,
1487                                                  avg_data,
1488                                                  avg_step,
1489                                                  eigVals   ));
1490             cvFree( &eigs );
1491             break;
1492         }
1493     case CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK:
1494
1495         CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
1496                                              input,
1497                                              avg_step / 4,
1498                                              output,
1499                                              avg_step,
1500                                              avg_size,
1501                                              ioFlags,
1502                                              ioBufSize,
1503                                              userData,
1504                                              calcLimit,
1505                                              avg_data,
1506                                              avg_step,
1507                                              eigVals   ));
1508         break;
1509
1510     default:
1511         CV_ERROR( CV_StsBadArg, "Unsupported i/o flag" );
1512     }
1513
1514     __END__;
1515 }
1516
1517 /*--------------------------------------------------------------------------------------*/
1518 /*F///////////////////////////////////////////////////////////////////////////////////////
1519 //    Name: cvCalcDecompCoeff
1520 //    Purpose: The function calculates one decomposition coefficient of input object
1521 //             using previously calculated eigen object and the mean (averaged) object
1522 //    Context:
1523 //    Parameters:  obj     - input object
1524 //                 eigObj  - eigen object
1525 //                 avg     - averaged object
1526 //
1527 //    Returns: decomposition coefficient value or large negative value (if error)
1528 //
1529 //    Notes:
1530 //F*/
1531
1532 CV_IMPL double
1533 cvCalcDecompCoeff( IplImage * obj, IplImage * eigObj, IplImage * avg )
1534 {
1535     double coeff = DBL_MAX;
1536
1537     uchar *obj_data;
1538     float *eig_data;
1539     float *avg_data;
1540     int obj_step = 0, eig_step = 0, avg_step = 0;
1541     CvSize obj_size, eig_size, avg_size;
1542
1543     CV_FUNCNAME( "cvCalcDecompCoeff" );
1544
1545     __BEGIN__;
1546
1547     cvGetImageRawData( obj, &obj_data, &obj_step, &obj_size );
1548     if( obj->depth != IPL_DEPTH_8U )
1549         CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1550     if( obj->nChannels != 1 )
1551         CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1552
1553     cvGetImageRawData( eigObj, (uchar **) & eig_data, &eig_step, &eig_size );
1554     if( eigObj->depth != IPL_DEPTH_32F )
1555         CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1556     if( eigObj->nChannels != 1 )
1557         CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1558
1559     cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
1560     if( avg->depth != IPL_DEPTH_32F )
1561         CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1562     if( avg->nChannels != 1 )
1563         CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1564
1565     if( obj_size != eig_size || obj_size != avg_size )
1566         CV_ERROR( CV_StsBadArg, "different sizes of images" );
1567
1568     coeff = icvCalcDecompCoeff_8u32fR( obj_data, obj_step,
1569                                        eig_data, eig_step,
1570                                        avg_data, avg_step, obj_size );
1571
1572     __END__;
1573     
1574     return coeff;
1575 }
1576
1577 /*--------------------------------------------------------------------------------------*/
1578 /*F///////////////////////////////////////////////////////////////////////////////////////
1579 //    Names: cvEigenDecomposite
1580 //    Purpose: The function calculates all decomposition coefficients for input object
1581 //             using previously calculated eigen objects basis and the mean (averaged)
1582 //             object
1583 //
1584 //    Parameters:  obj         - input object
1585 //                 nEigObjs    - number of eigen objects
1586 //                 eigInput    - pointer either to array of pointers to eigen objects
1587 //                               or to read callback function (depending on ioFlags)
1588 //                 ioFlags     - input/output flags
1589 //                 userData    - pointer to the structure which contains all necessary
1590 //                               data for the callback function
1591 //                 avg         - averaged object
1592 //                 coeffs      - calculated coefficients (output data)
1593 //
1594 //    Notes:   see notes for cvCalcEigenObjects function
1595 //F*/
1596
1597 CV_IMPL void
1598 cvEigenDecomposite( IplImage* obj,
1599                     int       nEigObjs,
1600                     void*     eigInput,
1601                     int       ioFlags, 
1602                     void*     userData, 
1603                     IplImage* avg, 
1604                     float*    coeffs )
1605 {
1606     float *avg_data;
1607     uchar *obj_data;
1608     int avg_step = 0, obj_step = 0;
1609     CvSize avg_size, obj_size;
1610     int i;
1611
1612     CV_FUNCNAME( "cvEigenDecomposite" );
1613
1614     __BEGIN__;
1615
1616     cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
1617     if( avg->depth != IPL_DEPTH_32F )
1618         CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1619     if( avg->nChannels != 1 )
1620         CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1621
1622     cvGetImageRawData( obj, &obj_data, &obj_step, &obj_size );
1623     if( obj->depth != IPL_DEPTH_8U )
1624         CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1625     if( obj->nChannels != 1 )
1626         CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1627
1628     if( obj_size != avg_size )
1629         CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1630
1631     if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
1632     {
1633         IplImage **eigens = (IplImage **) (((CvInput *) & eigInput)->data);
1634         float **eigs = (float **) cvAlloc( sizeof( float * ) * nEigObjs );
1635         int eig_step = 0, old_step = 0;
1636         CvSize eig_size = avg_size, old_size = avg_size;
1637
1638         if( eigs == NULL )
1639             CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1640
1641         for( i = 0; i < nEigObjs; i++ )
1642         {
1643             IplImage *eig = eigens[i];
1644             float *eig_data;
1645
1646             cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
1647             if( eig->depth != IPL_DEPTH_32F )
1648                 CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1649             if( eig_size != avg_size || eig_size != old_size )
1650                 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1651             if( eig->nChannels != 1 )
1652                 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1653             if( i > 0 && eig_step != old_step )
1654                 CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1655
1656             old_step = eig_step;
1657             old_size = eig_size;
1658             eigs[i] = eig_data;
1659         }
1660
1661         CV_CALL( icvEigenDecomposite_8u32fR( obj_data,
1662                                              obj_step,
1663                                              nEigObjs,
1664                                              (void*) eigs,
1665                                              eig_step,
1666                                              ioFlags,
1667                                              userData,
1668                                              avg_data,
1669                                              avg_step,
1670                                              obj_size,
1671                                              coeffs   ));
1672         cvFree( &eigs );
1673     }
1674
1675     else
1676
1677     {
1678         CV_CALL( icvEigenDecomposite_8u32fR( obj_data,
1679                                              obj_step,
1680                                              nEigObjs,
1681                                              eigInput,
1682                                              avg_step,
1683                                              ioFlags,
1684                                              userData,
1685                                              avg_data,
1686                                              avg_step,
1687                                              obj_size,
1688                                              coeffs   ));
1689     }
1690
1691     __END__;
1692 }
1693
1694 /*--------------------------------------------------------------------------------------*/
1695 /*F///////////////////////////////////////////////////////////////////////////////////////
1696 //    Name: cvEigenProjection
1697 //    Purpose: The function calculates object projection to the eigen sub-space (restores
1698 //             an object) using previously calculated eigen objects basis, mean (averaged)
1699 //             object and decomposition coefficients of the restored object
1700 //    Context:
1701 //    Parameters:  nEigObjs    - number of eigen objects
1702 //                 eigInput    - pointer either to array of pointers to eigen objects
1703 //                               or to read callback function (depending on ioFlags)
1704 //                 ioFlags     - input/output flags
1705 //                 userData    - pointer to the structure which contains all necessary
1706 //                               data for the callback function
1707 //                 coeffs      - array of decomposition coefficients
1708 //                 avg         - averaged object
1709 //                 proj        - object projection (output data)
1710 //
1711 //    Notes:   see notes for cvCalcEigenObjects function
1712 //F*/
1713
1714 CV_IMPL void
1715 cvEigenProjection( void*     eigInput,
1716                    int       nEigObjs,
1717                    int       ioFlags,
1718                    void*     userData,
1719                    float*    coeffs, 
1720                    IplImage* avg,
1721                    IplImage* proj )
1722 {
1723     float *avg_data;
1724     uchar *proj_data;
1725     int avg_step = 0, proj_step = 0;
1726     CvSize avg_size, proj_size;
1727     int i;
1728
1729     CV_FUNCNAME( "cvEigenProjection" );
1730
1731     __BEGIN__;
1732
1733     cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
1734     if( avg->depth != IPL_DEPTH_32F )
1735         CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1736     if( avg->nChannels != 1 )
1737         CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1738
1739     cvGetImageRawData( proj, &proj_data, &proj_step, &proj_size );
1740     if( proj->depth != IPL_DEPTH_8U )
1741         CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1742     if( proj->nChannels != 1 )
1743         CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1744
1745     if( proj_size != avg_size )
1746         CV_ERROR( CV_StsBadArg, "Different sizes of projects" );
1747
1748     if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
1749     {
1750         IplImage **eigens = (IplImage**) (((CvInput *) & eigInput)->data);
1751         float **eigs = (float**) cvAlloc( sizeof( float * ) * nEigObjs );
1752         int eig_step = 0, old_step = 0;
1753         CvSize eig_size = avg_size, old_size = avg_size;
1754
1755         if( eigs == NULL )
1756             CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1757
1758         for( i = 0; i < nEigObjs; i++ )
1759         {
1760             IplImage *eig = eigens[i];
1761             float *eig_data;
1762
1763             cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
1764             if( eig->depth != IPL_DEPTH_32F )
1765                 CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1766             if( eig_size != avg_size || eig_size != old_size )
1767                 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1768             if( eig->nChannels != 1 )
1769                 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
1770             if( i > 0 && eig_step != old_step )
1771                 CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1772
1773             old_step = eig_step;
1774             old_size = eig_size;
1775             eigs[i] = eig_data;
1776         }
1777
1778         CV_CALL( icvEigenProjection_8u32fR( nEigObjs,
1779                                             (void*) eigs,
1780                                             eig_step,
1781                                             ioFlags,
1782                                             userData,
1783                                             coeffs,
1784                                             avg_data,
1785                                             avg_step,
1786                                             proj_data,
1787                                             proj_step,
1788                                             avg_size   ));
1789         cvFree( &eigs );
1790     }
1791
1792     else
1793
1794     {
1795         CV_CALL( icvEigenProjection_8u32fR( nEigObjs,
1796                                             eigInput,
1797                                             avg_step,
1798                                             ioFlags,
1799                                             userData,
1800                                             coeffs,
1801                                             avg_data,
1802                                             avg_step,
1803                                             proj_data,
1804                                             proj_step,
1805                                             avg_size   ));
1806     }
1807
1808     __END__;
1809 }
1810
1811 /* End of file. */