16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M///////////////////////////////////////////////////////////////////////////////////////
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  By downloading, copying, installing or using the software you agree to this license.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  If you do not agree to this license, do not download, install,
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  copy or use the software.
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//            Intel License Agreement
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved.
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners.
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification,
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met:
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's of source code must retain the above copyright notice,
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer.
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's in binary form must reproduce the above copyright notice,
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer in the documentation
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     and/or other materials provided with the distribution.
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * The name of Intel Corporation may not be used to endorse or promote products
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     derived from this software without specific prior written permission.
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed.
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct,
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services;
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability,
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage.
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_ml.h"
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvNormalBayesClassifier::CvNormalBayesClassifier()
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_count = var_all = 0;
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_idx = 0;
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cls_labels = 0;
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count = 0;
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum = 0;
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    productsum = 0;
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    avg = 0;
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    inv_eigen_values = 0;
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cov_rotate_mats = 0;
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    c = 0;
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    default_model_name = "my_nb";
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvNormalBayesClassifier::clear()
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cls_labels )
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( int cls = 0; cls < cls_labels->cols; cls++ )
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvReleaseMat( &count[cls] );
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvReleaseMat( &sum[cls] );
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvReleaseMat( &productsum[cls] );
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvReleaseMat( &avg[cls] );
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvReleaseMat( &inv_eigen_values[cls] );
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvReleaseMat( &cov_rotate_mats[cls] );
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &cls_labels );
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &var_idx );
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &c );
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &count );
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvNormalBayesClassifier::~CvNormalBayesClassifier()
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvNormalBayesClassifier::CvNormalBayesClassifier(
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _train_data, const CvMat* _responses,
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _var_idx, const CvMat* _sample_idx )
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_count = var_all = 0;
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_idx = 0;
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cls_labels = 0;
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count = 0;
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum = 0;
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    productsum = 0;
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    avg = 0;
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    inv_eigen_values = 0;
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cov_rotate_mats = 0;
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    c = 0;
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    default_model_name = "my_nb";
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    train( _train_data, _responses, _var_idx, _sample_idx );
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvNormalBayesClassifier::train( const CvMat* _train_data, const CvMat* _responses,
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            const CvMat* _var_idx, const CvMat* _sample_idx, bool update )
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float min_variation = FLT_EPSILON;
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool result = false;
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* responses   = 0;
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float** train_data = 0;
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* __cls_labels = 0;
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* __var_idx = 0;
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* cov = 0;
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvNormalBayesClassifier::train" );
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int cls, nsamples = 0, _var_count = 0, _var_all = 0, nclasses = 0;
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int s, c1, c2;
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int* responses_data;
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvPrepareTrainData( 0,
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _train_data, CV_ROW_SAMPLE, _responses, CV_VAR_CATEGORICAL,
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _var_idx, _sample_idx, false, &train_data,
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        &nsamples, &_var_count, &_var_all, &responses,
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        &__cls_labels, &__var_idx ));
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !update )
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const size_t mat_size = sizeof(CvMat*);
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size_t data_size;
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        clear();
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        var_idx = __var_idx;
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cls_labels = __cls_labels;
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        __var_idx = __cls_labels = 0;
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        var_count = _var_count;
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        var_all = _var_all;
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        nclasses = cls_labels->cols;
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        data_size = nclasses*6*mat_size;
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( count = (CvMat**)cvAlloc( data_size ));
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memset( count, 0, data_size );
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sum             = count      + nclasses;
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        productsum      = sum        + nclasses;
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        avg             = productsum + nclasses;
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        inv_eigen_values= avg        + nclasses;
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cov_rotate_mats = inv_eigen_values         + nclasses;
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( c = cvCreateMat( 1, nclasses, CV_64FC1 ));
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( cls = 0; cls < nclasses; cls++ )
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(count[cls]            = cvCreateMat( 1, var_count, CV_32SC1 ));
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(sum[cls]              = cvCreateMat( 1, var_count, CV_64FC1 ));
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(productsum[cls]       = cvCreateMat( var_count, var_count, CV_64FC1 ));
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(avg[cls]              = cvCreateMat( 1, var_count, CV_64FC1 ));
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(inv_eigen_values[cls] = cvCreateMat( 1, var_count, CV_64FC1 ));
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(cov_rotate_mats[cls]  = cvCreateMat( var_count, var_count, CV_64FC1 ));
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(cvZero( count[cls] ));
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(cvZero( sum[cls] ));
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(cvZero( productsum[cls] ));
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(cvZero( avg[cls] ));
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(cvZero( inv_eigen_values[cls] ));
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(cvZero( cov_rotate_mats[cls] ));
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // check that the new training data has the same dimensionality etc.
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( _var_count != var_count || _var_all != var_all || !(!_var_idx && !var_idx ||
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            _var_idx && var_idx && cvNorm(_var_idx,var_idx,CV_C) < DBL_EPSILON) )
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg,
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "The new training data is inconsistent with the original training data" );
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( cls_labels->cols != __cls_labels->cols ||
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvNorm(cls_labels, __cls_labels, CV_C) > DBL_EPSILON )
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsNotImplemented,
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "In the current implementation the new training data must have absolutely "
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "the same set of class labels as used in the original training data" );
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        nclasses = cls_labels->cols;
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    responses_data = responses->data.i;
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cov = cvCreateMat( _var_count, _var_count, CV_64FC1 ));
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* process train data (count, sum , productsum) */
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( s = 0; s < nsamples; s++ )
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cls = responses_data[s];
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* count_data = count[cls]->data.i;
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double* sum_data = sum[cls]->data.db;
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double* prod_data = productsum[cls]->data.db;
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const float* train_vec = train_data[s];
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( c1 = 0; c1 < _var_count; c1++, prod_data += _var_count )
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double val1 = train_vec[c1];
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum_data[c1] += val1;
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            count_data[c1]++;
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( c2 = c1; c2 < _var_count; c2++ )
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                prod_data[c2] += train_vec[c2]*val1;
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* calculate avg, covariance matrix, c */
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( cls = 0; cls < nclasses; cls++ )
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double det = 1;
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i, j;
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMat* w = inv_eigen_values[cls];
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* count_data = count[cls]->data.i;
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double* avg_data = avg[cls]->data.db;
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double* sum1 = sum[cls]->data.db;
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvCompleteSymm( productsum[cls], 0 );
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( j = 0; j < _var_count; j++ )
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int n = count_data[j];
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            avg_data[j] = n ? sum1[j] / n : 0.;
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        count_data = count[cls]->data.i;
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        avg_data = avg[cls]->data.db;
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sum1 = sum[cls]->data.db;
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < _var_count; i++ )
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double* avg2_data = avg[cls]->data.db;
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double* sum2 = sum[cls]->data.db;
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double* prod_data = productsum[cls]->data.db + i*_var_count;
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double* cov_data = cov->data.db + i*_var_count;
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double s1val = sum1[j];
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double avg1 = avg_data[i];
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int count = count_data[i];
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j <= i; j++ )
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double avg2 = avg2_data[j];
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double cov_val = prod_data[j] - avg1 * sum2[j] - avg2 * s1val + avg1 * avg2 * count;
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cov_val = (count > 1) ? cov_val / (count - 1) : cov_val;
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cov_data[j] = cov_val;
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvCompleteSymm( cov, 1 ));
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvSVD( cov, w, cov_rotate_mats[cls], 0, CV_SVD_U_T ));
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvMaxS( w, min_variation, w ));
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( j = 0; j < _var_count; j++ )
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            det *= w->data.db[j];
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvDiv( NULL, w, w ));
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        c->data.db[cls] = log( det );
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    result = true;
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !result || cvGetErrStatus() < 0 )
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        clear();
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &cov );
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &__cls_labels );
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &__var_idx );
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &train_data );
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennfloat CvNormalBayesClassifier::predict( const CvMat* samples, CvMat* results ) const
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float value = 0;
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* buffer = 0;
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int allocated_buffer = 0;
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvNormalBayesClassifier::predict" );
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j, k, cls = -1, _var_count, nclasses;
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double opt = FLT_MAX;
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat diff;
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int rtype = 0, rstep = 0, size;
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int* vidx = 0;
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    nclasses = cls_labels->cols;
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _var_count = avg[0]->cols;
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_MAT(samples) || CV_MAT_TYPE(samples->type) != CV_32FC1 || samples->cols != var_all )
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg,
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "The input samples must be 32f matrix with the number of columns = var_all" );
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( samples->rows > 1 && !results )
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr,
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "When the number of input samples is >1, the output vector of results must be passed" );
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( results )
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_IS_MAT(results) || CV_MAT_TYPE(results->type) != CV_32FC1 &&
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MAT_TYPE(results->type) != CV_32SC1 ||
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        results->cols != 1 && results->rows != 1 ||
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        results->cols + results->rows - 1 != samples->rows )
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "The output array must be integer or floating-point vector "
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "with the number of elements = number of rows in the input matrix" );
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        rtype = CV_MAT_TYPE(results->type);
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        rstep = CV_IS_MAT_CONT(results->type) ? 1 : results->step/CV_ELEM_SIZE(rtype);
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( var_idx )
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        vidx = var_idx->data.i;
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// allocate memory and initializing headers for calculating
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size = sizeof(double) * (nclasses + var_count);
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( size <= CV_MAX_LOCAL_SIZE )
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        buffer = cvStackAlloc( size );
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( buffer = cvAlloc( size ));
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        allocated_buffer = 1;
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    diff = cvMat( 1, var_count, CV_64FC1, buffer );
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < samples->rows; k++ )
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int ival;
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < nclasses; i++ )
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double cur = c->data.db[i];
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvMat* u = cov_rotate_mats[i];
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvMat* w = inv_eigen_values[i];
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const double* avg_data = avg[i]->data.db;
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const float* x = (const float*)(samples->data.ptr + samples->step*k);
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // cov = u w u'  -->  cov^(-1) = u w^(-1) u'
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j < _var_count; j++ )
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                diff.data.db[j] = avg_data[j] - x[vidx ? vidx[j] : j];
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL(cvGEMM( &diff, u, 1, 0, 0, &diff, CV_GEMM_B_T ));
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j < _var_count; j++ )
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double d = diff.data.db[j];
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cur += d*d*w->data.db[j];
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( cur < opt )
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cls = i;
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                opt = cur;
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            /* probability = exp( -0.5 * cur ) */
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ival = cls_labels->data.i[cls];
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( results )
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( rtype == CV_32SC1 )
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                results->data.i[k*rstep] = ival;
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                results->data.fl[k*rstep] = (float)ival;
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( k == 0 )
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            value = (float)ival;
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /*if( _probs )
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( cvConvertScale( &expo, &expo, -0.5 ));
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( cvExp( &expo, &expo ));
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( _probs->cols == 1 )
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( cvReshape( &expo, &expo, 1, nclasses ));
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( cvConvertScale( &expo, _probs, 1./cvSum( &expo ).val[0] ));
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }*/
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( allocated_buffer )
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &buffer );
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return value;
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvNormalBayesClassifier::write( CvFileStorage* fs, const char* name )
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvNormalBayesClassifier::write" );
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int nclasses, i;
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    nclasses = cls_labels->cols;
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_ML_NBAYES );
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvWriteInt( fs, "var_count", var_count ));
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvWriteInt( fs, "var_all", var_all ));
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( var_idx )
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvWrite( fs, "var_idx", var_idx ));
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvWrite( fs, "cls_labels", cls_labels ));
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, "count", CV_NODE_SEQ ));
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvWrite( fs, NULL, count[i] ));
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvEndWriteStruct( fs ));
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, "sum", CV_NODE_SEQ ));
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvWrite( fs, NULL, sum[i] ));
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvEndWriteStruct( fs ));
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, "productsum", CV_NODE_SEQ ));
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvWrite( fs, NULL, productsum[i] ));
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvEndWriteStruct( fs ));
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, "avg", CV_NODE_SEQ ));
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvWrite( fs, NULL, avg[i] ));
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvEndWriteStruct( fs ));
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, "inv_eigen_values", CV_NODE_SEQ ));
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvWrite( fs, NULL, inv_eigen_values[i] ));
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvEndWriteStruct( fs ));
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, "cov_rotate_mats", CV_NODE_SEQ ));
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvWrite( fs, NULL, cov_rotate_mats[i] ));
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvEndWriteStruct( fs ));
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvWrite( fs, "c", c ));
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvNormalBayesClassifier::read( CvFileStorage* fs, CvFileNode* root_node )
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool ok = false;
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvNormalBayesClassifier::read" );
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int nclasses, i;
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size_t data_size;
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* node;
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* seq;
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( var_count = cvReadIntByName( fs, root_node, "var_count", -1 ));
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( var_all = cvReadIntByName( fs, root_node, "var_all", -1 ));
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( var_idx = (CvMat*)cvReadByName( fs, root_node, "var_idx" ));
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cls_labels = (CvMat*)cvReadByName( fs, root_node, "cls_labels" ));
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !cls_labels )
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError, "No \"cls_labels\" in NBayes classifier" );
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cls_labels->cols < 1 )
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Number of classes is less 1" );
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( var_count <= 0 )
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError,
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "The field \"var_count\" of NBayes classifier is missing" );
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    nclasses = cls_labels->cols;
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    data_size = nclasses*6*sizeof(CvMat*);
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( count = (CvMat**)cvAlloc( data_size ));
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( count, 0, data_size );
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum = count + nclasses;
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    productsum  = sum  + nclasses;
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    avg = productsum + nclasses;
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    inv_eigen_values = avg + nclasses;
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cov_rotate_mats = inv_eigen_values + nclasses;
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( node = cvGetFileNodeByName( fs, root_node, "count" ));
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq = node->data.seq;
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_SEQ(node->tag) || seq->total != nclasses)
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadSeq( seq, &reader, 0 ));
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( count[i] = (CvMat*)cvRead( fs, (CvFileNode*)reader.ptr ));
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( node = cvGetFileNodeByName( fs, root_node, "sum" ));
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq = node->data.seq;
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_SEQ(node->tag) || seq->total != nclasses)
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadSeq( seq, &reader, 0 ));
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( sum[i] = (CvMat*)cvRead( fs, (CvFileNode*)reader.ptr ));
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( node = cvGetFileNodeByName( fs, root_node, "productsum" ));
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq = node->data.seq;
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_SEQ(node->tag) || seq->total != nclasses)
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadSeq( seq, &reader, 0 ));
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( productsum[i] = (CvMat*)cvRead( fs, (CvFileNode*)reader.ptr ));
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( node = cvGetFileNodeByName( fs, root_node, "avg" ));
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq = node->data.seq;
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_SEQ(node->tag) || seq->total != nclasses)
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadSeq( seq, &reader, 0 ));
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( avg[i] = (CvMat*)cvRead( fs, (CvFileNode*)reader.ptr ));
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( node = cvGetFileNodeByName( fs, root_node, "inv_eigen_values" ));
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq = node->data.seq;
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_SEQ(node->tag) || seq->total != nclasses)
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadSeq( seq, &reader, 0 ));
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( inv_eigen_values[i] = (CvMat*)cvRead( fs, (CvFileNode*)reader.ptr ));
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( node = cvGetFileNodeByName( fs, root_node, "cov_rotate_mats" ));
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq = node->data.seq;
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_SEQ(node->tag) || seq->total != nclasses)
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadSeq( seq, &reader, 0 ));
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nclasses; i++ )
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cov_rotate_mats[i] = (CvMat*)cvRead( fs, (CvFileNode*)reader.ptr ));
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( c = (CvMat*)cvReadByName( fs, root_node, "c" ));
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ok = true;
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !ok )
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        clear();
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
570