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.

168 lines
5.4 KiB

/** @file */
/* The MIT License
*
* Copyright (c) 2008, Naotoshi Seo <sonots(at)sonots.com>
*
* 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_GMMPDF_INCLUDED
#define CV_GMMPDF_INCLUDED
#include "cv.h"
#include "cvaux.h"
#include <stdio.h>
#include <iostream>
#define _USE_MATH_DEFINES
#include <math.h>
#include "cvgausspdf.h"
//CVAPI(void)
//cvMatGmmPdf( const CvMat* samples, const CvMat* means, CvMat** covs,
// const CvMat* weights, CvMat* probs, bool normalize = false );
//CV_INLINE double
//cvGmmPdf( const CvMat* sample, const CvMat* means, CvMat** covs,
// const CvMat* weights, CvMat* probs = NULL, bool normalize = false );
/**
* Compute gaussian mixture pdf for a set of sample vectors
*
* Example)
* @code
* const int D = 2;
* const int N = 3;
* const int K = 2;
*
* double vs[] = { 3, 4, 5,
* 3, 4, 5 }; * col vectors
* double ms[] = { 3, 5,
* 3, 5 }; * col vectors
* double cs0[] = { 1, 0,
* 0, 1 };
* double cs1[] = { 1, 0.1,
* 0.1, 1 };
* double ws[] = { 0.5, 0.5 };
*
* CvMat vecs = cvMat(D, N, CV_64FC1, vs);
* CvMat means = cvMat(D, K, CV_64FC1, ms);
* CvMat **covs = (CvMat**)cvAlloc( K * sizeof(*covs) );
* covs[0] = &cvMat(D, D, CV_64FC1, cs0);
* covs[1] = &cvMat(D, D, CV_64FC1, cs0);
* CvMat weights = cvMat( 1, K, CV_64FC1, ws);
* CvMat *probs = cvCreateMat(K, N, CV_64FC1);
* cvMatGmmPdf( &vecs, &means, covs, &weights, probs, false);
* cvMatPrint( probs );
* cvReleaseMat( &probs );
* cvFree( &covs );
* @endcode
*
* @param samples D x N data vector (Note: not N x D for clearness of matrix operation)
* @param means D x K mean vector
* @param covs (D x D) x K covariance matrix for each cluster
* @param weights 1 x K weights
* @param probs K x N or 1 x N computed probabilites
* @param normalize Compute normalization term or not
* @see cvGaussPdf
*/
CVAPI(void)
cvMatGmmPdf( const CvMat* samples, const CvMat* means, CvMat** covs,
const CvMat* weights, CvMat* probs, bool normalize CV_DEFAULT(true) )
{
int D = samples->rows;
int N = samples->cols;
int K = means->cols;
int type = samples->type;
CV_FUNCNAME( "cvMatGmmPdf" ); // error handling
__CV_BEGIN__;
CV_ASSERT( CV_IS_MAT(samples) );
CV_ASSERT( CV_IS_MAT(means) );
for( int k = 0; k < K; k++ )
CV_ASSERT( CV_IS_MAT(covs[k]) );
CV_ASSERT( CV_IS_MAT(weights) );
CV_ASSERT( CV_IS_MAT(probs) );
CV_ASSERT( D == means->rows );
for( int k = 0; k < K; k++ )
CV_ASSERT( D == covs[k]->rows && D == covs[k]->cols ); // D x D
CV_ASSERT( 1 == weights->rows && K == weights->cols ); // 1 x K
CV_ASSERT( ( 1 == probs->rows || K == probs->rows ) && N == probs->cols ); // 1 x N or K x N
CvMat *mean = cvCreateMat( D, 1, type );
const CvMat *cov;
CvMat *_probs = cvCreateMat( 1, N, type );
cvZero( probs );
for( int k = 0; k < K; k++ )
{
cvGetCol( means, mean, k );
cov = covs[k];
cvMatGaussPdf( samples, mean, cov, _probs, normalize );
cvConvertScale( _probs, _probs, cvmGet( weights, 0, k ) );
if( 1 == probs->rows )
{
cvAdd( probs, _probs, probs );
}
else
{
for( int n = 0; n < N; n++ )
{
cvmSet( probs, k, n, cvmGet( _probs, 0, n ) );
}
}
}
cvReleaseMat( &mean );
cvReleaseMat( &_probs );
__CV_END__;
}
/**
* Compute gaussian mixture pdf
*
* @param sample D x 1 sample vector
* @param means D x K mean vector for each cluster
* @param covs (D x D) x K covariance matrix for each cluster
* @param weights 1 x K weights
* @param probs K x 1 probabilities for each cluster if want
* @param normalize use normalization term or not
* @return double prob
* @see cvMatGmmPdf
*/
CV_INLINE double
cvGmmPdf( const CvMat* sample, const CvMat* means, CvMat** covs,
const CvMat* weights, CvMat* probs CV_DEFAULT(NULL), bool normalize CV_DEFAULT(true) )
{
double prob;
CvMat* _probs;
int K = means->cols;
if( probs )
_probs = probs;
else
_probs = cvCreateMat( K, 1, sample->type );
cvMatGmmPdf( sample, means, covs, weights, _probs, normalize );
prob = cvSum( _probs ).val[0];
if( !probs )
cvReleaseMat( &probs );
return prob;
}
#endif