1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
45 icvJacobiEigens_32f(float *A, float *V, float *E, int n, float eps)
48 float *AA = A, *VV = V;
49 double Amax, anorm = 0, ax;
51 if( A == NULL || V == NULL || E == NULL )
52 return CV_NULLPTR_ERR;
54 return CV_BADSIZE_ERR;
58 /*-------- Prepare --------*/
59 for( i = 0; i < n; i++, VV += n, AA += n )
61 for( j = 0; j < i; j++ )
67 for( j = 0; j < n; j++ )
72 anorm = sqrt( anorm + anorm );
82 float *V1 = V, *A1 = A;
85 for( p = 0; p < n - 1; p++, A1 += n, V1 += n )
87 float *A2 = A + n * (p + 1), *V2 = V + n * (p + 1);
89 for( q = p + 1; q < n; q++, A2 += n, V2 += n )
91 double x, y, c, s, c2, s2, a;
92 float *A3, Apq = A1[q], App, Aqq, Aip, Aiq, Vpi, Vqi;
94 if( fabs( Apq ) < Amax )
99 /*---- Calculation of rotation angle's sine & cosine ----*/
102 y = 5.0e-1 * (App - Aqq);
103 x = -Apq / sqrt( (double)Apq * Apq + (double)y * y );
106 s = x / sqrt( 2.0 * (1.0 + sqrt( 1.0 - (double)x * x )));
108 c = sqrt( 1.0 - s2 );
110 a = 2.0 * Apq * c * s;
112 /*---- Apq annulation ----*/
114 for( i = 0; i < p; i++, A3 += n )
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);
125 for( ; i < q; i++, A3 += n )
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);
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);
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;
155 } /* while ( Amax > ax ) */
157 for( i = 0, k = 0; i < n; i++, k += n + 1 )
159 /*printf(" M = %d\n", M); */
161 /* -------- ordering -------- */
162 for( i = 0; i < n; i++ )
165 float Em = (float) fabs( E[i] );
167 for( j = i + 1; j < n; j++ )
169 float Ej = (float) fabs( E[j] );
171 m = (Em < Ej) ? j : m;
172 Em = (Em < Ej) ? Ej : Em;
181 for( j = 0, k = i * n, l = m * n; j < n; j++, k++, l++ )
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.
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
207 // Returns: CV_NO_ERR or error code
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 )
217 int objStep = objStep1;
219 /* ---- TEST OF PARAMETERS ---- */
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;
236 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK ) /* ==== USE INPUT CALLBACK ==== */
238 int nio, ngr, igr, n = size.width * size.height, mm = 0;
239 CvCallback read_callback = ((CvInput *) & input)->callback;
243 nio = ioBufSize / n; /* number of objects in buffer */
244 ngr = nObjects / nio; /* number of io groups */
249 buffer2 = (uchar *)cvAlloc( sizeof( uchar ) * n );
250 if( buffer2 == NULL )
251 return CV_OUTOFMEM_ERR;
253 for( igr = 0; igr < ngr; igr++ )
256 int io, jo, imin = igr * nio, imax = imin + nio;
257 uchar *bu1 = buffer, *bu2;
259 if( imax > nObjects )
263 for( io = imin; io < imax; io++, bu1 += n )
267 r = (CvStatus)read_callback( io, (void *) bu1, userData );
272 /* diagonal square calc */
274 for( io = imin; io < imax; io++, bu1 += n )
277 for( jo = io; jo < imax; jo++, bu2 += n )
283 for( k = 0; k < size.height; k++, fu += avgStep )
284 for( l = 0; l < size.width; l++, ij++ )
286 float f = fu[l], u1 = bu1[ij], u2 = bu2[ij];
288 w += (u1 - f) * (u2 - f);
290 covarMatrix[io * nObjects + jo] = covarMatrix[jo * nObjects + io] = w;
294 /* non-diagonal elements calc */
295 for( jo = imax; jo < nObjects; jo++ )
303 r = (CvStatus)read_callback( jo, (void *) bu2, userData );
307 for( io = imin; io < imax; io++, bu1 += n )
313 for( k = 0; k < size.height; k++, fu += avgStep )
315 for( l = 0; l < size.width - 3; l += 4, ij += 4 )
321 w += (u1 - f) * (u2 - f);
325 w += (u1 - f) * (u2 - f);
329 w += (u1 - f) * (u2 - f);
333 w += (u1 - f) * (u2 - f);
335 for( ; l < size.width; l++, ij++ )
337 float f = fu[l], u1 = bu1[ij], u2 = bu2[ij];
339 w += (u1 - f) * (u2 - f);
342 covarMatrix[io * nObjects + jo] = covarMatrix[jo * nObjects + io] = w;
351 /* ==== NOT USE INPUT CALLBACK ==== */
354 uchar **objects = (uchar **) (((CvInput *) & input)->data);
356 for( i = 0; i < nObjects; i++ )
358 uchar *bu = objects[i];
360 for( j = i; j < nObjects; j++ )
366 uchar *bu2 = objects[j];
368 for( k = 0; k < size.height;
369 k++, bu1 += objStep, bu2 += objStep, a += avgStep )
371 for( l = 0; l < size.width - 3; l += 4 )
377 w += (u1 - f) * (u2 - f);
381 w += (u1 - f) * (u2 - f);
385 w += (u1 - f) * (u2 - f);
389 w += (u1 - f) * (u2 - f);
391 for( ; l < size.width; l++ )
397 w += (u1 - f) * (u2 - f);
401 covarMatrix[i * nObjects + j] = covarMatrix[j * nObjects + i] = w;
409 /*======================== end of icvCalcCovarMatrixEx_8u32fR ===========================*/
413 icvDefaultBufferSize( void )
415 return 10 * 1024 * 1024;
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.
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)
441 // Returns: CV_NO_ERR or error code
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.
455 // 2. If ioBufSize = 0, or it's too large, the function dermines buffer size
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.
466 // 4. eigVals may be equal to NULL (if you don't need eigen values in further).
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 )
476 int i, j, n, iev = 0, m1 = nObjects - 1, objStep1 = objStep, eigStep1 = eigStep / 4;
477 CvSize objSize, eigSize, avgSize;
483 float m = 1.0f / (float) nObjects;
486 if( m1 > calcLimit->max_iter && calcLimit->type != CV_TERMCRIT_EPS )
487 m1 = calcLimit->max_iter;
489 /* ---- TEST OF PARAMETERS ---- */
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;
512 if( objStep == size.width && eigStep == size.width && avgStep == size.width )
514 size.width *= size.height;
516 objStep = objStep1 = eigStep = eigStep1 = avgStep = size.width;
518 objSize = eigSize = avgSize = size;
520 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
522 objSize.width *= objSize.height;
524 objStep = objSize.width;
525 objStep1 = size.width;
528 if( ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK )
530 eigSize.width *= eigSize.height;
532 eigStep = eigSize.width;
533 eigStep1 = size.width;
536 n = objSize.height * objSize.width * (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) +
537 2 * eigSize.height * eigSize.width * (ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK);
539 /* Buffer size determination */
542 int size = icvDefaultBufferSize();
543 ioBufSize = MIN( size, n );
546 /* memory allocation (if necesseay) */
548 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
550 buf = (uchar *) cvAlloc( sizeof( uchar ) * objSize.width );
552 return CV_OUTOFMEM_ERR;
557 buffer = (void *) cvAlloc( ioBufSize );
562 return CV_OUTOFMEM_ERR;
566 /* Calculation of averaged object */
568 for( i = 0; i < avgSize.height; i++, bf += avgStep )
569 for( j = 0; j < avgSize.width; j++ )
572 for( i = 0; i < nObjects; i++ )
575 uchar *bu = (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) ? buf : ((uchar **) input)[i];
577 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
579 CvCallback read_callback = ((CvInput *) & input)->callback;
581 r = (CvStatus)read_callback( i, (void *) buf, userData );
593 for( k = 0; k < avgSize.height; k++, bf += avgStep, bu += objStep1 )
594 for( l = 0; l < avgSize.width; l++ )
599 for( i = 0; i < avgSize.height; i++, bf += avgStep )
600 for( j = 0; j < avgSize.width; j++ )
603 /* Calculation of covariance matrix */
604 c = (float *) cvAlloc( sizeof( float ) * nObjects * nObjects );
612 return CV_OUTOFMEM_ERR;
615 r = icvCalcCovarMatrixEx_8u32fR( nObjects, input, objStep1, ioFlags, ioBufSize,
616 (uchar *) buffer, userData, avg, 4 * avgStep, size, c );
627 /* Calculation of eigenvalues & eigenvectors */
628 ev = (float *) cvAlloc( sizeof( float ) * nObjects * nObjects );
637 return CV_OUTOFMEM_ERR;
640 if( eigVals == NULL )
642 eigVals = (float *) cvAlloc( sizeof( float ) * nObjects );
644 if( eigVals == NULL )
652 return CV_OUTOFMEM_ERR;
657 r = icvJacobiEigens_32f( c, ev, eigVals, nObjects, 0.0f );
671 /* Eigen objects number determination */
672 if( calcLimit->type != CV_TERMCRIT_NUMBER )
674 for( i = 0; i < m1; i++ )
675 if( fabs( eigVals[i] / eigVals[0] ) < calcLimit->epsilon )
677 m1 = calcLimit->max_iter = i;
680 m1 = calcLimit->max_iter;
681 calcLimit->epsilon = (float) fabs( eigVals[m1 - 1] / eigVals[0] );
683 for( i = 0; i < m1; i++ )
684 eigVals[i] = (float) (1.0 / sqrt( (double)eigVals[i] ));
686 /* ----------------- Calculation of eigenobjects ----------------------- */
687 if( ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK )
691 nio = ioBufSize / (4 * eigSize.width); /* number of eigen objects in buffer */
692 ngr = m1 / nio; /* number of io groups */
696 for( igr = 0; igr < ngr; igr++ )
698 int i, io, ie, imin = igr * nio, imax = imin + nio;
703 for( i = 0; i < eigSize.width * (imax - imin); i++ )
704 ((float *) buffer)[i] = 0.f;
706 for( io = 0; io < nObjects; io++ )
708 uchar *bu = ioFlags & CV_EIGOBJ_INPUT_CALLBACK ? buf : ((uchar **) input)[io];
710 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
712 CvCallback read_callback = ((CvInput *) & input)->callback;
714 r = (CvStatus)read_callback( io, (void *) buf, userData );
728 for( ie = imin; ie < imax; ie++ )
732 float e = ev[ie * nObjects + io] * eigVals[ie];
733 float *be = ((float *) buffer) + ((ie - imin) * eigStep);
736 for( k = 0; k < size.height; k++, bv += objStep1,
737 bf += avgStep, be += eigStep1 )
739 for( l = 0; l < size.width - 3; l += 4 )
744 be[l] += e * (v - f);
747 be[l + 1] += e * (v - f);
750 be[l + 2] += e * (v - f);
753 be[l + 3] += e * (v - f);
755 for( ; l < size.width; l++ )
756 be[l] += e * (bv[l] - bf[l]);
761 for( ie = imin; ie < imax; ie++ ) /* calculated eigen objects writting */
763 CvCallback write_callback = ((CvInput *) & output)->callback;
764 float *be = ((float *) buffer) + ((ie - imin) * eigStep);
766 r = (CvStatus)write_callback( ie, (void *) be, userData );
786 for( i = 0; i < m1; i++ ) /* e.o. annulation */
788 float *be = ((float **) output)[i];
790 for( p = 0; p < eigSize.height; p++, be += eigStep )
791 for( l = 0; l < eigSize.width; l++ )
795 for( k = 0; k < nObjects; k++ )
797 uchar *bv = (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) ? buf : ((uchar **) input)[k];
799 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
801 CvCallback read_callback = ((CvInput *) & input)->callback;
803 r = (CvStatus)read_callback( k, (void *) buf, userData );
817 for( i = 0; i < m1; i++ )
819 float v = eigVals[i] * ev[i * nObjects + k];
820 float *be = ((float **) output)[i];
825 for( p = 0; p < size.height; p++, bu += objStep1,
826 bf += avgStep, be += eigStep1 )
828 for( l = 0; l < size.width - 3; l += 4 )
833 be[l] += v * (u - f);
836 be[l + 1] += v * (u - f);
839 be[l + 2] += v * (u - f);
842 be[l + 3] += v * (u - f);
844 for( ; l < size.width; l++ )
845 be[l] += v * (bu[l] - bf[l]);
855 for( i = 0; i < m1; i++ )
856 eigVals[i] = 1.f / (eigVals[i] * eigVals[i]);
864 /* --- End of icvCalcEigenObjects_8u32fR --- */
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
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
879 // Returns: decomposition coefficient value or large negative value (if error)
883 static float CV_STDCALL
884 icvCalcDecompCoeff_8u32fR( uchar* obj, int objStep,
885 float *eigObj, int eigStep,
886 float *avg, int avgStep, CvSize size )
891 if( size.width > objStep || 4 * size.width > eigStep
892 || 4 * size.width > avgStep || size.height < 1 )
894 if( obj == NULL || eigObj == NULL || avg == NULL )
900 if( size.width == objStep && size.width == eigStep && size.width == avgStep )
902 size.width *= size.height;
904 objStep = eigStep = avgStep = size.width;
907 for( i = 0; i < size.height; i++, obj += objStep, eigObj += eigStep, avg += avgStep )
909 for( k = 0; k < size.width - 4; k += 4 )
911 float o = (float) obj[k];
916 o = (float) obj[k + 1];
920 o = (float) obj[k + 2];
924 o = (float) obj[k + 3];
929 for( ; k < size.width; k++ )
930 w += eigObj[k] * ((float) obj[k] - avg[k]);
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)
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)
956 // Returns: icv status
958 // Notes: see notes for icvCalcEigenObjects_8u32fR function
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 )
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;
978 for( i = 0; i < nEigObjs; i++ )
979 if( ((uchar **) eigInput)[i] == NULL )
980 return CV_NULLPTR_ERR;
982 if( ioFlags ) /* callback */
986 CvCallback read_callback = ((CvInput *) & eigInput)->callback;
988 eigStep = 4 * size.width;
990 /* memory allocation */
991 buffer = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
994 return CV_OUTOFMEM_ERR;
996 for( i = 0; i < nEigObjs; i++ )
999 CvStatus r = (CvStatus)read_callback( i, (void *) buffer, userData );
1006 w = icvCalcDecompCoeff_8u32fR( obj, objStep, buffer,
1007 eigStep, avg, avgStep, size );
1011 return CV_NOTDEFINED_ERR;
1020 for( i = 0; i < nEigObjs; i++ )
1022 float w = icvCalcDecompCoeff_8u32fR( obj, objStep, ((float **) eigInput)[i],
1023 eigStep, avg, avgStep, size );
1026 return CV_NOTDEFINED_ERR;
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
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
1050 // Returns: CV status
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 )
1062 float *buffer = NULL;
1064 CvCallback read_callback = ((CvInput *) & eigInput)->callback;
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;
1073 for( i = 0; i < nEigObjs; i++ )
1074 if( ((uchar **) eigInput)[i] == NULL )
1075 return CV_NULLPTR_ERR;
1079 if( size.width == restStep && size.width == eigStep && size.width == avgStep )
1081 size.width *= size.height;
1083 restStep = eigStep = avgStep = size.width;
1086 buf = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
1089 return CV_OUTOFMEM_ERR;
1091 for( i = 0; i < size.height; i++, avg += avgStep, b += size.width )
1092 for( j = 0; j < size.width; j++ )
1097 buffer = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
1099 if( buffer == NULL )
1102 return CV_OUTOFMEM_ERR;
1104 eigStep = size.width;
1107 for( k = 0; k < nEigObjs; k++ )
1109 float *e = ioFlags ? buffer : ((float **) eigInput)[k];
1110 float c = coeffs[k];
1112 if( ioFlags ) /* read eigen object */
1114 CvStatus r = (CvStatus)read_callback( k, (void *) buffer, userData );
1125 for( i = 0; i < size.height; i++, e += eigStep, b += size.width )
1127 for( j = 0; j < size.width - 3; j += 4 )
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];
1139 for( ; j < size.width; j++ )
1145 for( i = 0; i < size.height; i++, avg += avgStep, b += size.width, rest += restStep )
1146 for( j = 0; j < size.width; j++ )
1148 int w = cvRound( b[j] );
1150 w = !(w & ~255) ? w : w < 0 ? 0 : 255;
1151 rest[j] = (uchar) w;
1160 /*F///////////////////////////////////////////////////////////////////////////////////////
1161 // Name: cvCalcCovarMatrixEx
1162 // Purpose: The function calculates a covariance matrix for a group of input objects
1163 // (images, vectors, etc.).
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
1177 // Notes: See Notes to cvCalcEigenObjects function
1181 cvCalcCovarMatrixEx( int nObjects, void* input, int ioFlags,
1182 int ioBufSize, uchar* buffer, void* userData,
1183 IplImage* avg, float* covarMatrix )
1190 CV_FUNCNAME( "cvCalcCovarMatrixEx" );
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 );
1200 if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
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;
1207 if( objects == NULL )
1208 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1210 for( i = 0; i < nObjects; i++ )
1212 IplImage *img = images[i];
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" );
1225 old_step = img_step;
1226 old_size = img_size;
1227 objects[i] = img_data;
1230 CV_CALL( icvCalcCovarMatrixEx_8u32fR( nObjects,
1233 CV_EIGOBJ_NO_CALLBACK,
1247 CV_CALL( icvCalcCovarMatrixEx_8u32fR( nObjects,
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.).
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)
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.
1294 // 2. If ioBufSize = 0, or it's too large, the function dermines buffer size
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.
1305 // 4. eigVals may be equal to NULL (if you don't need eigen values in further).
1309 cvCalcEigenObjects( int nObjects,
1315 CvTermCriteria* calcLimit,
1323 int nEigens = nObjects - 1;
1325 CV_FUNCNAME( "cvCalcEigenObjects" );
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 );
1335 if( nEigens > calcLimit->max_iter && calcLimit->type != CV_TERMCRIT_EPS )
1336 nEigens = calcLimit->max_iter;
1340 case CV_EIGOBJ_NO_CALLBACK:
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,
1350 eig_size = avg_size, oldeig_size = avg_size;
1352 if( objects == NULL || eigens == NULL )
1353 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1355 for( i = 0; i < nObjects; i++ )
1357 IplImage *img = objects[i];
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" );
1370 old_step = obj_step;
1371 old_size = obj_size;
1374 for( i = 0; i < nEigens; i++ )
1376 IplImage *eig = eigens[i];
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" );
1389 oldeig_step = eig_step;
1390 oldeig_size = eig_size;
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 ));
1402 case CV_EIGOBJ_OUTPUT_CALLBACK:
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;
1409 if( objects == NULL )
1410 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1412 for( i = 0; i < nObjects; i++ )
1414 IplImage *img = objects[i];
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" );
1427 old_step = obj_step;
1428 old_size = obj_size;
1431 CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
1448 case CV_EIGOBJ_INPUT_CALLBACK:
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;
1455 if( eigens == NULL )
1456 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1458 for( i = 0; i < nEigens; i++ )
1460 IplImage *eig = eigens[i];
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" );
1473 oldeig_step = eig_step;
1474 oldeig_size = eig_size;
1477 CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
1493 case CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK:
1495 CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
1511 CV_ERROR( CV_StsBadArg, "Unsupported i/o flag" );
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
1523 // Parameters: obj - input object
1524 // eigObj - eigen object
1525 // avg - averaged object
1527 // Returns: decomposition coefficient value or large negative value (if error)
1533 cvCalcDecompCoeff( IplImage * obj, IplImage * eigObj, IplImage * avg )
1535 double coeff = DBL_MAX;
1540 int obj_step = 0, eig_step = 0, avg_step = 0;
1541 CvSize obj_size, eig_size, avg_size;
1543 CV_FUNCNAME( "cvCalcDecompCoeff" );
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 );
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 );
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 );
1565 if( obj_size != eig_size || obj_size != avg_size )
1566 CV_ERROR( CV_StsBadArg, "different sizes of images" );
1568 coeff = icvCalcDecompCoeff_8u32fR( obj_data, obj_step,
1570 avg_data, avg_step, obj_size );
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)
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)
1594 // Notes: see notes for cvCalcEigenObjects function
1598 cvEigenDecomposite( IplImage* obj,
1608 int avg_step = 0, obj_step = 0;
1609 CvSize avg_size, obj_size;
1612 CV_FUNCNAME( "cvEigenDecomposite" );
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 );
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 );
1628 if( obj_size != avg_size )
1629 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1631 if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
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;
1639 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1641 for( i = 0; i < nEigObjs; i++ )
1643 IplImage *eig = eigens[i];
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" );
1656 old_step = eig_step;
1657 old_size = eig_size;
1661 CV_CALL( icvEigenDecomposite_8u32fR( obj_data,
1678 CV_CALL( icvEigenDecomposite_8u32fR( obj_data,
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
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)
1711 // Notes: see notes for cvCalcEigenObjects function
1715 cvEigenProjection( void* eigInput,
1725 int avg_step = 0, proj_step = 0;
1726 CvSize avg_size, proj_size;
1729 CV_FUNCNAME( "cvEigenProjection" );
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 );
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 );
1745 if( proj_size != avg_size )
1746 CV_ERROR( CV_StsBadArg, "Different sizes of projects" );
1748 if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
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;
1756 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1758 for( i = 0; i < nEigObjs; i++ )
1760 IplImage *eig = eigens[i];
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" );
1773 old_step = eig_step;
1774 old_size = eig_size;
1778 CV_CALL( icvEigenProjection_8u32fR( nEigObjs,
1795 CV_CALL( icvEigenProjection_8u32fR( nEigObjs,