+++ /dev/null
-/*M///////////////////////////////////////////////////////////////////////////////////////
-//
-// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
-//
-// By downloading, copying, installing or using the software you agree to this license.
-// If you do not agree to this license, do not download, install,
-// copy or use the software.
-//
-//
-// Intel License Agreement
-// For Open Source Computer Vision Library
-//
-// Copyright (C) 2000, Intel Corporation, all rights reserved.
-// Third party copyrights are property of their respective owners.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-// * Redistribution's of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// * Redistribution's in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// * The name of Intel Corporation may not be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// This software is provided by the copyright holders and contributors "as is" and
-// any express or implied warranties, including, but not limited to, the implied
-// warranties of merchantability and fitness for a particular purpose are disclaimed.
-// In no event shall the Intel Corporation or contributors be liable for any direct,
-// indirect, incidental, special, exemplary, or consequential damages
-// (including, but not limited to, procurement of substitute goods or services;
-// loss of use, data, or profits; or business interruption) however caused
-// and on any theory of liability, whether in contract, strict liability,
-// or tort (including negligence or otherwise) arising in any way out of
-// the use of this software, even if advised of the possibility of such damage.
-//
-//M*/
-
-#include "_cvaux.h"
-
-CvStatus CV_STDCALL
-icvJacobiEigens_32f(float *A, float *V, float *E, int n, float eps)
-{
- int i, j, k, ind;
- float *AA = A, *VV = V;
- double Amax, anorm = 0, ax;
-
- if( A == NULL || V == NULL || E == NULL )
- return CV_NULLPTR_ERR;
- if( n <= 0 )
- return CV_BADSIZE_ERR;
- if( eps < 1.0e-7f )
- eps = 1.0e-7f;
-
- /*-------- Prepare --------*/
- for( i = 0; i < n; i++, VV += n, AA += n )
- {
- for( j = 0; j < i; j++ )
- {
- double Am = AA[j];
-
- anorm += Am * Am;
- }
- for( j = 0; j < n; j++ )
- VV[j] = 0.f;
- VV[i] = 1.f;
- }
-
- anorm = sqrt( anorm + anorm );
- ax = anorm * eps / n;
- Amax = anorm;
-
- while( Amax > ax )
- {
- Amax /= n;
- do /* while (ind) */
- {
- int p, q;
- float *V1 = V, *A1 = A;
-
- ind = 0;
- for( p = 0; p < n - 1; p++, A1 += n, V1 += n )
- {
- float *A2 = A + n * (p + 1), *V2 = V + n * (p + 1);
-
- for( q = p + 1; q < n; q++, A2 += n, V2 += n )
- {
- double x, y, c, s, c2, s2, a;
- float *A3, Apq = A1[q], App, Aqq, Aip, Aiq, Vpi, Vqi;
-
- if( fabs( Apq ) < Amax )
- continue;
-
- ind = 1;
-
- /*---- Calculation of rotation angle's sine & cosine ----*/
- App = A1[p];
- Aqq = A2[q];
- y = 5.0e-1 * (App - Aqq);
- x = -Apq / sqrt( (double)Apq * Apq + (double)y * y );
- if( y < 0.0 )
- x = -x;
- s = x / sqrt( 2.0 * (1.0 + sqrt( 1.0 - (double)x * x )));
- s2 = s * s;
- c = sqrt( 1.0 - s2 );
- c2 = c * c;
- a = 2.0 * Apq * c * s;
-
- /*---- Apq annulation ----*/
- A3 = A;
- for( i = 0; i < p; i++, A3 += n )
- {
- Aip = A3[p];
- Aiq = A3[q];
- Vpi = V1[i];
- Vqi = V2[i];
- A3[p] = (float) (Aip * c - Aiq * s);
- A3[q] = (float) (Aiq * c + Aip * s);
- V1[i] = (float) (Vpi * c - Vqi * s);
- V2[i] = (float) (Vqi * c + Vpi * s);
- }
- for( ; i < q; i++, A3 += n )
- {
- Aip = A1[i];
- Aiq = A3[q];
- Vpi = V1[i];
- Vqi = V2[i];
- A1[i] = (float) (Aip * c - Aiq * s);
- A3[q] = (float) (Aiq * c + Aip * s);
- V1[i] = (float) (Vpi * c - Vqi * s);
- V2[i] = (float) (Vqi * c + Vpi * s);
- }
- for( ; i < n; i++ )
- {
- Aip = A1[i];
- Aiq = A2[i];
- Vpi = V1[i];
- Vqi = V2[i];
- A1[i] = (float) (Aip * c - Aiq * s);
- A2[i] = (float) (Aiq * c + Aip * s);
- V1[i] = (float) (Vpi * c - Vqi * s);
- V2[i] = (float) (Vqi * c + Vpi * s);
- }
- A1[p] = (float) (App * c2 + Aqq * s2 - a);
- A2[q] = (float) (App * s2 + Aqq * c2 + a);
- A1[q] = A2[p] = 0.0f;
- } /*q */
- } /*p */
- }
- while( ind );
- Amax /= n;
- } /* while ( Amax > ax ) */
-
- for( i = 0, k = 0; i < n; i++, k += n + 1 )
- E[i] = A[k];
- /*printf(" M = %d\n", M); */
-
- /* -------- ordering -------- */
- for( i = 0; i < n; i++ )
- {
- int m = i;
- float Em = (float) fabs( E[i] );
-
- for( j = i + 1; j < n; j++ )
- {
- float Ej = (float) fabs( E[j] );
-
- m = (Em < Ej) ? j : m;
- Em = (Em < Ej) ? Ej : Em;
- }
- if( m != i )
- {
- int l;
- float b = E[i];
-
- E[i] = E[m];
- E[m] = b;
- for( j = 0, k = i * n, l = m * n; j < n; j++, k++, l++ )
- {
- b = V[k];
- V[k] = V[l];
- V[l] = b;
- }
- }
- }
-
- return CV_NO_ERR;
-}
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Name: icvCalcCovarMatrixEx_8u32fR
-// Purpose: The function calculates a covariance matrix for a group of input objects
-// (images, vectors, etc.). ROI supported.
-// Context:
-// Parameters: nObjects - number of source objects
-// objects - array of pointers to ROIs of the source objects
-// imgStep - full width of each source object row in bytes
-// avg - pointer to averaged object
-// avgStep - full width of averaged object row in bytes
-// size - ROI size of each source and averaged objects
-// covarMatrix - covariance matrix (output parameter; must be allocated
-// before call)
-//
-// Returns: CV_NO_ERR or error code
-//
-// Notes:
-//F*/
-static CvStatus CV_STDCALL
-icvCalcCovarMatrixEx_8u32fR( int nObjects, void *input, int objStep1,
- int ioFlags, int ioBufSize, uchar* buffer,
- void *userData, float *avg, int avgStep,
- CvSize size, float *covarMatrix )
-{
- int objStep = objStep1;
-
- /* ---- TEST OF PARAMETERS ---- */
-
- if( nObjects < 2 )
- return CV_BADFACTOR_ERR;
- if( ioFlags < 0 || ioFlags > 3 )
- return CV_BADFACTOR_ERR;
- if( ioFlags && ioBufSize < 1024 )
- return CV_BADFACTOR_ERR;
- if( ioFlags && buffer == NULL )
- return CV_NULLPTR_ERR;
- if( input == NULL || avg == NULL || covarMatrix == NULL )
- return CV_NULLPTR_ERR;
- if( size.width > objStep || 4 * size.width > avgStep || size.height < 1 )
- return CV_BADSIZE_ERR;
-
- avgStep /= 4;
-
- if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK ) /* ==== USE INPUT CALLBACK ==== */
- {
- int nio, ngr, igr, n = size.width * size.height, mm = 0;
- CvCallback read_callback = ((CvInput *) & input)->callback;
- uchar *buffer2;
-
- objStep = n;
- nio = ioBufSize / n; /* number of objects in buffer */
- ngr = nObjects / nio; /* number of io groups */
- if( nObjects % nio )
- mm = 1;
- ngr += mm;
-
- buffer2 = (uchar *)cvAlloc( sizeof( uchar ) * n );
- if( buffer2 == NULL )
- return CV_OUTOFMEM_ERR;
-
- for( igr = 0; igr < ngr; igr++ )
- {
- int k, l;
- int io, jo, imin = igr * nio, imax = imin + nio;
- uchar *bu1 = buffer, *bu2;
-
- if( imax > nObjects )
- imax = nObjects;
-
- /* read igr group */
- for( io = imin; io < imax; io++, bu1 += n )
- {
- CvStatus r;
-
- r = (CvStatus)read_callback( io, (void *) bu1, userData );
- if( r )
- return r;
- }
-
- /* diagonal square calc */
- bu1 = buffer;
- for( io = imin; io < imax; io++, bu1 += n )
- {
- bu2 = bu1;
- for( jo = io; jo < imax; jo++, bu2 += n )
- {
- float w = 0.f;
- float *fu = avg;
- int ij = 0;
-
- for( k = 0; k < size.height; k++, fu += avgStep )
- for( l = 0; l < size.width; l++, ij++ )
- {
- float f = fu[l], u1 = bu1[ij], u2 = bu2[ij];
-
- w += (u1 - f) * (u2 - f);
- }
- covarMatrix[io * nObjects + jo] = covarMatrix[jo * nObjects + io] = w;
- }
- }
-
- /* non-diagonal elements calc */
- for( jo = imax; jo < nObjects; jo++ )
- {
- CvStatus r;
-
- bu1 = buffer;
- bu2 = buffer2;
-
- /* read jo object */
- r = (CvStatus)read_callback( jo, (void *) bu2, userData );
- if( r )
- return r;
-
- for( io = imin; io < imax; io++, bu1 += n )
- {
- float w = 0.f;
- float *fu = avg;
- int ij = 0;
-
- for( k = 0; k < size.height; k++, fu += avgStep )
- {
- for( l = 0; l < size.width - 3; l += 4, ij += 4 )
- {
- float f = fu[l];
- uchar u1 = bu1[ij];
- uchar u2 = bu2[ij];
-
- w += (u1 - f) * (u2 - f);
- f = fu[l + 1];
- u1 = bu1[ij + 1];
- u2 = bu2[ij + 1];
- w += (u1 - f) * (u2 - f);
- f = fu[l + 2];
- u1 = bu1[ij + 2];
- u2 = bu2[ij + 2];
- w += (u1 - f) * (u2 - f);
- f = fu[l + 3];
- u1 = bu1[ij + 3];
- u2 = bu2[ij + 3];
- w += (u1 - f) * (u2 - f);
- }
- for( ; l < size.width; l++, ij++ )
- {
- float f = fu[l], u1 = bu1[ij], u2 = bu2[ij];
-
- w += (u1 - f) * (u2 - f);
- }
- }
- covarMatrix[io * nObjects + jo] = covarMatrix[jo * nObjects + io] = w;
- }
- }
- } /* igr */
-
- cvFree( &buffer2 );
- } /* if() */
-
- else
- /* ==== NOT USE INPUT CALLBACK ==== */
- {
- int i, j;
- uchar **objects = (uchar **) (((CvInput *) & input)->data);
-
- for( i = 0; i < nObjects; i++ )
- {
- uchar *bu = objects[i];
-
- for( j = i; j < nObjects; j++ )
- {
- int k, l;
- float w = 0.f;
- float *a = avg;
- uchar *bu1 = bu;
- uchar *bu2 = objects[j];
-
- for( k = 0; k < size.height;
- k++, bu1 += objStep, bu2 += objStep, a += avgStep )
- {
- for( l = 0; l < size.width - 3; l += 4 )
- {
- float f = a[l];
- uchar u1 = bu1[l];
- uchar u2 = bu2[l];
-
- w += (u1 - f) * (u2 - f);
- f = a[l + 1];
- u1 = bu1[l + 1];
- u2 = bu2[l + 1];
- w += (u1 - f) * (u2 - f);
- f = a[l + 2];
- u1 = bu1[l + 2];
- u2 = bu2[l + 2];
- w += (u1 - f) * (u2 - f);
- f = a[l + 3];
- u1 = bu1[l + 3];
- u2 = bu2[l + 3];
- w += (u1 - f) * (u2 - f);
- }
- for( ; l < size.width; l++ )
- {
- float f = a[l];
- uchar u1 = bu1[l];
- uchar u2 = bu2[l];
-
- w += (u1 - f) * (u2 - f);
- }
- }
-
- covarMatrix[i * nObjects + j] = covarMatrix[j * nObjects + i] = w;
- }
- }
- } /* else */
-
- return CV_NO_ERR;
-}
-
-/*======================== end of icvCalcCovarMatrixEx_8u32fR ===========================*/
-
-
-static int
-icvDefaultBufferSize( void )
-{
- return 10 * 1024 * 1024;
-}
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Name: icvCalcEigenObjects_8u32fR
-// Purpose: The function calculates an orthonormal eigen basis and a mean (averaged)
-// object for a group of input objects (images, vectors, etc.). ROI supported.
-// Context:
-// Parameters: nObjects - number of source objects
-// input - pointer either to array of pointers to input objects
-// or to read callback function (depending on ioFlags)
-// imgStep - full width of each source object row in bytes
-// output - pointer either to array of pointers to output eigen objects
-// or to write callback function (depending on ioFlags)
-// eigStep - full width of each eigenobject row in bytes
-// size - ROI size of each source object
-// ioFlags - input/output flags (see Notes)
-// ioBufSize - input/output buffer size
-// userData - pointer to the structure which contains all necessary
-// data for the callback functions
-// calcLimit - determines the calculation finish conditions
-// avg - pointer to averaged object (has the same size as ROI)
-// avgStep - full width of averaged object row in bytes
-// eigVals - pointer to corresponding eigenvalues (array of <nObjects>
-// elements in descending order)
-//
-// Returns: CV_NO_ERR or error code
-//
-// Notes: 1. input/output data (that is, input objects and eigen ones) may either
-// be allocated in the RAM or be read from/written to the HDD (or any
-// other device) by read/write callback functions. It depends on the
-// value of ioFlags paramater, which may be the following:
-// CV_EIGOBJ_NO_CALLBACK, or 0;
-// CV_EIGOBJ_INPUT_CALLBACK;
-// CV_EIGOBJ_OUTPUT_CALLBACK;
-// CV_EIGOBJ_BOTH_CALLBACK, or
-// CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK.
-// The callback functions as well as the user data structure must be
-// developed by the user.
-//
-// 2. If ioBufSize = 0, or it's too large, the function dermines buffer size
-// itself.
-//
-// 3. Depending on calcLimit parameter, calculations are finished either if
-// eigenfaces number comes up to certain value or the relation of the
-// current eigenvalue and the largest one comes down to certain value
-// (or any of the above conditions takes place). The calcLimit->type value
-// must be CV_TERMCRIT_NUMB, CV_TERMCRIT_EPS or
-// CV_TERMCRIT_NUMB | CV_TERMCRIT_EPS. The function returns the real
-// values calcLimit->max_iter and calcLimit->epsilon.
-//
-// 4. eigVals may be equal to NULL (if you don't need eigen values in further).
-//
-//F*/
-static CvStatus CV_STDCALL
-icvCalcEigenObjects_8u32fR( int nObjects, void* input, int objStep,
- void* output, int eigStep, CvSize size,
- int ioFlags, int ioBufSize, void* userData,
- CvTermCriteria* calcLimit, float* avg,
- int avgStep, float *eigVals )
-{
- int i, j, n, iev = 0, m1 = nObjects - 1, objStep1 = objStep, eigStep1 = eigStep / 4;
- CvSize objSize, eigSize, avgSize;
- float *c = 0;
- float *ev = 0;
- float *bf = 0;
- uchar *buf = 0;
- void *buffer = 0;
- float m = 1.0f / (float) nObjects;
- CvStatus r;
-
- if( m1 > calcLimit->max_iter && calcLimit->type != CV_TERMCRIT_EPS )
- m1 = calcLimit->max_iter;
-
- /* ---- TEST OF PARAMETERS ---- */
-
- if( nObjects < 2 )
- return CV_BADFACTOR_ERR;
- if( ioFlags < 0 || ioFlags > 3 )
- return CV_BADFACTOR_ERR;
- if( input == NULL || output == NULL || avg == NULL )
- return CV_NULLPTR_ERR;
- if( size.width > objStep || 4 * size.width > eigStep ||
- 4 * size.width > avgStep || size.height < 1 )
- return CV_BADSIZE_ERR;
- if( !(ioFlags & CV_EIGOBJ_INPUT_CALLBACK) )
- for( i = 0; i < nObjects; i++ )
- if( ((uchar **) input)[i] == NULL )
- return CV_NULLPTR_ERR;
- if( !(ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK) )
- for( i = 0; i < m1; i++ )
- if( ((float **) output)[i] == NULL )
- return CV_NULLPTR_ERR;
-
- avgStep /= 4;
- eigStep /= 4;
-
- if( objStep == size.width && eigStep == size.width && avgStep == size.width )
- {
- size.width *= size.height;
- size.height = 1;
- objStep = objStep1 = eigStep = eigStep1 = avgStep = size.width;
- }
- objSize = eigSize = avgSize = size;
-
- if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
- {
- objSize.width *= objSize.height;
- objSize.height = 1;
- objStep = objSize.width;
- objStep1 = size.width;
- }
-
- if( ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK )
- {
- eigSize.width *= eigSize.height;
- eigSize.height = 1;
- eigStep = eigSize.width;
- eigStep1 = size.width;
- }
-
- n = objSize.height * objSize.width * (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) +
- 2 * eigSize.height * eigSize.width * (ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK);
-
- /* Buffer size determination */
- if( ioFlags )
- {
- int size = icvDefaultBufferSize();
- ioBufSize = MIN( size, n );
- }
-
- /* memory allocation (if necesseay) */
-
- if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
- {
- buf = (uchar *) cvAlloc( sizeof( uchar ) * objSize.width );
- if( buf == NULL )
- return CV_OUTOFMEM_ERR;
- }
-
- if( ioFlags )
- {
- buffer = (void *) cvAlloc( ioBufSize );
- if( buffer == NULL )
- {
- if( buf )
- cvFree( &buf );
- return CV_OUTOFMEM_ERR;
- }
- }
-
- /* Calculation of averaged object */
- bf = avg;
- for( i = 0; i < avgSize.height; i++, bf += avgStep )
- for( j = 0; j < avgSize.width; j++ )
- bf[j] = 0.f;
-
- for( i = 0; i < nObjects; i++ )
- {
- int k, l;
- uchar *bu = (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) ? buf : ((uchar **) input)[i];
-
- if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
- {
- CvCallback read_callback = ((CvInput *) & input)->callback;
-
- r = (CvStatus)read_callback( i, (void *) buf, userData );
- if( r )
- {
- if( buffer )
- cvFree( &buffer );
- if( buf )
- cvFree( &buf );
- return r;
- }
- }
-
- bf = avg;
- for( k = 0; k < avgSize.height; k++, bf += avgStep, bu += objStep1 )
- for( l = 0; l < avgSize.width; l++ )
- bf[l] += bu[l];
- }
-
- bf = avg;
- for( i = 0; i < avgSize.height; i++, bf += avgStep )
- for( j = 0; j < avgSize.width; j++ )
- bf[j] *= m;
-
- /* Calculation of covariance matrix */
- c = (float *) cvAlloc( sizeof( float ) * nObjects * nObjects );
-
- if( c == NULL )
- {
- if( buffer )
- cvFree( &buffer );
- if( buf )
- cvFree( &buf );
- return CV_OUTOFMEM_ERR;
- }
-
- r = icvCalcCovarMatrixEx_8u32fR( nObjects, input, objStep1, ioFlags, ioBufSize,
- (uchar *) buffer, userData, avg, 4 * avgStep, size, c );
- if( r )
- {
- cvFree( &c );
- if( buffer )
- cvFree( &buffer );
- if( buf )
- cvFree( &buf );
- return r;
- }
-
- /* Calculation of eigenvalues & eigenvectors */
- ev = (float *) cvAlloc( sizeof( float ) * nObjects * nObjects );
-
- if( ev == NULL )
- {
- cvFree( &c );
- if( buffer )
- cvFree( &buffer );
- if( buf )
- cvFree( &buf );
- return CV_OUTOFMEM_ERR;
- }
-
- if( eigVals == NULL )
- {
- eigVals = (float *) cvAlloc( sizeof( float ) * nObjects );
-
- if( eigVals == NULL )
- {
- cvFree( &c );
- cvFree( &ev );
- if( buffer )
- cvFree( &buffer );
- if( buf )
- cvFree( &buf );
- return CV_OUTOFMEM_ERR;
- }
- iev = 1;
- }
-
- r = icvJacobiEigens_32f( c, ev, eigVals, nObjects, 0.0f );
- cvFree( &c );
- if( r )
- {
- cvFree( &ev );
- if( buffer )
- cvFree( &buffer );
- if( buf )
- cvFree( &buf );
- if( iev )
- cvFree( &eigVals );
- return r;
- }
-
- /* Eigen objects number determination */
- if( calcLimit->type != CV_TERMCRIT_NUMBER )
- {
- for( i = 0; i < m1; i++ )
- if( fabs( eigVals[i] / eigVals[0] ) < calcLimit->epsilon )
- break;
- m1 = calcLimit->max_iter = i;
- }
- else
- m1 = calcLimit->max_iter;
- calcLimit->epsilon = (float) fabs( eigVals[m1 - 1] / eigVals[0] );
-
- for( i = 0; i < m1; i++ )
- eigVals[i] = (float) (1.0 / sqrt( (double)eigVals[i] ));
-
- /* ----------------- Calculation of eigenobjects ----------------------- */
- if( ioFlags & CV_EIGOBJ_OUTPUT_CALLBACK )
- {
- int nio, ngr, igr;
-
- nio = ioBufSize / (4 * eigSize.width); /* number of eigen objects in buffer */
- ngr = m1 / nio; /* number of io groups */
- if( nObjects % nio )
- ngr += 1;
-
- for( igr = 0; igr < ngr; igr++ )
- {
- int i, io, ie, imin = igr * nio, imax = imin + nio;
-
- if( imax > m1 )
- imax = m1;
-
- for( i = 0; i < eigSize.width * (imax - imin); i++ )
- ((float *) buffer)[i] = 0.f;
-
- for( io = 0; io < nObjects; io++ )
- {
- uchar *bu = ioFlags & CV_EIGOBJ_INPUT_CALLBACK ? buf : ((uchar **) input)[io];
-
- if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
- {
- CvCallback read_callback = ((CvInput *) & input)->callback;
-
- r = (CvStatus)read_callback( io, (void *) buf, userData );
- if( r )
- {
- cvFree( &ev );
- if( iev )
- cvFree( &eigVals );
- if( buffer )
- cvFree( &buffer );
- if( buf )
- cvFree( &buf );
- return r;
- }
- }
-
- for( ie = imin; ie < imax; ie++ )
- {
- int k, l;
- uchar *bv = bu;
- float e = ev[ie * nObjects + io] * eigVals[ie];
- float *be = ((float *) buffer) + ((ie - imin) * eigStep);
-
- bf = avg;
- for( k = 0; k < size.height; k++, bv += objStep1,
- bf += avgStep, be += eigStep1 )
- {
- for( l = 0; l < size.width - 3; l += 4 )
- {
- float f = bf[l];
- uchar v = bv[l];
-
- be[l] += e * (v - f);
- f = bf[l + 1];
- v = bv[l + 1];
- be[l + 1] += e * (v - f);
- f = bf[l + 2];
- v = bv[l + 2];
- be[l + 2] += e * (v - f);
- f = bf[l + 3];
- v = bv[l + 3];
- be[l + 3] += e * (v - f);
- }
- for( ; l < size.width; l++ )
- be[l] += e * (bv[l] - bf[l]);
- }
- }
- } /* io */
-
- for( ie = imin; ie < imax; ie++ ) /* calculated eigen objects writting */
- {
- CvCallback write_callback = ((CvInput *) & output)->callback;
- float *be = ((float *) buffer) + ((ie - imin) * eigStep);
-
- r = (CvStatus)write_callback( ie, (void *) be, userData );
- if( r )
- {
- cvFree( &ev );
- if( iev )
- cvFree( &eigVals );
- if( buffer )
- cvFree( &buffer );
- if( buf )
- cvFree( &buf );
- return r;
- }
- }
- } /* igr */
- }
-
- else
- {
- int k, p, l;
-
- for( i = 0; i < m1; i++ ) /* e.o. annulation */
- {
- float *be = ((float **) output)[i];
-
- for( p = 0; p < eigSize.height; p++, be += eigStep )
- for( l = 0; l < eigSize.width; l++ )
- be[l] = 0.0f;
- }
-
- for( k = 0; k < nObjects; k++ )
- {
- uchar *bv = (ioFlags & CV_EIGOBJ_INPUT_CALLBACK) ? buf : ((uchar **) input)[k];
-
- if( ioFlags & CV_EIGOBJ_INPUT_CALLBACK )
- {
- CvCallback read_callback = ((CvInput *) & input)->callback;
-
- r = (CvStatus)read_callback( k, (void *) buf, userData );
- if( r )
- {
- cvFree( &ev );
- if( iev )
- cvFree( &eigVals );
- if( buffer )
- cvFree( &buffer );
- if( buf )
- cvFree( &buf );
- return r;
- }
- }
-
- for( i = 0; i < m1; i++ )
- {
- float v = eigVals[i] * ev[i * nObjects + k];
- float *be = ((float **) output)[i];
- uchar *bu = bv;
-
- bf = avg;
-
- for( p = 0; p < size.height; p++, bu += objStep1,
- bf += avgStep, be += eigStep1 )
- {
- for( l = 0; l < size.width - 3; l += 4 )
- {
- float f = bf[l];
- uchar u = bu[l];
-
- be[l] += v * (u - f);
- f = bf[l + 1];
- u = bu[l + 1];
- be[l + 1] += v * (u - f);
- f = bf[l + 2];
- u = bu[l + 2];
- be[l + 2] += v * (u - f);
- f = bf[l + 3];
- u = bu[l + 3];
- be[l + 3] += v * (u - f);
- }
- for( ; l < size.width; l++ )
- be[l] += v * (bu[l] - bf[l]);
- }
- } /* i */
- } /* k */
- } /* else */
-
- cvFree( &ev );
- if( iev )
- cvFree( &eigVals );
- else
- for( i = 0; i < m1; i++ )
- eigVals[i] = 1.f / (eigVals[i] * eigVals[i]);
- if( buffer )
- cvFree( &buffer );
- if( buf )
- cvFree( &buf );
- return CV_NO_ERR;
-}
-
-/* --- End of icvCalcEigenObjects_8u32fR --- */
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Name: icvCalcDecompCoeff_8u32fR
-// Purpose: The function calculates one decomposition coefficient of input object
-// using previously calculated eigen object and the mean (averaged) object
-// Context:
-// Parameters: obj - input object
-// objStep - its step (in bytes)
-// eigObj - pointer to eigen object
-// eigStep - its step (in bytes)
-// avg - pointer to averaged object
-// avgStep - its step (in bytes)
-// size - ROI size of each source object
-//
-// Returns: decomposition coefficient value or large negative value (if error)
-//
-// Notes:
-//F*/
-static float CV_STDCALL
-icvCalcDecompCoeff_8u32fR( uchar* obj, int objStep,
- float *eigObj, int eigStep,
- float *avg, int avgStep, CvSize size )
-{
- int i, k;
- float w = 0.0f;
-
- if( size.width > objStep || 4 * size.width > eigStep
- || 4 * size.width > avgStep || size.height < 1 )
- return -1.0e30f;
- if( obj == NULL || eigObj == NULL || avg == NULL )
- return -1.0e30f;
-
- eigStep /= 4;
- avgStep /= 4;
-
- if( size.width == objStep && size.width == eigStep && size.width == avgStep )
- {
- size.width *= size.height;
- size.height = 1;
- objStep = eigStep = avgStep = size.width;
- }
-
- for( i = 0; i < size.height; i++, obj += objStep, eigObj += eigStep, avg += avgStep )
- {
- for( k = 0; k < size.width - 4; k += 4 )
- {
- float o = (float) obj[k];
- float e = eigObj[k];
- float a = avg[k];
-
- w += e * (o - a);
- o = (float) obj[k + 1];
- e = eigObj[k + 1];
- a = avg[k + 1];
- w += e * (o - a);
- o = (float) obj[k + 2];
- e = eigObj[k + 2];
- a = avg[k + 2];
- w += e * (o - a);
- o = (float) obj[k + 3];
- e = eigObj[k + 3];
- a = avg[k + 3];
- w += e * (o - a);
- }
- for( ; k < size.width; k++ )
- w += eigObj[k] * ((float) obj[k] - avg[k]);
- }
-
- return w;
-}
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Names: icvEigenDecomposite_8u32fR
-// Purpose: The function calculates all decomposition coefficients for input object
-// using previously calculated eigen objects basis and the mean (averaged)
-// object
-// Context:
-// Parameters: obj - input object
-// objStep - its step (in bytes)
-// nEigObjs - number of eigen objects
-// eigInput - pointer either to array of pointers to eigen objects
-// or to read callback function (depending on ioFlags)
-// eigStep - eigen objects step (in bytes)
-// ioFlags - input/output flags
-// iserData - pointer to the structure which contains all necessary
-// data for the callback function
-// avg - pointer to averaged object
-// avgStep - its step (in bytes)
-// size - ROI size of each source object
-// coeffs - calculated coefficients (output data)
-//
-// Returns: icv status
-//
-// Notes: see notes for icvCalcEigenObjects_8u32fR function
-//F*/
-static CvStatus CV_STDCALL
-icvEigenDecomposite_8u32fR( uchar * obj, int objStep, int nEigObjs,
- void *eigInput, int eigStep, int ioFlags,
- void *userData, float *avg, int avgStep,
- CvSize size, float *coeffs )
-{
- int i;
-
- if( nEigObjs < 2 )
- return CV_BADFACTOR_ERR;
- if( ioFlags < 0 || ioFlags > 1 )
- return CV_BADFACTOR_ERR;
- if( size.width > objStep || 4 * size.width > eigStep ||
- 4 * size.width > avgStep || size.height < 1 )
- return CV_BADSIZE_ERR;
- if( obj == NULL || eigInput == NULL || coeffs == NULL || avg == NULL )
- return CV_NULLPTR_ERR;
- if( !ioFlags )
- for( i = 0; i < nEigObjs; i++ )
- if( ((uchar **) eigInput)[i] == NULL )
- return CV_NULLPTR_ERR;
-
- if( ioFlags ) /* callback */
-
- {
- float *buffer;
- CvCallback read_callback = ((CvInput *) & eigInput)->callback;
-
- eigStep = 4 * size.width;
-
- /* memory allocation */
- buffer = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
-
- if( buffer == NULL )
- return CV_OUTOFMEM_ERR;
-
- for( i = 0; i < nEigObjs; i++ )
- {
- float w;
- CvStatus r = (CvStatus)read_callback( i, (void *) buffer, userData );
-
- if( r )
- {
- cvFree( &buffer );
- return r;
- }
- w = icvCalcDecompCoeff_8u32fR( obj, objStep, buffer,
- eigStep, avg, avgStep, size );
- if( w < -1.0e29f )
- {
- cvFree( &buffer );
- return CV_NOTDEFINED_ERR;
- }
- coeffs[i] = w;
- }
- cvFree( &buffer );
- }
-
- else
- /* no callback */
- for( i = 0; i < nEigObjs; i++ )
- {
- float w = icvCalcDecompCoeff_8u32fR( obj, objStep, ((float **) eigInput)[i],
- eigStep, avg, avgStep, size );
-
- if( w < -1.0e29f )
- return CV_NOTDEFINED_ERR;
- coeffs[i] = w;
- }
-
- return CV_NO_ERR;
-}
-
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Names: icvEigenProjection_8u32fR
-// Purpose: The function calculates object projection to the eigen sub-space (restores
-// an object) using previously calculated eigen objects basis, mean (averaged)
-// object and decomposition coefficients of the restored object
-// Context:
-// Parameters: nEigObjs - Number of eigen objects
-// eigens - Array of pointers to eigen objects
-// eigStep - Eigen objects step (in bytes)
-// coeffs - Previously calculated decomposition coefficients
-// avg - Pointer to averaged object
-// avgStep - Its step (in bytes)
-// rest - Pointer to restored object
-// restStep - Its step (in bytes)
-// size - ROI size of each object
-//
-// Returns: CV status
-//
-// Notes:
-//F*/
-static CvStatus CV_STDCALL
-icvEigenProjection_8u32fR( int nEigObjs, void *eigInput, int eigStep,
- int ioFlags, void *userData, float *coeffs,
- float *avg, int avgStep, uchar * rest,
- int restStep, CvSize size )
-{
- int i, j, k;
- float *buf;
- float *buffer = NULL;
- float *b;
- CvCallback read_callback = ((CvInput *) & eigInput)->callback;
-
- if( size.width > avgStep || 4 * size.width > eigStep || size.height < 1 )
- return CV_BADSIZE_ERR;
- if( rest == NULL || eigInput == NULL || avg == NULL || coeffs == NULL )
- return CV_NULLPTR_ERR;
- if( ioFlags < 0 || ioFlags > 1 )
- return CV_BADFACTOR_ERR;
- if( !ioFlags )
- for( i = 0; i < nEigObjs; i++ )
- if( ((uchar **) eigInput)[i] == NULL )
- return CV_NULLPTR_ERR;
- eigStep /= 4;
- avgStep /= 4;
-
- if( size.width == restStep && size.width == eigStep && size.width == avgStep )
- {
- size.width *= size.height;
- size.height = 1;
- restStep = eigStep = avgStep = size.width;
- }
-
- buf = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
-
- if( buf == NULL )
- return CV_OUTOFMEM_ERR;
- b = buf;
- for( i = 0; i < size.height; i++, avg += avgStep, b += size.width )
- for( j = 0; j < size.width; j++ )
- b[j] = avg[j];
-
- if( ioFlags )
- {
- buffer = (float *) cvAlloc( sizeof( float ) * size.width * size.height );
-
- if( buffer == NULL )
- {
- cvFree( &buf );
- return CV_OUTOFMEM_ERR;
- }
- eigStep = size.width;
- }
-
- for( k = 0; k < nEigObjs; k++ )
- {
- float *e = ioFlags ? buffer : ((float **) eigInput)[k];
- float c = coeffs[k];
-
- if( ioFlags ) /* read eigen object */
- {
- CvStatus r = (CvStatus)read_callback( k, (void *) buffer, userData );
-
- if( r )
- {
- cvFree( &buf );
- cvFree( &buffer );
- return r;
- }
- }
-
- b = buf;
- for( i = 0; i < size.height; i++, e += eigStep, b += size.width )
- {
- for( j = 0; j < size.width - 3; j += 4 )
- {
- float b0 = c * e[j];
- float b1 = c * e[j + 1];
- float b2 = c * e[j + 2];
- float b3 = c * e[j + 3];
-
- b[j] += b0;
- b[j + 1] += b1;
- b[j + 2] += b2;
- b[j + 3] += b3;
- }
- for( ; j < size.width; j++ )
- b[j] += c * e[j];
- }
- }
-
- b = buf;
- for( i = 0; i < size.height; i++, avg += avgStep, b += size.width, rest += restStep )
- for( j = 0; j < size.width; j++ )
- {
- int w = cvRound( b[j] );
-
- w = !(w & ~255) ? w : w < 0 ? 0 : 255;
- rest[j] = (uchar) w;
- }
-
- cvFree( &buf );
- if( ioFlags )
- cvFree( &buffer );
- return CV_NO_ERR;
-}
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Name: cvCalcCovarMatrixEx
-// Purpose: The function calculates a covariance matrix for a group of input objects
-// (images, vectors, etc.).
-// Context:
-// Parameters: nObjects - number of source objects
-// input - pointer either to array of input objects
-// or to read callback function (depending on ioFlags)
-// ioFlags - input/output flags (see Notes to
-// cvCalcEigenObjects function)
-// ioBufSize - input/output buffer size
-// userData - pointer to the structure which contains all necessary
-// data for the callback functions
-// avg - averaged object
-// covarMatrix - covariance matrix (output parameter; must be allocated
-// before call)
-//
-// Notes: See Notes to cvCalcEigenObjects function
-//F*/
-
-CV_IMPL void
-cvCalcCovarMatrixEx( int nObjects, void* input, int ioFlags,
- int ioBufSize, uchar* buffer, void* userData,
- IplImage* avg, float* covarMatrix )
-{
- float *avg_data;
- int avg_step = 0;
- CvSize avg_size;
- int i;
-
- CV_FUNCNAME( "cvCalcCovarMatrixEx" );
-
- __BEGIN__;
-
- cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
- if( avg->depth != IPL_DEPTH_32F )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( avg->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
-
- if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
- {
- IplImage **images = (IplImage **) (((CvInput *) & input)->data);
- uchar **objects = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects );
- int img_step = 0, old_step = 0;
- CvSize img_size = avg_size, old_size = avg_size;
-
- if( objects == NULL )
- CV_ERROR( CV_StsBadArg, "Insufficient memory" );
-
- for( i = 0; i < nObjects; i++ )
- {
- IplImage *img = images[i];
- uchar *img_data;
-
- cvGetImageRawData( img, &img_data, &img_step, &img_size );
- if( img->depth != IPL_DEPTH_8U )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( img_size != avg_size || img_size != old_size )
- CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
- if( img->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
- if( i > 0 && img_step != old_step )
- CV_ERROR( CV_StsBadArg, "Different steps of objects" );
-
- old_step = img_step;
- old_size = img_size;
- objects[i] = img_data;
- }
-
- CV_CALL( icvCalcCovarMatrixEx_8u32fR( nObjects,
- (void*) objects,
- img_step,
- CV_EIGOBJ_NO_CALLBACK,
- 0,
- NULL,
- NULL,
- avg_data,
- avg_step,
- avg_size,
- covarMatrix ));
- cvFree( &objects );
- }
-
- else
-
- {
- CV_CALL( icvCalcCovarMatrixEx_8u32fR( nObjects,
- input,
- avg_step / 4,
- ioFlags,
- ioBufSize,
- buffer,
- userData,
- avg_data,
- avg_step,
- avg_size,
- covarMatrix ));
- }
-
- __END__;
-}
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Name: cvCalcEigenObjects
-// Purpose: The function calculates an orthonormal eigen basis and a mean (averaged)
-// object for a group of input objects (images, vectors, etc.).
-// Context:
-// Parameters: nObjects - number of source objects
-// input - pointer either to array of input objects
-// or to read callback function (depending on ioFlags)
-// output - pointer either to output eigen objects
-// or to write callback function (depending on ioFlags)
-// ioFlags - input/output flags (see Notes)
-// ioBufSize - input/output buffer size
-// userData - pointer to the structure which contains all necessary
-// data for the callback functions
-// calcLimit - determines the calculation finish conditions
-// avg - averaged object (has the same size as ROI)
-// eigVals - pointer to corresponding eigen values (array of <nObjects>
-// elements in descending order)
-//
-// Notes: 1. input/output data (that is, input objects and eigen ones) may either
-// be allocated in the RAM or be read from/written to the HDD (or any
-// other device) by read/write callback functions. It depends on the
-// value of ioFlags paramater, which may be the following:
-// CV_EIGOBJ_NO_CALLBACK, or 0;
-// CV_EIGOBJ_INPUT_CALLBACK;
-// CV_EIGOBJ_OUTPUT_CALLBACK;
-// CV_EIGOBJ_BOTH_CALLBACK, or
-// CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK.
-// The callback functions as well as the user data structure must be
-// developed by the user.
-//
-// 2. If ioBufSize = 0, or it's too large, the function dermines buffer size
-// itself.
-//
-// 3. Depending on calcLimit parameter, calculations are finished either if
-// eigenfaces number comes up to certain value or the relation of the
-// current eigenvalue and the largest one comes down to certain value
-// (or any of the above conditions takes place). The calcLimit->type value
-// must be CV_TERMCRIT_NUMB, CV_TERMCRIT_EPS or
-// CV_TERMCRIT_NUMB | CV_TERMCRIT_EPS. The function returns the real
-// values calcLimit->max_iter and calcLimit->epsilon.
-//
-// 4. eigVals may be equal to NULL (if you don't need eigen values in further).
-//
-//F*/
-CV_IMPL void
-cvCalcEigenObjects( int nObjects,
- void* input,
- void* output,
- int ioFlags,
- int ioBufSize,
- void* userData,
- CvTermCriteria* calcLimit,
- IplImage* avg,
- float* eigVals )
-{
- float *avg_data;
- int avg_step = 0;
- CvSize avg_size;
- int i;
- int nEigens = nObjects - 1;
-
- CV_FUNCNAME( "cvCalcEigenObjects" );
-
- __BEGIN__;
-
- cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
- if( avg->depth != IPL_DEPTH_32F )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( avg->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
-
- if( nEigens > calcLimit->max_iter && calcLimit->type != CV_TERMCRIT_EPS )
- nEigens = calcLimit->max_iter;
-
- switch (ioFlags)
- {
- case CV_EIGOBJ_NO_CALLBACK:
- {
- IplImage **objects = (IplImage **) (((CvInput *) & input)->data);
- IplImage **eigens = (IplImage **) (((CvInput *) & output)->data);
- uchar **objs = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects );
- float **eigs = (float **) cvAlloc( sizeof( float * ) * nEigens );
- int obj_step = 0, old_step = 0;
- int eig_step = 0, oldeig_step = 0;
- CvSize obj_size = avg_size, old_size = avg_size,
-
- eig_size = avg_size, oldeig_size = avg_size;
-
- if( objects == NULL || eigens == NULL )
- CV_ERROR( CV_StsBadArg, "Insufficient memory" );
-
- for( i = 0; i < nObjects; i++ )
- {
- IplImage *img = objects[i];
- uchar *obj_data;
-
- cvGetImageRawData( img, &obj_data, &obj_step, &obj_size );
- if( img->depth != IPL_DEPTH_8U )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( obj_size != avg_size || obj_size != old_size )
- CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
- if( img->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
- if( i > 0 && obj_step != old_step )
- CV_ERROR( CV_StsBadArg, "Different steps of objects" );
-
- old_step = obj_step;
- old_size = obj_size;
- objs[i] = obj_data;
- }
- for( i = 0; i < nEigens; i++ )
- {
- IplImage *eig = eigens[i];
- float *eig_data;
-
- cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
- if( eig->depth != IPL_DEPTH_32F )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( eig_size != avg_size || eig_size != oldeig_size )
- CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
- if( eig->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
- if( i > 0 && eig_step != oldeig_step )
- CV_ERROR( CV_StsBadArg, "Different steps of objects" );
-
- oldeig_step = eig_step;
- oldeig_size = eig_size;
- eigs[i] = eig_data;
- }
- CV_CALL( icvCalcEigenObjects_8u32fR( nObjects, (void*) objs, obj_step,
- (void*) eigs, eig_step, obj_size,
- ioFlags, ioBufSize, userData,
- calcLimit, avg_data, avg_step, eigVals ));
- cvFree( &objs );
- cvFree( &eigs );
- break;
- }
-
- case CV_EIGOBJ_OUTPUT_CALLBACK:
- {
- IplImage **objects = (IplImage **) (((CvInput *) & input)->data);
- uchar **objs = (uchar **) cvAlloc( sizeof( uchar * ) * nObjects );
- int obj_step = 0, old_step = 0;
- CvSize obj_size = avg_size, old_size = avg_size;
-
- if( objects == NULL )
- CV_ERROR( CV_StsBadArg, "Insufficient memory" );
-
- for( i = 0; i < nObjects; i++ )
- {
- IplImage *img = objects[i];
- uchar *obj_data;
-
- cvGetImageRawData( img, &obj_data, &obj_step, &obj_size );
- if( img->depth != IPL_DEPTH_8U )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( obj_size != avg_size || obj_size != old_size )
- CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
- if( img->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
- if( i > 0 && obj_step != old_step )
- CV_ERROR( CV_StsBadArg, "Different steps of objects" );
-
- old_step = obj_step;
- old_size = obj_size;
- objs[i] = obj_data;
- }
- CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
- (void*) objs,
- obj_step,
- output,
- avg_step,
- obj_size,
- ioFlags,
- ioBufSize,
- userData,
- calcLimit,
- avg_data,
- avg_step,
- eigVals ));
- cvFree( &objs );
- break;
- }
-
- case CV_EIGOBJ_INPUT_CALLBACK:
- {
- IplImage **eigens = (IplImage **) (((CvInput *) & output)->data);
- float **eigs = (float**) cvAlloc( sizeof( float* ) * nEigens );
- int eig_step = 0, oldeig_step = 0;
- CvSize eig_size = avg_size, oldeig_size = avg_size;
-
- if( eigens == NULL )
- CV_ERROR( CV_StsBadArg, "Insufficient memory" );
-
- for( i = 0; i < nEigens; i++ )
- {
- IplImage *eig = eigens[i];
- float *eig_data;
-
- cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
- if( eig->depth != IPL_DEPTH_32F )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( eig_size != avg_size || eig_size != oldeig_size )
- CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
- if( eig->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
- if( i > 0 && eig_step != oldeig_step )
- CV_ERROR( CV_StsBadArg, "Different steps of objects" );
-
- oldeig_step = eig_step;
- oldeig_size = eig_size;
- eigs[i] = eig_data;
- }
- CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
- input,
- avg_step / 4,
- (void*) eigs,
- eig_step,
- eig_size,
- ioFlags,
- ioBufSize,
- userData,
- calcLimit,
- avg_data,
- avg_step,
- eigVals ));
- cvFree( &eigs );
- break;
- }
- case CV_EIGOBJ_INPUT_CALLBACK | CV_EIGOBJ_OUTPUT_CALLBACK:
-
- CV_CALL( icvCalcEigenObjects_8u32fR( nObjects,
- input,
- avg_step / 4,
- output,
- avg_step,
- avg_size,
- ioFlags,
- ioBufSize,
- userData,
- calcLimit,
- avg_data,
- avg_step,
- eigVals ));
- break;
-
- default:
- CV_ERROR( CV_StsBadArg, "Unsupported i/o flag" );
- }
-
- __END__;
-}
-
-/*--------------------------------------------------------------------------------------*/
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Name: cvCalcDecompCoeff
-// Purpose: The function calculates one decomposition coefficient of input object
-// using previously calculated eigen object and the mean (averaged) object
-// Context:
-// Parameters: obj - input object
-// eigObj - eigen object
-// avg - averaged object
-//
-// Returns: decomposition coefficient value or large negative value (if error)
-//
-// Notes:
-//F*/
-
-CV_IMPL double
-cvCalcDecompCoeff( IplImage * obj, IplImage * eigObj, IplImage * avg )
-{
- double coeff = DBL_MAX;
-
- uchar *obj_data;
- float *eig_data;
- float *avg_data;
- int obj_step = 0, eig_step = 0, avg_step = 0;
- CvSize obj_size, eig_size, avg_size;
-
- CV_FUNCNAME( "cvCalcDecompCoeff" );
-
- __BEGIN__;
-
- cvGetImageRawData( obj, &obj_data, &obj_step, &obj_size );
- if( obj->depth != IPL_DEPTH_8U )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( obj->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
-
- cvGetImageRawData( eigObj, (uchar **) & eig_data, &eig_step, &eig_size );
- if( eigObj->depth != IPL_DEPTH_32F )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( eigObj->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
-
- cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
- if( avg->depth != IPL_DEPTH_32F )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( avg->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
-
- if( obj_size != eig_size || obj_size != avg_size )
- CV_ERROR( CV_StsBadArg, "different sizes of images" );
-
- coeff = icvCalcDecompCoeff_8u32fR( obj_data, obj_step,
- eig_data, eig_step,
- avg_data, avg_step, obj_size );
-
- __END__;
-
- return coeff;
-}
-
-/*--------------------------------------------------------------------------------------*/
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Names: cvEigenDecomposite
-// Purpose: The function calculates all decomposition coefficients for input object
-// using previously calculated eigen objects basis and the mean (averaged)
-// object
-//
-// Parameters: obj - input object
-// nEigObjs - number of eigen objects
-// eigInput - pointer either to array of pointers to eigen objects
-// or to read callback function (depending on ioFlags)
-// ioFlags - input/output flags
-// userData - pointer to the structure which contains all necessary
-// data for the callback function
-// avg - averaged object
-// coeffs - calculated coefficients (output data)
-//
-// Notes: see notes for cvCalcEigenObjects function
-//F*/
-
-CV_IMPL void
-cvEigenDecomposite( IplImage* obj,
- int nEigObjs,
- void* eigInput,
- int ioFlags,
- void* userData,
- IplImage* avg,
- float* coeffs )
-{
- float *avg_data;
- uchar *obj_data;
- int avg_step = 0, obj_step = 0;
- CvSize avg_size, obj_size;
- int i;
-
- CV_FUNCNAME( "cvEigenDecomposite" );
-
- __BEGIN__;
-
- cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
- if( avg->depth != IPL_DEPTH_32F )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( avg->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
-
- cvGetImageRawData( obj, &obj_data, &obj_step, &obj_size );
- if( obj->depth != IPL_DEPTH_8U )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( obj->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
-
- if( obj_size != avg_size )
- CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
-
- if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
- {
- IplImage **eigens = (IplImage **) (((CvInput *) & eigInput)->data);
- float **eigs = (float **) cvAlloc( sizeof( float * ) * nEigObjs );
- int eig_step = 0, old_step = 0;
- CvSize eig_size = avg_size, old_size = avg_size;
-
- if( eigs == NULL )
- CV_ERROR( CV_StsBadArg, "Insufficient memory" );
-
- for( i = 0; i < nEigObjs; i++ )
- {
- IplImage *eig = eigens[i];
- float *eig_data;
-
- cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
- if( eig->depth != IPL_DEPTH_32F )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( eig_size != avg_size || eig_size != old_size )
- CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
- if( eig->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
- if( i > 0 && eig_step != old_step )
- CV_ERROR( CV_StsBadArg, "Different steps of objects" );
-
- old_step = eig_step;
- old_size = eig_size;
- eigs[i] = eig_data;
- }
-
- CV_CALL( icvEigenDecomposite_8u32fR( obj_data,
- obj_step,
- nEigObjs,
- (void*) eigs,
- eig_step,
- ioFlags,
- userData,
- avg_data,
- avg_step,
- obj_size,
- coeffs ));
- cvFree( &eigs );
- }
-
- else
-
- {
- CV_CALL( icvEigenDecomposite_8u32fR( obj_data,
- obj_step,
- nEigObjs,
- eigInput,
- avg_step,
- ioFlags,
- userData,
- avg_data,
- avg_step,
- obj_size,
- coeffs ));
- }
-
- __END__;
-}
-
-/*--------------------------------------------------------------------------------------*/
-/*F///////////////////////////////////////////////////////////////////////////////////////
-// Name: cvEigenProjection
-// Purpose: The function calculates object projection to the eigen sub-space (restores
-// an object) using previously calculated eigen objects basis, mean (averaged)
-// object and decomposition coefficients of the restored object
-// Context:
-// Parameters: nEigObjs - number of eigen objects
-// eigInput - pointer either to array of pointers to eigen objects
-// or to read callback function (depending on ioFlags)
-// ioFlags - input/output flags
-// userData - pointer to the structure which contains all necessary
-// data for the callback function
-// coeffs - array of decomposition coefficients
-// avg - averaged object
-// proj - object projection (output data)
-//
-// Notes: see notes for cvCalcEigenObjects function
-//F*/
-
-CV_IMPL void
-cvEigenProjection( void* eigInput,
- int nEigObjs,
- int ioFlags,
- void* userData,
- float* coeffs,
- IplImage* avg,
- IplImage* proj )
-{
- float *avg_data;
- uchar *proj_data;
- int avg_step = 0, proj_step = 0;
- CvSize avg_size, proj_size;
- int i;
-
- CV_FUNCNAME( "cvEigenProjection" );
-
- __BEGIN__;
-
- cvGetImageRawData( avg, (uchar **) & avg_data, &avg_step, &avg_size );
- if( avg->depth != IPL_DEPTH_32F )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( avg->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
-
- cvGetImageRawData( proj, &proj_data, &proj_step, &proj_size );
- if( proj->depth != IPL_DEPTH_8U )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( proj->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
-
- if( proj_size != avg_size )
- CV_ERROR( CV_StsBadArg, "Different sizes of projects" );
-
- if( ioFlags == CV_EIGOBJ_NO_CALLBACK )
- {
- IplImage **eigens = (IplImage**) (((CvInput *) & eigInput)->data);
- float **eigs = (float**) cvAlloc( sizeof( float * ) * nEigObjs );
- int eig_step = 0, old_step = 0;
- CvSize eig_size = avg_size, old_size = avg_size;
-
- if( eigs == NULL )
- CV_ERROR( CV_StsBadArg, "Insufficient memory" );
-
- for( i = 0; i < nEigObjs; i++ )
- {
- IplImage *eig = eigens[i];
- float *eig_data;
-
- cvGetImageRawData( eig, (uchar **) & eig_data, &eig_step, &eig_size );
- if( eig->depth != IPL_DEPTH_32F )
- CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
- if( eig_size != avg_size || eig_size != old_size )
- CV_ERROR( CV_StsBadArg, "Different sizes of objects" );
- if( eig->nChannels != 1 )
- CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );
- if( i > 0 && eig_step != old_step )
- CV_ERROR( CV_StsBadArg, "Different steps of objects" );
-
- old_step = eig_step;
- old_size = eig_size;
- eigs[i] = eig_data;
- }
-
- CV_CALL( icvEigenProjection_8u32fR( nEigObjs,
- (void*) eigs,
- eig_step,
- ioFlags,
- userData,
- coeffs,
- avg_data,
- avg_step,
- proj_data,
- proj_step,
- avg_size ));
- cvFree( &eigs );
- }
-
- else
-
- {
- CV_CALL( icvEigenProjection_8u32fR( nEigObjs,
- eigInput,
- avg_step,
- ioFlags,
- userData,
- coeffs,
- avg_data,
- avg_step,
- proj_data,
- proj_step,
- avg_size ));
- }
-
- __END__;
-}
-
-/* End of file. */