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.
42 #include "precomp.hpp"
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 ioBufSize = MIN( icvDefaultBufferSize(), n );
545 /* memory allocation (if necesseay) */
547 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
549 buf = (uchar *) cvAlloc( sizeof( uchar ) * objSize.width );
551 return CV_OUTOFMEM_ERR;
556 buffer = (void *) cvAlloc( ioBufSize );
561 return CV_OUTOFMEM_ERR;
565 /* Calculation of averaged object */
567 for( i = 0; i < avgSize.height; i++, bf += avgStep )
568 for( j = 0; j < avgSize.width; j++ )
571 for( i = 0; i < nObjects; i++ )
574 uchar *bu = (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) ? buf : ((uchar **) input)[i];
576 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
578 CvCallback read_callback = ((CvInput *) & input)->callback;
580 r = (CvStatus)read_callback( i, (void *) buf, userData );
592 for( k = 0; k < avgSize.height; k++, bf += avgStep, bu += objStep1 )
593 for( l = 0; l < avgSize.width; l++ )
598 for( i = 0; i < avgSize.height; i++, bf += avgStep )
599 for( j = 0; j < avgSize.width; j++ )
602 /* Calculation of covariance matrix */
603 c = (float *) cvAlloc( sizeof( float ) * nObjects * nObjects );
611 return CV_OUTOFMEM_ERR;
614 r = icvCalcCovarMatrixEx_8u32fR( nObjects, input, objStep1, ioFlags, ioBufSize,
615 (uchar *) buffer, userData, avg, 4 * avgStep, size, c );
626 /* Calculation of eigenvalues & eigenvectors */
627 ev = (float *) cvAlloc( sizeof( float ) * nObjects * nObjects );
636 return CV_OUTOFMEM_ERR;
639 if( eigVals == NULL )
641 eigVals = (float *) cvAlloc( sizeof( float ) * nObjects );
643 if( eigVals == NULL )
651 return CV_OUTOFMEM_ERR;
656 r = icvJacobiEigens_32f( c, ev, eigVals, nObjects, 0.0f );
670 /* Eigen objects number determination */
671 if( calcLimit->type != CV_TERMCRIT_NUMBER )
673 for( i = 0; i < m1; i++ )
674 if( fabs( eigVals[i] / eigVals[0] ) < calcLimit->epsilon )
676 m1 = calcLimit->max_iter = i;
679 m1 = calcLimit->max_iter;
680 calcLimit->epsilon = (float) fabs( eigVals[m1 - 1] / eigVals[0] );
682 for( i = 0; i < m1; i++ )
683 eigVals[i] = (float) (1.0 / sqrt( (double)eigVals[i] ));
685 /* ----------------- Calculation of eigenobjects ----------------------- */
686 if( ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK )
690 nio = ioBufSize / (4 * eigSize.width); /* number of eigen objects in buffer */
691 ngr = m1 / nio; /* number of io groups */
695 for( igr = 0; igr < ngr; igr++ )
697 int io, ie, imin = igr * nio, imax = imin + nio;
702 for(int k = 0; k < eigSize.width * (imax - imin); k++ )
703 ((float *) buffer)[k] = 0.f;
705 for( io = 0; io < nObjects; io++ )
707 uchar *bu = ioFlags & CV_EIGOBJ_INPUT_CALLBACK ? buf : ((uchar **) input)[io];
709 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
711 CvCallback read_callback = ((CvInput *) & input)->callback;
713 r = (CvStatus)read_callback( io, (void *) buf, userData );
727 for( ie = imin; ie < imax; ie++ )
731 float e = ev[ie * nObjects + io] * eigVals[ie];
732 float *be = ((float *) buffer) + ((ie - imin) * eigStep);
735 for( k = 0; k < size.height; k++, bv += objStep1,
736 bf += avgStep, be += eigStep1 )
738 for( l = 0; l < size.width - 3; l += 4 )
743 be[l] += e * (v - f);
746 be[l + 1] += e * (v - f);
749 be[l + 2] += e * (v - f);
752 be[l + 3] += e * (v - f);
754 for( ; l < size.width; l++ )
755 be[l] += e * (bv[l] - bf[l]);
760 for( ie = imin; ie < imax; ie++ ) /* calculated eigen objects writting */
762 CvCallback write_callback = ((CvInput *) & output)->callback;
763 float *be = ((float *) buffer) + ((ie - imin) * eigStep);
765 r = (CvStatus)write_callback( ie, (void *) be, userData );
785 for( i = 0; i < m1; i++ ) /* e.o. annulation */
787 float *be = ((float **) output)[i];
789 for( p = 0; p < eigSize.height; p++, be += eigStep )
790 for( l = 0; l < eigSize.width; l++ )
794 for( k = 0; k < nObjects; k++ )
796 uchar *bv = (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) ? buf : ((uchar **) input)[k];
798 if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
800 CvCallback read_callback = ((CvInput *) & input)->callback;
802 r = (CvStatus)read_callback( k, (void *) buf, userData );
816 for( i = 0; i < m1; i++ )
818 float v = eigVals[i] * ev[i * nObjects + k];
819 float *be = ((float **) output)[i];
824 for( p = 0; p < size.height; p++, bu += objStep1,
825 bf += avgStep, be += eigStep1 )
827 for( l = 0; l < size.width - 3; l += 4 )
832 be[l] += v * (u - f);
835 be[l + 1] += v * (u - f);
838 be[l + 2] += v * (u - f);
841 be[l + 3] += v * (u - f);
843 for( ; l < size.width; l++ )
844 be[l] += v * (bu[l] - bf[l]);
854 for( i = 0; i < m1; i++ )
855 eigVals[i] = 1.f / (eigVals[i] * eigVals[i]);
863 /* --- End of icvCalcEigenObjects_8u32fR --- */
865 /*F///////////////////////////////////////////////////////////////////////////////////////
866 // Name: icvCalcDecompCoeff_8u32fR
867 // Purpose: The function calculates one decomposition coefficient of input object
868 // using previously calculated eigen object and the mean (averaged) object
870 // Parameters: obj - input object
871 // objStep - its step (in bytes)
872 // eigObj - pointer to eigen object
873 // eigStep - its step (in bytes)
874 // avg - pointer to averaged object
875 // avgStep - its step (in bytes)
876 // size - ROI size of each source object
878 // Returns: decomposition coefficient value or large negative value (if error)
882 static float CV_STDCALL
883 icvCalcDecompCoeff_8u32fR( uchar* obj, int objStep,
884 float *eigObj, int eigStep,
885 float *avg, int avgStep, CvSize size )
890 if( size.width > objStep || 4 * size.width > eigStep
891 || 4 * size.width > avgStep || size.height < 1 )
893 if( obj == NULL || eigObj == NULL || avg == NULL )
899 if( size.width == objStep && size.width == eigStep && size.width == avgStep )
901 size.width *= size.height;
903 objStep = eigStep = avgStep = size.width;
906 for( i = 0; i < size.height; i++, obj += objStep, eigObj += eigStep, avg += avgStep )
908 for( k = 0; k < size.width - 4; k += 4 )
910 float o = (float) obj[k];
915 o = (float) obj[k + 1];
919 o = (float) obj[k + 2];
923 o = (float) obj[k + 3];
928 for( ; k < size.width; k++ )
929 w += eigObj[k] * ((float) obj[k] - avg[k]);
935 /*F///////////////////////////////////////////////////////////////////////////////////////
936 // Names: icvEigenDecomposite_8u32fR
937 // Purpose: The function calculates all decomposition coefficients for input object
938 // using previously calculated eigen objects basis and the mean (averaged)
941 // Parameters: obj - input object
942 // objStep - its step (in bytes)
943 // nEigObjs - number of eigen objects
944 // eigInput - pointer either to array of pointers to eigen objects
945 // or to read callback function (depending on ioFlags)
946 // eigStep - eigen objects step (in bytes)
947 // ioFlags - input/output flags
948 // iserData - pointer to the structure which contains all necessary
949 // data for the callback function
950 // avg - pointer to averaged object
951 // avgStep - its step (in bytes)
952 // size - ROI size of each source object
953 // coeffs - calculated coefficients (output data)
955 // Returns: icv status
957 // Notes: see notes for icvCalcEigenObjects_8u32fR function
959 static CvStatus CV_STDCALL
960 icvEigenDecomposite_8u32fR( uchar * obj, int objStep, int nEigObjs,
961 void *eigInput, int eigStep, int ioFlags,
962 void *userData, float *avg, int avgStep,
963 CvSize size, float *coeffs )
968 return CV_BADFACTOR_ERR;
969 if( ioFlags < 0 || ioFlags > 1 )
970 return CV_BADFACTOR_ERR;
971 if( size.width > objStep || 4 * size.width > eigStep ||
972 4 * size.width > avgStep || size.height < 1 )
973 return CV_BADSIZE_ERR;
974 if( obj == NULL || eigInput == NULL || coeffs == NULL || avg == NULL )
975 return CV_NULLPTR_ERR;
977 for( i = 0; i < nEigObjs; i++ )
978 if( ((uchar **) eigInput)[i] == NULL )
979 return CV_NULLPTR_ERR;
981 if( ioFlags ) /* callback */
985 CvCallback read_callback = ((CvInput *) & eigInput)->callback;
987 eigStep = 4 * size.width;
989 /* memory allocation */
990 buffer = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
993 return CV_OUTOFMEM_ERR;
995 for( i = 0; i < nEigObjs; i++ )
998 CvStatus r = (CvStatus)read_callback( i, (void *) buffer, userData );
1005 w = icvCalcDecompCoeff_8u32fR( obj, objStep, buffer,
1006 eigStep, avg, avgStep, size );
1010 return CV_NOTDEFINED_ERR;
1019 for( i = 0; i < nEigObjs; i++ )
1021 float w = icvCalcDecompCoeff_8u32fR( obj, objStep, ((float **) eigInput)[i],
1022 eigStep, avg, avgStep, size );
1025 return CV_NOTDEFINED_ERR;
1033 /*F///////////////////////////////////////////////////////////////////////////////////////
1034 // Names: icvEigenProjection_8u32fR
1035 // Purpose: The function calculates object projection to the eigen sub-space (restores
1036 // an object) using previously calculated eigen objects basis, mean (averaged)
1037 // object and decomposition coefficients of the restored object
1039 // Parameters: nEigObjs - Number of eigen objects
1040 // eigens - Array of pointers to eigen objects
1041 // eigStep - Eigen objects step (in bytes)
1042 // coeffs - Previously calculated decomposition coefficients
1043 // avg - Pointer to averaged object
1044 // avgStep - Its step (in bytes)
1045 // rest - Pointer to restored object
1046 // restStep - Its step (in bytes)
1047 // size - ROI size of each object
1049 // Returns: CV status
1053 static CvStatus CV_STDCALL
1054 icvEigenProjection_8u32fR( int nEigObjs, void *eigInput, int eigStep,
1055 int ioFlags, void *userData, float *coeffs,
1056 float *avg, int avgStep, uchar * rest,
1057 int restStep, CvSize size )
1061 float *buffer = NULL;
1063 CvCallback read_callback = ((CvInput *) & eigInput)->callback;
1065 if( size.width > avgStep || 4 * size.width > eigStep || size.height < 1 )
1066 return CV_BADSIZE_ERR;
1067 if( rest == NULL || eigInput == NULL || avg == NULL || coeffs == NULL )
1068 return CV_NULLPTR_ERR;
1069 if( ioFlags < 0 || ioFlags > 1 )
1070 return CV_BADFACTOR_ERR;
1072 for( i = 0; i < nEigObjs; i++ )
1073 if( ((uchar **) eigInput)[i] == NULL )
1074 return CV_NULLPTR_ERR;
1078 if( size.width == restStep && size.width == eigStep && size.width == avgStep )
1080 size.width *= size.height;
1082 restStep = eigStep = avgStep = size.width;
1085 buf = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
1088 return CV_OUTOFMEM_ERR;
1090 for( i = 0; i < size.height; i++, avg += avgStep, b += size.width )
1091 for( j = 0; j < size.width; j++ )
1096 buffer = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
1098 if( buffer == NULL )
1101 return CV_OUTOFMEM_ERR;
1103 eigStep = size.width;
1106 for( k = 0; k < nEigObjs; k++ )
1108 float *e = ioFlags ? buffer : ((float **) eigInput)[k];
1109 float c = coeffs[k];
1111 if( ioFlags ) /* read eigen object */
1113 CvStatus r = (CvStatus)read_callback( k, (void *) buffer, userData );
1124 for( i = 0; i < size.height; i++, e += eigStep, b += size.width )
1126 for( j = 0; j < size.width - 3; j += 4 )
1128 float b0 = c * e[j];
1129 float b1 = c * e[j + 1];
1130 float b2 = c * e[j + 2];
1131 float b3 = c * e[j + 3];
1138 for( ; j < size.width; j++ )
1144 for( i = 0; i < size.height; i++, avg += avgStep, b += size.width, rest += restStep )
1145 for( j = 0; j < size.width; j++ )
1147 int w = cvRound( b[j] );
1149 w = !(w & ~255) ? w : w < 0 ? 0 : 255;
1150 rest[j] = (uchar) w;
1159 /*F///////////////////////////////////////////////////////////////////////////////////////
1160 // Name: cvCalcCovarMatrixEx
1161 // Purpose: The function calculates a covariance matrix for a group of input objects
1162 // (images, vectors, etc.).
1164 // Parameters: nObjects - number of source objects
1165 // input - pointer either to array of input objects
1166 // or to read callback function (depending on ioFlags)
1167 // ioFlags - input/output flags (see Notes to
1168 // cvCalcEigenObjects function)
1169 // ioBufSize - input/output buffer size
1170 // userData - pointer to the structure which contains all necessary
1171 // data for the callback functions
1172 // avg - averaged object
1173 // covarMatrix - covariance matrix (output parameter; must be allocated
1176 // Notes: See Notes to cvCalcEigenObjects function
1180 cvCalcCovarMatrixEx( int nObjects, void* input, int ioFlags,
1181 int ioBufSize, uchar* buffer, void* userData,
1182 IplImage* avg, float* covarMatrix )
1189 CV_FUNCNAME( "cvCalcCovarMatrixEx" );
1193 cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
1194 if( avg->depth != IPL_DEPTH_32F )
1195 CV_ERROR( CV_BadDepth, "Unsupported format" );
1196 if( avg->nChannels != 1 )
1197 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1199 if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
1201 IplImage **images = (IplImage **) (((CvInput *) & input)->data);
1202 uchar **objects = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects );
1203 int img_step = 0, old_step = 0;
1204 CvSize img_size = avg_size, old_size = avg_size;
1206 if( objects == NULL )
1207 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1209 for( i = 0; i < nObjects; i++ )
1211 IplImage *img = images[i];
1214 cvGetImageRawData( img, &img_data, &img_step, &img_size );
1215 if( img->depth != IPL_DEPTH_8U )
1216 CV_ERROR( CV_BadDepth, "Unsupported format" );
1217 if( img_size != avg_size || img_size != old_size )
1218 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1219 if( img->nChannels != 1 )
1220 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1221 if( i > 0 && img_step != old_step )
1222 CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1224 old_step = img_step;
1225 old_size = img_size;
1226 objects[i] = img_data;
1229 CV_CALL( icvCalcCovarMatrixEx_8u32fR( nObjects,
1232 CV_EIGOBJ_NO_CALLBACK,
1246 CV_CALL( icvCalcCovarMatrixEx_8u32fR( nObjects,
1262 /*F///////////////////////////////////////////////////////////////////////////////////////
1263 // Name: cvCalcEigenObjects
1264 // Purpose: The function calculates an orthonormal eigen basis and a mean (averaged)
1265 // object for a group of input objects (images, vectors, etc.).
1267 // Parameters: nObjects - number of source objects
1268 // input - pointer either to array of input objects
1269 // or to read callback function (depending on ioFlags)
1270 // output - pointer either to output eigen objects
1271 // or to write callback function (depending on ioFlags)
1272 // ioFlags - input/output flags (see Notes)
1273 // ioBufSize - input/output buffer size
1274 // userData - pointer to the structure which contains all necessary
1275 // data for the callback functions
1276 // calcLimit - determines the calculation finish conditions
1277 // avg - averaged object (has the same size as ROI)
1278 // eigVals - pointer to corresponding eigen values (array of <nObjects>
1279 // elements in descending order)
1281 // Notes: 1. input/output data (that is, input objects and eigen ones) may either
1282 // be allocated in the RAM or be read from/written to the HDD (or any
1283 // other device) by read/write callback functions. It depends on the
1284 // value of ioFlags paramater, which may be the following:
1285 // CV_EIGOBJ_NO_CALLBACK, or 0;
1286 // CV_EIGOBJ_INPUT_CALLBACK;
1287 // CV_EIGOBJ_OUTPUT_CALLBACK;
1288 // CV_EIGOBJ_BOTH_CALLBACK, or
1289 // CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK.
1290 // The callback functions as well as the user data structure must be
1291 // developed by the user.
1293 // 2. If ioBufSize = 0, or it's too large, the function dermines buffer size
1296 // 3. Depending on calcLimit parameter, calculations are finished either if
1297 // eigenfaces number comes up to certain value or the relation of the
1298 // current eigenvalue and the largest one comes down to certain value
1299 // (or any of the above conditions takes place). The calcLimit->type value
1300 // must be CV_TERMCRIT_NUMB, CV_TERMCRIT_EPS or
1301 // CV_TERMCRIT_NUMB | CV_TERMCRIT_EPS. The function returns the real
1302 // values calcLimit->max_iter and calcLimit->epsilon.
1304 // 4. eigVals may be equal to NULL (if you don't need eigen values in further).
1308 cvCalcEigenObjects( int nObjects,
1314 CvTermCriteria* calcLimit,
1322 int nEigens = nObjects - 1;
1324 CV_FUNCNAME( "cvCalcEigenObjects" );
1328 cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
1329 if( avg->depth != IPL_DEPTH_32F )
1330 CV_ERROR( CV_BadDepth, "Unsupported format" );
1331 if( avg->nChannels != 1 )
1332 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1334 if( nEigens > calcLimit->max_iter && calcLimit->type != CV_TERMCRIT_EPS )
1335 nEigens = calcLimit->max_iter;
1339 case CV_EIGOBJ_NO_CALLBACK:
1341 IplImage **objects = (IplImage **) (((CvInput *) & input)->data);
1342 IplImage **eigens = (IplImage **) (((CvInput *) & output)->data);
1343 uchar **objs = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects );
1344 float **eigs = (float **) cvAlloc( sizeof( float * ) * nEigens );
1345 int obj_step = 0, old_step = 0;
1346 int eig_step = 0, oldeig_step = 0;
1347 CvSize obj_size = avg_size, old_size = avg_size,
1349 eig_size = avg_size, oldeig_size = avg_size;
1351 if( objects == NULL || eigens == NULL )
1352 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1354 for( i = 0; i < nObjects; i++ )
1356 IplImage *img = objects[i];
1359 cvGetImageRawData( img, &obj_data, &obj_step, &obj_size );
1360 if( img->depth != IPL_DEPTH_8U )
1361 CV_ERROR( CV_BadDepth, "Unsupported format" );
1362 if( obj_size != avg_size || obj_size != old_size )
1363 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1364 if( img->nChannels != 1 )
1365 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1366 if( i > 0 && obj_step != old_step )
1367 CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1369 old_step = obj_step;
1370 old_size = obj_size;
1373 for( i = 0; i < nEigens; i++ )
1375 IplImage *eig = eigens[i];
1378 cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
1379 if( eig->depth != IPL_DEPTH_32F )
1380 CV_ERROR( CV_BadDepth, "Unsupported format" );
1381 if( eig_size != avg_size || eig_size != oldeig_size )
1382 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1383 if( eig->nChannels != 1 )
1384 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1385 if( i > 0 && eig_step != oldeig_step )
1386 CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1388 oldeig_step = eig_step;
1389 oldeig_size = eig_size;
1392 CV_CALL( icvCalcEigenObjects_8u32fR( nObjects, (void*) objs, obj_step,
1393 (void*) eigs, eig_step, obj_size,
1394 ioFlags, ioBufSize, userData,
1395 calcLimit, avg_data, avg_step, eigVals ));
1401 case CV_EIGOBJ_OUTPUT_CALLBACK:
1403 IplImage **objects = (IplImage **) (((CvInput *) & input)->data);
1404 uchar **objs = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects );
1405 int obj_step = 0, old_step = 0;
1406 CvSize obj_size = avg_size, old_size = avg_size;
1408 if( objects == NULL )
1409 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1411 for( i = 0; i < nObjects; i++ )
1413 IplImage *img = objects[i];
1416 cvGetImageRawData( img, &obj_data, &obj_step, &obj_size );
1417 if( img->depth != IPL_DEPTH_8U )
1418 CV_ERROR( CV_BadDepth, "Unsupported format" );
1419 if( obj_size != avg_size || obj_size != old_size )
1420 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1421 if( img->nChannels != 1 )
1422 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1423 if( i > 0 && obj_step != old_step )
1424 CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1426 old_step = obj_step;
1427 old_size = obj_size;
1430 CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
1447 case CV_EIGOBJ_INPUT_CALLBACK:
1449 IplImage **eigens = (IplImage **) (((CvInput *) & output)->data);
1450 float **eigs = (float**) cvAlloc( sizeof( float* ) * nEigens );
1451 int eig_step = 0, oldeig_step = 0;
1452 CvSize eig_size = avg_size, oldeig_size = avg_size;
1454 if( eigens == NULL )
1455 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1457 for( i = 0; i < nEigens; i++ )
1459 IplImage *eig = eigens[i];
1462 cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
1463 if( eig->depth != IPL_DEPTH_32F )
1464 CV_ERROR( CV_BadDepth, "Unsupported format" );
1465 if( eig_size != avg_size || eig_size != oldeig_size )
1466 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1467 if( eig->nChannels != 1 )
1468 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1469 if( i > 0 && eig_step != oldeig_step )
1470 CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1472 oldeig_step = eig_step;
1473 oldeig_size = eig_size;
1476 CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
1492 case CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK:
1494 CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
1510 CV_ERROR( CV_StsBadArg, "Unsupported i/o flag" );
1516 /*--------------------------------------------------------------------------------------*/
1517 /*F///////////////////////////////////////////////////////////////////////////////////////
1518 // Name: cvCalcDecompCoeff
1519 // Purpose: The function calculates one decomposition coefficient of input object
1520 // using previously calculated eigen object and the mean (averaged) object
1522 // Parameters: obj - input object
1523 // eigObj - eigen object
1524 // avg - averaged object
1526 // Returns: decomposition coefficient value or large negative value (if error)
1532 cvCalcDecompCoeff( IplImage * obj, IplImage * eigObj, IplImage * avg )
1534 double coeff = DBL_MAX;
1539 int obj_step = 0, eig_step = 0, avg_step = 0;
1540 CvSize obj_size, eig_size, avg_size;
1542 CV_FUNCNAME( "cvCalcDecompCoeff" );
1546 cvGetImageRawData( obj, &obj_data, &obj_step, &obj_size );
1547 if( obj->depth != IPL_DEPTH_8U )
1548 CV_ERROR( CV_BadDepth, "Unsupported format" );
1549 if( obj->nChannels != 1 )
1550 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1552 cvGetImageRawData( eigObj, (uchar **) & eig_data, &eig_step, &eig_size );
1553 if( eigObj->depth != IPL_DEPTH_32F )
1554 CV_ERROR( CV_BadDepth, "Unsupported format" );
1555 if( eigObj->nChannels != 1 )
1556 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1558 cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
1559 if( avg->depth != IPL_DEPTH_32F )
1560 CV_ERROR( CV_BadDepth, "Unsupported format" );
1561 if( avg->nChannels != 1 )
1562 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1564 if( obj_size != eig_size || obj_size != avg_size )
1565 CV_ERROR( CV_StsBadArg, "different sizes of images" );
1567 coeff = icvCalcDecompCoeff_8u32fR( obj_data, obj_step,
1569 avg_data, avg_step, obj_size );
1576 /*--------------------------------------------------------------------------------------*/
1577 /*F///////////////////////////////////////////////////////////////////////////////////////
1578 // Names: cvEigenDecomposite
1579 // Purpose: The function calculates all decomposition coefficients for input object
1580 // using previously calculated eigen objects basis and the mean (averaged)
1583 // Parameters: obj - input object
1584 // nEigObjs - number of eigen objects
1585 // eigInput - pointer either to array of pointers to eigen objects
1586 // or to read callback function (depending on ioFlags)
1587 // ioFlags - input/output flags
1588 // userData - pointer to the structure which contains all necessary
1589 // data for the callback function
1590 // avg - averaged object
1591 // coeffs - calculated coefficients (output data)
1593 // Notes: see notes for cvCalcEigenObjects function
1597 cvEigenDecomposite( IplImage* obj,
1607 int avg_step = 0, obj_step = 0;
1608 CvSize avg_size, obj_size;
1611 CV_FUNCNAME( "cvEigenDecomposite" );
1615 cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
1616 if( avg->depth != IPL_DEPTH_32F )
1617 CV_ERROR( CV_BadDepth, "Unsupported format" );
1618 if( avg->nChannels != 1 )
1619 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1621 cvGetImageRawData( obj, &obj_data, &obj_step, &obj_size );
1622 if( obj->depth != IPL_DEPTH_8U )
1623 CV_ERROR( CV_BadDepth, "Unsupported format" );
1624 if( obj->nChannels != 1 )
1625 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1627 if( obj_size != avg_size )
1628 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1630 if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
1632 IplImage **eigens = (IplImage **) (((CvInput *) & eigInput)->data);
1633 float **eigs = (float **) cvAlloc( sizeof( float * ) * nEigObjs );
1634 int eig_step = 0, old_step = 0;
1635 CvSize eig_size = avg_size, old_size = avg_size;
1638 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1640 for( i = 0; i < nEigObjs; i++ )
1642 IplImage *eig = eigens[i];
1645 cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
1646 if( eig->depth != IPL_DEPTH_32F )
1647 CV_ERROR( CV_BadDepth, "Unsupported format" );
1648 if( eig_size != avg_size || eig_size != old_size )
1649 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1650 if( eig->nChannels != 1 )
1651 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1652 if( i > 0 && eig_step != old_step )
1653 CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1655 old_step = eig_step;
1656 old_size = eig_size;
1660 CV_CALL( icvEigenDecomposite_8u32fR( obj_data,
1677 CV_CALL( icvEigenDecomposite_8u32fR( obj_data,
1693 /*--------------------------------------------------------------------------------------*/
1694 /*F///////////////////////////////////////////////////////////////////////////////////////
1695 // Name: cvEigenProjection
1696 // Purpose: The function calculates object projection to the eigen sub-space (restores
1697 // an object) using previously calculated eigen objects basis, mean (averaged)
1698 // object and decomposition coefficients of the restored object
1700 // Parameters: nEigObjs - number of eigen objects
1701 // eigInput - pointer either to array of pointers to eigen objects
1702 // or to read callback function (depending on ioFlags)
1703 // ioFlags - input/output flags
1704 // userData - pointer to the structure which contains all necessary
1705 // data for the callback function
1706 // coeffs - array of decomposition coefficients
1707 // avg - averaged object
1708 // proj - object projection (output data)
1710 // Notes: see notes for cvCalcEigenObjects function
1714 cvEigenProjection( void* eigInput,
1724 int avg_step = 0, proj_step = 0;
1725 CvSize avg_size, proj_size;
1728 CV_FUNCNAME( "cvEigenProjection" );
1732 cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
1733 if( avg->depth != IPL_DEPTH_32F )
1734 CV_ERROR( CV_BadDepth, "Unsupported format" );
1735 if( avg->nChannels != 1 )
1736 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1738 cvGetImageRawData( proj, &proj_data, &proj_step, &proj_size );
1739 if( proj->depth != IPL_DEPTH_8U )
1740 CV_ERROR( CV_BadDepth, "Unsupported format" );
1741 if( proj->nChannels != 1 )
1742 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1744 if( proj_size != avg_size )
1745 CV_ERROR( CV_StsBadArg, "Different sizes of projects" );
1747 if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
1749 IplImage **eigens = (IplImage**) (((CvInput *) & eigInput)->data);
1750 float **eigs = (float**) cvAlloc( sizeof( float * ) * nEigObjs );
1751 int eig_step = 0, old_step = 0;
1752 CvSize eig_size = avg_size, old_size = avg_size;
1755 CV_ERROR( CV_StsBadArg, "Insufficient memory" );
1757 for( i = 0; i < nEigObjs; i++ )
1759 IplImage *eig = eigens[i];
1762 cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
1763 if( eig->depth != IPL_DEPTH_32F )
1764 CV_ERROR( CV_BadDepth, "Unsupported format" );
1765 if( eig_size != avg_size || eig_size != old_size )
1766 CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
1767 if( eig->nChannels != 1 )
1768 CV_ERROR( CV_BadNumChannels, "Unsupported format" );
1769 if( i > 0 && eig_step != old_step )
1770 CV_ERROR( CV_StsBadArg, "Different steps of objects" );
1772 old_step = eig_step;
1773 old_size = eig_size;
1777 CV_CALL( icvEigenProjection_8u32fR( nEigObjs,
1794 CV_CALL( icvEigenProjection_8u32fR( nEigObjs,