You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
4.1 KiB

/** @file */
/* Copyright (c) 2008, Naotoshi Seo. All rights reserved.
*
* The program is free to use for non-commercial academic purposes,
* but for course works, you must understand what is going inside to
* use. The program can be used, modified, or re-distributed for any
* purposes only if you or one of your group understand not only
* programming codes but also theory and math behind (if any).
* Please contact the authors if you are interested in using the
* program without meeting the above conditions.
*/
#include "cv.h"
#include "cvaux.h"
#include <stdio.h>
#include <iostream>
#define _USE_MATH_DEFINES
#include <math.h>
#ifndef CV_PCADIST_INCLUDED
#define CV_PCADIST_INCLUDED
#ifndef NO_DOXYGEN
CVAPI(void)
cvMatPcaDist( const CvMat* samples, const CvMat* avg,
const CvMat* eigenvectors, CvMat* dists );
CV_INLINE double
cvPcaDist( const CvMat* sample, const CvMat* avg,
const CvMat* eigenvectors );
#endif
/**
* Distance between sample and PCA subspace, i.e, reconstruction error
*
* @param samples D x N sample vectors
* @param avg D x 1 mean vector
* @param eigenvectors M x D or D x M (automatically adjusted) eigen vectors
* @param dists 1 x N computed distances
*
* @see CVAPI(void) cvCalcPCA( const CvArr* data, CvArr* avg, CvArr* eigenvalues, CvArr* eigenvectors, int flags );
* @see CVAPI(void) cvProjectPCA( const CvArr* data, const CvArr* avg, const CvArr* eigenvectors, CvArr* result );
* @see CVAPI(void) cvBackProjectPCA( const CvArr* proj, const CvArr* avg,const CvArr* eigenvects, CvArr* result );
*/
CVAPI(void)
cvMatPcaDist( const CvMat* samples, const CvMat* avg,
const CvMat* eigenvectors, CvMat* dists )
{
int D = samples->rows;
int N = samples->cols;
int M = (eigenvectors->rows == D) ? eigenvectors->cols : eigenvectors->rows;
int type = samples->type;
int d, n;
CvMat *_eigenvectors; // cvProjectPCA requires M x D vec
CvMat *proj = cvCreateMat( N, M, type );
CvMat *subproj, subprojhdr;
CvMat *samples0 = cvCreateMat( D, N, type ); // mean subtracted samples
CvMat *subsamples0, subsamples0hdr;
CvMat *_proj;
CV_FUNCNAME( "cvMatPcaDist" );
__CV_BEGIN__;
CV_ASSERT( CV_IS_MAT(samples) );
CV_ASSERT( CV_IS_MAT(avg) );
CV_ASSERT( CV_IS_MAT(eigenvectors) );
CV_ASSERT( D == eigenvectors->rows || D == eigenvectors->cols );
CV_ASSERT( D == avg->rows && 1 == avg->cols );
CV_ASSERT( 1 == dists->rows && N == dists->cols );
if( D == eigenvectors->rows ) { // support transpose
_eigenvectors = cvCreateMat( M, D, type );
cvT( eigenvectors, _eigenvectors );
} else {
_eigenvectors = (CvMat*)eigenvectors;
}
//cvProjectPCA( samples, avg, _eigenvectors, proj );
for( n = 0; n < N; n++ ) { // want mean subtracted samples for laster too
for( d = 0; d < D; d++ ) {
cvmSet( samples0, d, n, cvmGet( samples, d, n ) - cvmGet( avg, d, 0 ) );
}
}
_proj = cvCreateMat( M, N, type );
cvMatMul( _eigenvectors, samples0, _proj );
cvT( _proj, proj );
cvReleaseMat( &_proj );
// distance from feature space
for( n = 0; n < N; n++ ) {
subsamples0 = cvGetCol( samples0, &subsamples0hdr, n );
subproj = cvGetRow( proj, &subprojhdr, n );
cvmSet( dists, 0, n, pow(cvNorm( subsamples0, NULL, CV_L2 ),2) - pow(cvNorm( subproj, NULL, CV_L2 ),2) );
}
cvReleaseMat( &proj );
cvReleaseMat( &samples0 );
if( D == eigenvectors->rows ) {
cvReleaseMat( &_eigenvectors );
}
__CV_END__;
}
/**
* Distance between sample and PCA subspace, i.e, reconstruction error
*
* @param sample D x 1 feature vector
* @param avg D x 1 mean vector
* @param eigenvectors M x D eigen vectors
* @return double
*/
CV_INLINE double
cvPcaDist( const CvMat* sample, const CvMat* avg, const CvMat* eigenvectors )
{
double prob;
CvMat *_dists = cvCreateMat( 1, 1, sample->type );
cvMatPcaDist( sample, avg, eigenvectors, _dists );
prob = cvmGet(_dists, 0, 0);
cvReleaseMat( &_dists );
return prob;
}
#endif