/** @file */ /* The MIT License * * Copyright (c) 2008, Naotoshi Seo * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef CV_GAUSSPDF_INCLUDED #define CV_GAUSSPDF_INCLUDED #include "cv.h" #include "cvaux.h" #define _USE_MATH_DEFINES #include //CVAPI(void) //cvMatGaussPdf( const CvMat* samples, const CvMat* mean, const CvMat* cov, // CvMat* probs, bool normalize = false, bool logprob = false ); //CV_INLINE double //cvGaussPdf( const CvMat* sample, const CvMat* mean, const CvMat* cov, // bool normalize = false, bool logprob = false ); /** * Compute multivariate gaussian pdf for a set of sample vectors * * Example) * @code * double vs[] = { 3, 4, 5, * 3, 4, 5 }; // col vectors * double m[] = { 5, * 5 }; * double a[] = { 1, 0, * 0, 1 }; * CvMat vecs = cvMat(2, 3, CV_64FC1, vs); * CvMat mean = cvMat(2, 1, CV_64FC1, m); * CvMat cov = cvMat(2, 2, CV_64FC1, a); * CvMat *probs = cvCreateMat(1, 3, CV_64FC1); * cvMatGaussPdf( &vecs, &mean, &cov, probs, false, false); * cvMatPrint( probs ); // 0.018316 0.367879 1.000000 * cvMatGaussPdf( &vecs, &mean, &cov, probs, true, false); * cvMatPrint( probs ); // 0.002915 0.058550 0.159155 * cvMatGaussPdf( &vecs, &mean, &cov, probs, false, true); * cvMatPrint( probs ); // -4.000000 -1.000000 -0.000000 * cvMatGaussPdf( &vecs, &mean, &cov, probs, true, true); * cvMatPrint( probs ); // -5.837877 -2.837877 -1.837877 * cvReleaseMat( &probs ); * @endcode * * @param samples D x N data vectors where D is the number of * dimensions and N is the number of data * (Note: not N x D for clearness of matrix operation) * @param mean D x 1 mean vector * @param cov D x D covariance matrix * @param probs 1 x N computed probabilites * @param normalize Compute normalization term or not * @param logprob Log probability or not * @return CVAPI(void) * @see cvCalcCovarMatrix, cvAvg */ CVAPI(void) cvMatGaussPdf( const CvMat* samples, const CvMat* mean, const CvMat* cov, CvMat* probs, bool normalize CV_DEFAULT(true), bool logprob CV_DEFAULT(false) ) { int D = samples->rows; int N = samples->cols; int type = samples->type; CV_FUNCNAME( "cvMatGaussPdf" ); // error handling __CV_BEGIN__; CV_ASSERT( CV_IS_MAT(samples) ); CV_ASSERT( CV_IS_MAT(mean) ); CV_ASSERT( CV_IS_MAT(cov) ); CV_ASSERT( CV_IS_MAT(probs) ); CV_ASSERT( D == mean->rows && 1 == mean->cols ); CV_ASSERT( D == cov->rows && D == cov->cols ); CV_ASSERT( 1 == probs->rows && N == probs->cols ); CvMat *invcov = cvCreateMat( D, D, type ); cvInvert( cov, invcov, CV_SVD ); CvMat *sample = cvCreateMat( D, 1, type ); CvMat *subsample = cvCreateMat( D, 1, type ); CvMat *subsample_T = cvCreateMat( 1, D, type ); CvMat *value = cvCreateMat( 1, 1, type ); double prob; for( int n = 0; n < N; n++ ) { cvGetCol( samples, sample, n ); cvSub( sample, mean, subsample ); cvTranspose( subsample, subsample_T ); cvMatMul( subsample_T, invcov, subsample_T ); cvMatMul( subsample_T, subsample, value ); prob = -0.5 * cvmGet(value, 0, 0); if( !logprob ) prob = exp( prob ); cvmSet( probs, 0, n, prob ); } if( normalize ) { double norm = pow( 2* M_PI, D/2.0 ) * sqrt( cvDet( cov ) ); if( logprob ) cvSubS( probs, cvScalar( log( norm ) ), probs ); else cvConvertScale( probs, probs, 1.0 / norm ); } cvReleaseMat( &invcov ); cvReleaseMat( &sample ); cvReleaseMat( &subsample ); cvReleaseMat( &subsample_T ); cvReleaseMat( &value ); __CV_END__; } /** * Compute multivariate gaussian pdf * * Example) * @code * double v[] = { 3, * 3 }; * double m[] = { 5, * 5 }; * double a[] = { 1, 0, * 0, 1 }; * CvMat vec = cvMat(2, 1, CV_64FC1, v); * CvMat mean = cvMat(2, 1, CV_64FC1, m); * CvMat cov = cvMat(2, 2, CV_64FC1, a); * std::cout << cvGaussPdf( &vec, &mean, &cov, false ) << std::endl; * @endcode * * @param sample D x 1 data vector * @param mean D x 1 mean vector * @param cov D x D covariance matrix * @param normalize Compute normalization term or not * @param logprob Log probability or not * @return double probability * @see cvCalcCovarMatrix, cvAvg * @see cvMatGaussPdf */ CV_INLINE double cvGaussPdf( const CvMat* sample, const CvMat* mean, const CvMat* cov, bool normalize CV_DEFAULT(true), bool logprob CV_DEFAULT(false) ) { double prob; CvMat *_probs = cvCreateMat( 1, 1, sample->type ); cvMatGaussPdf( sample, mean, cov, _probs, normalize, logprob ); prob = cvmGet(_probs, 0, 0); cvReleaseMat( &_probs ); return prob; } #endif