Update to 2.0.0 tree from current Fremantle build
[opencv] / cvaux / src / cvhmm.cpp
diff --git a/cvaux/src/cvhmm.cpp b/cvaux/src/cvhmm.cpp
deleted file mode 100644 (file)
index 65e0b2f..0000000
+++ /dev/null
@@ -1,1770 +0,0 @@
-/*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"
-
-#define LN2PI 1.837877f
-#define BIG_FLT 1.e+10f
-
-
-#define _CV_ERGODIC 1
-#define _CV_CAUSAL 2
-
-#define _CV_LAST_STATE 1
-#define _CV_BEST_STATE 2  
-
-
-//*F///////////////////////////////////////////////////////////////////////////////////////
-//    Name: _cvCreateObsInfo
-//    Purpose: The function allocates memory for CvImgObsInfo structure 
-//             and its inner stuff
-//    Context:
-//    Parameters: obs_info - addres of pointer to CvImgObsInfo structure
-//                num_hor_obs - number of horizontal observation vectors
-//                num_ver_obs - number of horizontal observation vectors
-//                obs_size - length of observation vector
-//
-//    Returns: error status
-//
-//    Notes:   
-//F*/      
-static CvStatus CV_STDCALL icvCreateObsInfo(  CvImgObsInfo** obs_info, 
-                                           CvSize num_obs, int obs_size )
-{
-    int total = num_obs.height * num_obs.width;
-    CvImgObsInfo* obs = (CvImgObsInfo*)cvAlloc( sizeof( CvImgObsInfo) );
-    
-    obs->obs_x = num_obs.width;
-    obs->obs_y = num_obs.height;
-
-    obs->obs = (float*)cvAlloc( total * obs_size * sizeof(float) );
-
-    obs->state = (int*)cvAlloc( 2 * total * sizeof(int) );
-    obs->mix = (int*)cvAlloc( total * sizeof(int) );  
-        
-    obs->obs_size = obs_size;
-
-    obs_info[0] = obs;
-    return CV_NO_ERR;
-}
-
-static CvStatus CV_STDCALL icvReleaseObsInfo( CvImgObsInfo** p_obs_info )
-{
-    CvImgObsInfo* obs_info = p_obs_info[0];
-
-    cvFree( &(obs_info->obs) );
-    cvFree( &(obs_info->mix) );
-    cvFree( &(obs_info->state) ); 
-    cvFree( &(obs_info) );
-
-    p_obs_info[0] = NULL;
-
-    return CV_NO_ERR;
-} 
-
-    
-//*F///////////////////////////////////////////////////////////////////////////////////////
-//    Name: icvCreate2DHMM
-//    Purpose: The function allocates memory for 2-dimensional embedded HMM model 
-//             and its inner stuff
-//    Context:
-//    Parameters: hmm - addres of pointer to CvEHMM structure
-//                state_number - array of hmm sizes (size of array == state_number[0]+1 )
-//                num_mix - number of gaussian mixtures in low-level HMM states 
-//                          size of array is defined by previous array values
-//                obs_size - length of observation vectors
-//
-//    Returns: error status
-//
-//    Notes: state_number[0] - number of states in external HMM.
-//           state_number[i] - number of states in embedded HMM
-//           
-//           example for face recognition: state_number = { 5 3 6 6 6 3 },
-//                                         length of num_mix array = 3+6+6+6+3 = 24//
-//
-//F*/
-static CvStatus CV_STDCALL icvCreate2DHMM( CvEHMM** this_hmm,
-                                         int* state_number, int* num_mix, int obs_size )
-{
-    int i;
-    int real_states = 0;
-
-    CvEHMMState* all_states;
-    CvEHMM* hmm;
-    int total_mix = 0;
-    float* pointers;
-
-    //compute total number of states of all level in 2d EHMM
-    for( i = 1; i <= state_number[0]; i++ )
-    {
-        real_states += state_number[i];
-    }
-
-    /* allocate memory for all hmms (from all levels) */
-    hmm = (CvEHMM*)cvAlloc( (state_number[0] + 1) * sizeof(CvEHMM) );
-    
-    /* set number of superstates */
-    hmm[0].num_states = state_number[0];
-    hmm[0].level = 1;
-        
-    /* allocate memory for all states */
-    all_states = (CvEHMMState *)cvAlloc( real_states * sizeof( CvEHMMState ) );
-
-    /* assign number of mixtures */
-    for( i = 0; i < real_states; i++ )
-    {
-        all_states[i].num_mix = num_mix[i];
-    }
-
-    /* compute size of inner of all real states */
-    for( i = 0; i < real_states; i++ )
-    {
-        total_mix += num_mix[i];
-    } 
-    /* allocate memory for states stuff */
-    pointers = (float*)cvAlloc( total_mix * (2/*for mu invvar */ * obs_size + 
-                                 2/*for weight and log_var_val*/ ) * sizeof( float) );
-    
-    /* organize memory */
-    for( i = 0; i < real_states; i++ )
-    {
-        all_states[i].mu      = pointers; pointers += num_mix[i] * obs_size;  
-        all_states[i].inv_var = pointers; pointers += num_mix[i] * obs_size;
-
-        all_states[i].log_var_val = pointers; pointers += num_mix[i];
-        all_states[i].weight      = pointers; pointers += num_mix[i];
-    }          
-    
-    /* set pointer to embedded hmm array */
-    hmm->u.ehmm = hmm + 1;
-    
-    for( i = 0; i < hmm[0].num_states; i++ )
-    {
-        hmm[i+1].u.state = all_states;
-        all_states += state_number[i+1];
-        hmm[i+1].num_states = state_number[i+1];
-    }                              
-    
-    for( i = 0; i <= state_number[0]; i++ )
-    {
-        hmm[i].transP = icvCreateMatrix_32f( hmm[i].num_states, hmm[i].num_states );
-        hmm[i].obsProb = NULL;
-        hmm[i].level = i ? 0 : 1;
-    }
-    
-    /* if all ok - return pointer */
-    *this_hmm = hmm;
-    return CV_NO_ERR;
-} 
-
-static CvStatus CV_STDCALL icvRelease2DHMM( CvEHMM** phmm )
-{
-    CvEHMM* hmm = phmm[0]; 
-    int i;
-    for( i = 0; i < hmm[0].num_states + 1; i++ )
-    {
-        icvDeleteMatrix( hmm[i].transP );
-    } 
-
-    if (hmm->obsProb != NULL)
-    {
-        int* tmp = ((int*)(hmm->obsProb)) - 3;
-        cvFree( &(tmp)  );
-    }
-
-    cvFree( &(hmm->u.ehmm->u.state->mu) );
-    cvFree( &(hmm->u.ehmm->u.state) );
-
-
-    /* free hmm structures */
-    cvFree( phmm );
-
-    phmm[0] = NULL;
-
-    return CV_NO_ERR;
-}     
-
-/* distance between 2 vectors */
-static float icvSquareDistance( CvVect32f v1, CvVect32f v2, int len )
-{
-    int i;
-    double dist0 = 0;
-    double dist1 = 0;
-
-    for( i = 0; i <= len - 4; i += 4 )
-    {
-        double t0 = v1[i] - v2[i];
-        double t1 = v1[i+1] - v2[i+1];
-        dist0 += t0*t0;
-        dist1 += t1*t1;
-
-        t0 = v1[i+2] - v2[i+2];
-        t1 = v1[i+3] - v2[i+3];
-        dist0 += t0*t0;
-        dist1 += t1*t1;
-    }
-
-    for( ; i < len; i++ )
-    {
-        double t0 = v1[i] - v2[i];
-        dist0 += t0*t0;
-    }
-
-    return (float)(dist0 + dist1);
-} 
-
-/*can be used in CHMM & DHMM */
-static CvStatus CV_STDCALL
-icvUniformImgSegm(  CvImgObsInfo* obs_info, CvEHMM* hmm )
-{
-#if 1
-    /* implementation is very bad */
-    int  i, j, counter = 0;
-    CvEHMMState* first_state;
-    float inv_x = 1.f/obs_info->obs_x;
-    float inv_y = 1.f/obs_info->obs_y;
-
-    /* check arguments */
-    if ( !obs_info || !hmm ) return CV_NULLPTR_ERR;
-
-    first_state = hmm->u.ehmm->u.state;
-            
-    for (i = 0; i < obs_info->obs_y; i++)
-    {
-        //bad line (division )
-        int superstate = (int)((i * hmm->num_states)*inv_y);/* /obs_info->obs_y; */
-        
-        int index = (int)(hmm->u.ehmm[superstate].u.state - first_state);
-
-        for (j = 0; j < obs_info->obs_x; j++, counter++)
-        {
-            int state = (int)((j * hmm->u.ehmm[superstate].num_states)* inv_x); /* / obs_info->obs_x; */
-            
-            obs_info->state[2 * counter] = superstate;
-            obs_info->state[2 * counter + 1] = state + index;
-        }
-    } 
-#else
-    //this is not ready yet
-
-    int i,j,k,m;
-    CvEHMMState* first_state = hmm->u.ehmm->u.state; 
-
-    /* check bad arguments */
-    if ( hmm->num_states > obs_info->obs_y ) return CV_BADSIZE_ERR;
-
-    //compute vertical subdivision
-    float row_per_state = (float)obs_info->obs_y / hmm->num_states;
-    float col_per_state[1024]; /* maximum 1024 superstates */
-    
-    //for every horizontal band compute subdivision
-    for( i = 0; i < hmm->num_states; i++ )
-    {
-        CvEHMM* ehmm = &(hmm->u.ehmm[i]);
-        col_per_state[i] = (float)obs_info->obs_x / ehmm->num_states;
-    }
-
-    //compute state bounds
-    int ss_bound[1024];
-    for( i = 0; i < hmm->num_states - 1; i++ )
-    {
-        ss_bound[i] = floor( row_per_state * ( i+1 ) );
-    }
-    ss_bound[hmm->num_states - 1] = obs_info->obs_y;
-
-    //work inside every superstate
-
-    int row = 0;
-
-    for( i = 0; i < hmm->num_states; i++ )
-    {
-        CvEHMM* ehmm = &(hmm->u.ehmm[i]);
-        int index = ehmm->u.state - first_state;
-
-        //calc distribution in superstate
-        int es_bound[1024];
-        for( j = 0; j < ehmm->num_states - 1; j++ )
-        {
-            es_bound[j] = floor( col_per_state[i] * ( j+1 ) );
-        }
-        es_bound[ehmm->num_states - 1] = obs_info->obs_x;
-
-        //assign states to first row of superstate
-        int col = 0;
-        for( j = 0; j < ehmm->num_states; j++ )
-        {
-            for( k = col; k < es_bound[j]; k++, col++ )
-            {
-                obs_info->state[row * obs_info->obs_x + 2 * k] = i;
-                obs_info->state[row * obs_info->obs_x + 2 * k + 1] = j + index;
-            }
-            col = es_bound[j]; 
-        }
-
-        //copy the same to other rows of superstate
-        for( m = row; m < ss_bound[i]; m++ )
-        {
-            memcpy( &(obs_info->state[m * obs_info->obs_x * 2]), 
-                    &(obs_info->state[row * obs_info->obs_x * 2]), obs_info->obs_x * 2 * sizeof(int) );
-        }
-
-        row = ss_bound[i];    
-    }   
-
-#endif
-
-    return CV_NO_ERR;
-}
-           
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-//    Name: InitMixSegm
-//    Purpose: The function implements the mixture segmentation of the states of the
-//             embedded HMM
-//    Context: used with the Viterbi training of the embedded HMM
-//             Function uses K-Means algorithm for clustering
-//
-//    Parameters:  obs_info_array - array of pointers to image observations 
-//                 num_img - length of above array
-//                 hmm - pointer to HMM structure   
-//     
-//    Returns: error status
-//
-//    Notes: 
-//F*/
-static CvStatus CV_STDCALL
-icvInitMixSegm( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm )
-{                                      
-    int  k, i, j; 
-    int* num_samples; /* number of observations in every state */
-    int* counter;     /* array of counters for every state */
-    
-    int**  a_class;   /* for every state - characteristic array */
-    
-    CvVect32f** samples; /* for every state - pointer to observation vectors */
-    int***  samples_mix;   /* for every state - array of pointers to vectors mixtures */   
-    
-    CvTermCriteria criteria = cvTermCriteria( CV_TERMCRIT_EPS|CV_TERMCRIT_ITER,
-                                              1000,    /* iter */
-                                              0.01f ); /* eps  */
-    
-    int total = 0;
-    
-    CvEHMMState* first_state = hmm->u.ehmm->u.state; 
-    
-    for( i = 0 ; i < hmm->num_states; i++ )
-    {
-        total += hmm->u.ehmm[i].num_states;
-    }                                  
-    
-    /* for every state integer is allocated - number of vectors in state */
-    num_samples = (int*)cvAlloc( total * sizeof(int) );
-    
-    /* integer counter is allocated for every state */
-    counter = (int*)cvAlloc( total * sizeof(int) );
-    
-    samples = (CvVect32f**)cvAlloc( total * sizeof(CvVect32f*) ); 
-    samples_mix = (int***)cvAlloc( total * sizeof(int**) ); 
-    
-    /* clear */
-    memset( num_samples, 0 , total*sizeof(int) );
-    memset( counter, 0 , total*sizeof(int) );
-    
-    
-    /* for every state the number of vectors which belong to it is computed (smth. like histogram) */
-    for (k = 0; k < num_img; k++)
-    {  
-        CvImgObsInfo* obs = obs_info_array[k];
-        int count = 0;
-        
-        for (i = 0; i < obs->obs_y; i++)
-        {
-            for (j = 0; j < obs->obs_x; j++, count++)
-            {
-                int state = obs->state[ 2 * count + 1];
-                num_samples[state] += 1;
-            }
-        }
-    } 
-    
-    /* for every state int* is allocated */
-    a_class = (int**)cvAlloc( total*sizeof(int*) );
-    
-    for (i = 0; i < total; i++)
-    {
-        a_class[i] = (int*)cvAlloc( num_samples[i] * sizeof(int) );
-        samples[i] = (CvVect32f*)cvAlloc( num_samples[i] * sizeof(CvVect32f) );
-        samples_mix[i] = (int**)cvAlloc( num_samples[i] * sizeof(int*) );
-    }
-    
-    /* for every state vectors which belong to state are gathered */
-    for (k = 0; k < num_img; k++)
-    {  
-        CvImgObsInfo* obs = obs_info_array[k];
-        int num_obs = ( obs->obs_x ) * ( obs->obs_y );
-        float* vector = obs->obs;
-
-        for (i = 0; i < num_obs; i++, vector+=obs->obs_size )
-        {
-            int state = obs->state[2*i+1];
-            
-            samples[state][counter[state]] = vector;
-            samples_mix[state][counter[state]] = &(obs->mix[i]);
-            counter[state]++;            
-        }
-    } 
-    
-    /* clear counters */
-    memset( counter, 0, total*sizeof(int) );
-    
-    /* do the actual clustering using the K Means algorithm */
-    for (i = 0; i < total; i++)
-    {
-        if ( first_state[i].num_mix == 1)
-        {   
-            for (k = 0; k < num_samples[i]; k++)
-            {  
-                /* all vectors belong to one mixture */
-                a_class[i][k] = 0;
-            }
-        }      
-        else if( num_samples[i] )
-        {
-            /* clusterize vectors  */
-            cvKMeans( first_state[i].num_mix, samples[i], num_samples[i], 
-                      obs_info_array[0]->obs_size, criteria, a_class[i] );
-        } 
-    }
-    
-    /* for every vector number of mixture is assigned */
-    for( i = 0; i < total; i++ )
-    {
-        for (j = 0; j < num_samples[i]; j++)
-        {
-            samples_mix[i][j][0] = a_class[i][j];
-        }
-    }
-    
-    for (i = 0; i < total; i++)
-    {
-        cvFree( &(a_class[i]) );
-        cvFree( &(samples[i]) );
-        cvFree( &(samples_mix[i]) );
-    }
-
-    cvFree( &a_class );
-    cvFree( &samples );
-    cvFree( &samples_mix );
-    cvFree( &counter );
-    cvFree( &num_samples );  
-    
-    return CV_NO_ERR;
-}
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-//    Name: ComputeUniModeGauss
-//    Purpose: The function computes the Gaussian pdf for a sample vector 
-//    Context:
-//    Parameters:  obsVeq - pointer to the sample vector
-//                 mu - pointer to the mean vector of the Gaussian pdf
-//                 var - pointer to the variance vector of the Gaussian pdf
-//                 VecSize - the size of sample vector
-//                 
-//    Returns: the pdf of the sample vector given the specified Gaussian 
-//
-//    Notes: 
-//F*/
-/*static float icvComputeUniModeGauss(CvVect32f vect, CvVect32f mu, 
-                              CvVect32f inv_var, float log_var_val, int vect_size)           
-{
-    int n; 
-    double tmp;
-    double prob;
-
-    prob = -log_var_val;
-
-    for (n = 0; n < vect_size; n++)
-    {
-        tmp = (vect[n] - mu[n]) * inv_var[n];
-        prob = prob - tmp * tmp;
-   }
-   //prob *= 0.5f;
-  
-   return (float)prob;
-}*/                        
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-//    Name: ComputeGaussMixture
-//    Purpose: The function computes the mixture Gaussian pdf of a sample vector. 
-//    Context:
-//    Parameters:  obsVeq - pointer to the sample vector
-//                 mu  - two-dimensional pointer to the mean vector of the Gaussian pdf;
-//                       the first dimension is indexed over the number of mixtures and 
-//                       the second dimension is indexed along the size of the mean vector
-//                 var - two-dimensional pointer to the variance vector of the Gaussian pdf;
-//                       the first dimension is indexed over the number of mixtures and 
-//                       the second dimension is indexed along the size of the variance vector
-//                 VecSize - the size of sample vector
-//                 weight - pointer to the wights of the Gaussian mixture
-//                 NumMix - the number of Gaussian mixtures
-//                 
-//    Returns: the pdf of the sample vector given the specified Gaussian mixture.  
-//
-//    Notes: 
-//F*/
-/* Calculate probability of observation at state in logarithmic scale*/
-/*static float
-icvComputeGaussMixture( CvVect32f vect, float* mu, 
-                        float* inv_var, float* log_var_val, 
-                        int vect_size, float* weight, int num_mix )
-{       
-    double prob, l_prob;
-    
-    prob = 0.0f; 
-
-    if (num_mix == 1)
-    {
-        return icvComputeUniModeGauss( vect, mu, inv_var, log_var_val[0], vect_size);    
-    }
-    else
-    {
-        int m;
-        for (m = 0; m < num_mix; m++)
-        {
-            if ( weight[m] > 0.0)
-            { 
-                l_prob = icvComputeUniModeGauss(vect, mu + m*vect_size, 
-                                                        inv_var + m * vect_size,
-                                                        log_var_val[m], 
-                                                        vect_size); 
-
-                prob = prob + weight[m]*exp((double)l_prob);
-            }
-        } 
-        prob = log(prob);    
-    }                        
-    return (float)prob;   
-}*/                            
-
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-//    Name: EstimateObsProb
-//    Purpose: The function computes the probability of every observation in every state 
-//    Context:
-//    Parameters:  obs_info - observations
-//                 hmm      - hmm
-//    Returns: error status  
-//
-//    Notes: 
-//F*/
-static CvStatus CV_STDCALL icvEstimateObsProb( CvImgObsInfo* obs_info, CvEHMM* hmm )
-{
-    int i, j;
-    int total_states = 0;
-
-    /* check if matrix exist and check current size
-       if not sufficient - realloc */
-    int status = 0; /* 1 - not allocated, 2 - allocated but small size, 
-                       3 - size is enough, but distribution is bad, 0 - all ok */
-
-    for( j = 0; j < hmm->num_states; j++ )
-    {
-       total_states += hmm->u.ehmm[j].num_states;
-    }
-
-    if ( hmm->obsProb == NULL ) 
-    {
-        /* allocare memory */
-        int need_size = ( obs_info->obs_x * obs_info->obs_y * total_states * sizeof(float) +
-                          obs_info->obs_y * hmm->num_states * sizeof( CvMatr32f) );
-
-        int* buffer = (int*)cvAlloc( need_size + 3 * sizeof(int) );
-        buffer[0] = need_size;
-        buffer[1] = obs_info->obs_y;
-        buffer[2] = obs_info->obs_x;
-        hmm->obsProb = (float**) (buffer + 3);
-        status = 3;
-        
-    }
-    else
-    {   
-        /* check current size */
-        int* total= (int*)(((int*)(hmm->obsProb)) - 3);
-        int need_size = ( obs_info->obs_x * obs_info->obs_y * total_states * sizeof(float) +
-                          obs_info->obs_y * hmm->num_states * sizeof( CvMatr32f/*(float*)*/ ) );
-
-        assert( sizeof(float*) == sizeof(int) );
-
-        if ( need_size > (*total) ) 
-        {
-            int* buffer = ((int*)(hmm->obsProb)) - 3;
-            cvFree( &buffer);
-            buffer = (int*)cvAlloc( need_size + 3 * sizeof(int));
-            buffer[0] = need_size;
-            buffer[1] = obs_info->obs_y;
-            buffer[2] = obs_info->obs_x;
-
-            hmm->obsProb = (float**)(buffer + 3);
-            
-            status = 3;
-        }          
-    }
-    if (!status)
-    {
-        int* obsx = ((int*)(hmm->obsProb)) - 1;
-        int* obsy = ((int*)(hmm->obsProb)) - 2;
-                
-        assert( (*obsx > 0) && (*obsy > 0) );
-
-        /* is good distribution? */
-        if ( (obs_info->obs_x > (*obsx) ) || (obs_info->obs_y > (*obsy) ) ) 
-            status = 3;        
-    }
-    
-    /* if bad status - do reallocation actions */
-    assert( (status == 0) || (status == 3) );
-
-    if ( status )
-    {
-        float** tmp = hmm->obsProb;
-        float*  tmpf;
-
-        /* distribute pointers of ehmm->obsProb */
-        for( i = 0; i < hmm->num_states; i++ )
-        {
-            hmm->u.ehmm[i].obsProb = tmp; 
-            tmp += obs_info->obs_y;
-        }
-
-        tmpf = (float*)tmp;
-
-        /* distribute pointers of ehmm->obsProb[j] */
-        for( i = 0; i < hmm->num_states; i++ )
-        {
-            CvEHMM* ehmm = &( hmm->u.ehmm[i] );
-            
-            for( j = 0; j < obs_info->obs_y; j++ )
-            {
-                ehmm->obsProb[j] = tmpf;
-                tmpf += ehmm->num_states * obs_info->obs_x;
-            }           
-        }
-    }/* end of pointer distribution */ 
-
-#if 1    
-    {
-#define MAX_BUF_SIZE  1200
-        float  local_log_mix_prob[MAX_BUF_SIZE];
-        double local_mix_prob[MAX_BUF_SIZE];
-        int    vect_size = obs_info->obs_size;
-        CvStatus res = CV_NO_ERR;
-
-        float*  log_mix_prob = local_log_mix_prob;
-        double* mix_prob = local_mix_prob;
-        
-        int  max_size = 0;
-        int  obs_x = obs_info->obs_x;
-
-        /* calculate temporary buffer size */
-        for( i = 0; i < hmm->num_states; i++ )
-        {
-            CvEHMM* ehmm = &(hmm->u.ehmm[i]);
-            CvEHMMState* state = ehmm->u.state;
-
-            int max_mix = 0;
-            for( j = 0; j < ehmm->num_states; j++ )
-            {
-                int t = state[j].num_mix;
-                if( max_mix < t ) max_mix = t;
-            }
-            max_mix *= ehmm->num_states;
-            if( max_size < max_mix ) max_size = max_mix;
-        }
-
-        max_size *= obs_x * vect_size;
-        
-        /* allocate buffer */
-        if( max_size > MAX_BUF_SIZE )
-        {
-            log_mix_prob = (float*)cvAlloc( max_size*(sizeof(float) + sizeof(double)));
-            if( !log_mix_prob ) return CV_OUTOFMEM_ERR;
-            mix_prob = (double*)(log_mix_prob + max_size);
-        }
-
-        memset( log_mix_prob, 0, max_size*sizeof(float));
-
-        /*****************computing probabilities***********************/
-        
-        /* loop through external states */
-        for( i = 0; i < hmm->num_states; i++ )
-        {
-            CvEHMM* ehmm = &(hmm->u.ehmm[i]);
-            CvEHMMState* state = ehmm->u.state;
-            
-            int max_mix = 0;
-            int n_states = ehmm->num_states;
-
-            /* determine maximal number of mixtures (again) */
-            for( j = 0; j < ehmm->num_states; j++ )
-            {
-                int t = state[j].num_mix;
-                if( max_mix < t ) max_mix = t;
-            }
-
-            /* loop through rows of the observation matrix */
-            for( j = 0; j < obs_info->obs_y; j++ )
-            {
-                int  m, n;
-                       
-                float* obs = obs_info->obs + j * obs_x * vect_size;
-                float* log_mp = max_mix > 1 ? log_mix_prob : ehmm->obsProb[j];
-                double* mp = mix_prob;
-            
-                /* several passes are done below */
-                
-                /* 1. calculate logarithms of probabilities for each mixture */
-
-                /* loop through mixtures */
-                for( m = 0; m < max_mix; m++ )
-                {
-                    /* set pointer to first observation in the line */
-                    float* vect = obs;
-
-                    /* cycles through obseravtions in the line */
-                    for( n = 0; n < obs_x; n++, vect += vect_size, log_mp += n_states )
-                    {
-                        int k, l;
-                        for( l = 0; l < n_states; l++ )
-                        {
-                            if( state[l].num_mix > m )
-                            {
-                                float* mu = state[l].mu + m*vect_size;
-                                float* inv_var = state[l].inv_var + m*vect_size;
-                                double prob = -state[l].log_var_val[m];
-                                for( k = 0; k < vect_size; k++ )
-                                {
-                                    double t = (vect[k] - mu[k])*inv_var[k];
-                                    prob -= t*t;
-                                }
-                                log_mp[l] = MAX( (float)prob, -500 );
-                            }
-                        }
-                    }
-                }
-
-                /* skip the rest if there is a single mixture */
-                if( max_mix == 1 ) continue;
-
-                /* 2. calculate exponent of log_mix_prob
-                      (i.e. probability for each mixture) */
-                cvbFastExp( log_mix_prob, mix_prob, max_mix * obs_x * n_states );
-
-                /* 3. sum all mixtures with weights */
-                /* 3a. first mixture - simply scale by weight */
-                for( n = 0; n < obs_x; n++, mp += n_states )
-                {
-                    int l;
-                    for( l = 0; l < n_states; l++ )
-                    {
-                        mp[l] *= state[l].weight[0];
-                    }
-                }
-
-                /* 3b. add other mixtures */
-                for( m = 1; m < max_mix; m++ )
-                {
-                    int ofs = -m*obs_x*n_states;
-                    for( n = 0; n < obs_x; n++, mp += n_states )
-                    {
-                        int l;
-                        for( l = 0; l < n_states; l++ )
-                        {
-                            if( m < state[l].num_mix )
-                            {
-                                mp[l + ofs] += mp[l] * state[l].weight[m];
-                            }
-                        }
-                    }
-                }
-
-                /* 4. Put logarithms of summary probabilities to the destination matrix */
-                cvbFastLog( mix_prob, ehmm->obsProb[j], obs_x * n_states );
-            }
-        }
-
-        if( log_mix_prob != local_log_mix_prob ) cvFree( &log_mix_prob );
-        return res;
-#undef MAX_BUF_SIZE
-    }
-#else
-    for( i = 0; i < hmm->num_states; i++ )
-    {
-        CvEHMM* ehmm = &(hmm->u.ehmm[i]);
-        CvEHMMState* state = ehmm->u.state;
-
-        for( j = 0; j < obs_info->obs_y; j++ )
-        {
-            int k,m;
-                       
-            int obs_index = j * obs_info->obs_x;
-
-            float* B = ehmm->obsProb[j];
-            
-            /* cycles through obs and states */
-            for( k = 0; k < obs_info->obs_x; k++ )
-            {
-                CvVect32f vect = (obs_info->obs) + (obs_index + k) * vect_size;
-                
-                float* matr_line = B + k * ehmm->num_states;
-
-                for( m = 0; m < ehmm->num_states; m++ )
-                {
-                    matr_line[m] = icvComputeGaussMixture( vect, state[m].mu, state[m].inv_var, 
-                                                             state[m].log_var_val, vect_size, state[m].weight,
-                                                             state[m].num_mix );
-                }
-            }
-        }
-    }
-#endif
-}
-
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-//    Name: EstimateTransProb
-//    Purpose: The function calculates the state and super state transition probabilities 
-//             of the model given the images, 
-//             the state segmentation and the input parameters
-//    Context:
-//    Parameters: obs_info_array - array of pointers to image observations 
-//                num_img - length of above array
-//                hmm - pointer to HMM structure                 
-//    Returns: void
-//
-//    Notes:   
-//F*/
-static CvStatus CV_STDCALL
-icvEstimateTransProb( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm )
-{
-    int  i, j, k;
-
-    CvEHMMState* first_state = hmm->u.ehmm->u.state;
-    /* as a counter we will use transP matrix */
-    
-    /* initialization */
-    
-    /* clear transP */
-    icvSetZero_32f( hmm->transP, hmm->num_states, hmm->num_states );
-    for (i = 0; i < hmm->num_states; i++ )
-    {
-        icvSetZero_32f( hmm->u.ehmm[i].transP , hmm->u.ehmm[i].num_states, hmm->u.ehmm[i].num_states );
-    }
-        
-    /* compute the counters */
-    for (i = 0; i < num_img; i++)
-    {
-        int counter = 0;
-        CvImgObsInfo* info = obs_info_array[i];
-        
-        for (j = 0; j < info->obs_y; j++)
-        {
-            for (k = 0; k < info->obs_x; k++, counter++)
-            {
-                /* compute how many transitions from state to state
-                   occured both in horizontal and vertical direction */ 
-                int superstate, state;
-                int nextsuperstate, nextstate;
-                int begin_ind;
-
-                superstate = info->state[2 * counter];
-                begin_ind = (int)(hmm->u.ehmm[superstate].u.state - first_state);
-                state = info->state[ 2 * counter + 1] - begin_ind; 
-                
-                if (j < info->obs_y - 1)
-                {
-                    int transP_size = hmm->num_states;
-                    
-                    nextsuperstate = info->state[ 2*(counter + info->obs_x) ];
-
-                    hmm->transP[superstate * transP_size + nextsuperstate] += 1;
-                }
-                
-                if (k < info->obs_x - 1)
-                {   
-                    int transP_size = hmm->u.ehmm[superstate].num_states;
-
-                    nextstate = info->state[2*(counter+1) + 1] - begin_ind;
-                    hmm->u.ehmm[superstate].transP[ state * transP_size + nextstate] += 1;
-                }
-            }
-        }
-    }
-    /* estimate superstate matrix */
-    for( i = 0; i < hmm->num_states; i++)
-    {
-        float total = 0;
-        float inv_total;
-        for( j = 0; j < hmm->num_states; j++)
-        {
-            total += hmm->transP[i * hmm->num_states + j];
-        }
-        //assert( total );
-
-        inv_total = total ? 1.f/total : 0;
-        
-        for( j = 0; j < hmm->num_states; j++)
-        {                   
-            hmm->transP[i * hmm->num_states + j] = 
-                hmm->transP[i * hmm->num_states + j] ? 
-                (float)log( hmm->transP[i * hmm->num_states + j] * inv_total ) : -BIG_FLT;
-        }
-    }
-    
-    /* estimate other matrices */
-    for( k = 0; k < hmm->num_states; k++ )
-    {
-        CvEHMM* ehmm = &(hmm->u.ehmm[k]);
-
-        for( i = 0; i < ehmm->num_states; i++)
-        {
-            float total = 0;
-            float inv_total;
-            for( j = 0; j < ehmm->num_states; j++)
-            {
-                total += ehmm->transP[i*ehmm->num_states + j];
-            }
-            //assert( total );
-            inv_total = total ? 1.f/total :  0;
-            
-            for( j = 0; j < ehmm->num_states; j++)
-            {                   
-                ehmm->transP[i * ehmm->num_states + j] = 
-                    (ehmm->transP[i * ehmm->num_states + j]) ?
-                    (float)log( ehmm->transP[i * ehmm->num_states + j] * inv_total) : -BIG_FLT ;
-            }
-        }
-    }
-    return CV_NO_ERR;
-} 
-                      
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-//    Name: MixSegmL2
-//    Purpose: The function implements the mixture segmentation of the states of the
-//             embedded HMM
-//    Context: used with the Viterbi training of the embedded HMM
-//
-//    Parameters:  
-//             obs_info_array
-//             num_img
-//             hmm
-//    Returns: void
-//
-//    Notes: 
-//F*/
-static CvStatus CV_STDCALL
-icvMixSegmL2( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm )
-{
-    int     k, i, j, m;
-       
-    CvEHMMState* state = hmm->u.ehmm[0].u.state;
-    
-    
-    for (k = 0; k < num_img; k++)
-    {   
-        int counter = 0;
-        CvImgObsInfo* info = obs_info_array[k];
-
-        for (i = 0; i < info->obs_y; i++)
-        {
-            for (j = 0; j < info->obs_x; j++, counter++)
-            {
-                int e_state = info->state[2 * counter + 1];
-                float min_dist;
-                                                
-                min_dist = icvSquareDistance((info->obs) + (counter * info->obs_size), 
-                                               state[e_state].mu, info->obs_size);
-                info->mix[counter] = 0;  
-                
-                for (m = 1; m < state[e_state].num_mix; m++)
-                {
-                    float dist=icvSquareDistance( (info->obs) + (counter * info->obs_size),
-                                                    state[e_state].mu + m * info->obs_size,
-                                                    info->obs_size);
-                    if (dist < min_dist)
-                    {
-                        min_dist = dist;
-                        /* assign mixture with smallest distance */ 
-                        info->mix[counter] = m;
-                    }
-                }
-            }
-        }
-    }
-    return CV_NO_ERR;
-} 
-
-/*
-CvStatus icvMixSegmProb(CvImgObsInfo* obs_info, int num_img, CvEHMM* hmm )
-{
-    int     k, i, j, m;
-       
-    CvEHMMState* state = hmm->ehmm[0].state_info;
-    
-    
-    for (k = 0; k < num_img; k++)
-    {   
-        int counter = 0;
-        CvImgObsInfo* info = obs_info + k;
-
-        for (i = 0; i < info->obs_y; i++)
-        {
-            for (j = 0; j < info->obs_x; j++, counter++)
-            {
-                int e_state = info->in_state[counter];
-                float max_prob;
-                                                
-                max_prob = icvComputeUniModeGauss( info->obs[counter], state[e_state].mu[0], 
-                                                    state[e_state].inv_var[0], 
-                                                    state[e_state].log_var[0],
-                                                    info->obs_size );
-                info->mix[counter] = 0;  
-                
-                for (m = 1; m < state[e_state].num_mix; m++)
-                {
-                    float prob=icvComputeUniModeGauss(info->obs[counter], state[e_state].mu[m],
-                                                       state[e_state].inv_var[m], 
-                                                       state[e_state].log_var[m],
-                                                       info->obs_size);
-                    if (prob > max_prob)
-                    {
-                        max_prob = prob;
-                        // assign mixture with greatest probability. 
-                        info->mix[counter] = m;
-                    }
-                }
-            }
-        }
-    } 
-
-    return CV_NO_ERR;
-} 
-*/
-static CvStatus CV_STDCALL
-icvViterbiSegmentation( int num_states, int /*num_obs*/, CvMatr32f transP,
-                        CvMatr32f B, int start_obs, int prob_type,
-                        int** q, int min_num_obs, int max_num_obs,
-                        float* prob )
-{
-    // memory allocation 
-    int i, j, last_obs;
-    int m_HMMType = _CV_ERGODIC; /* _CV_CAUSAL or _CV_ERGODIC */
-    
-    int m_ProbType   = prob_type; /* _CV_LAST_STATE or _CV_BEST_STATE */
-    
-    int m_minNumObs  = min_num_obs; /*??*/
-    int m_maxNumObs  = max_num_obs; /*??*/
-    
-    int m_numStates  = num_states;
-    
-    float* m_pi = (float*)cvAlloc( num_states* sizeof(float) );
-    CvMatr32f m_a = transP;
-
-    // offset brobability matrix to starting observation 
-    CvMatr32f m_b = B + start_obs * num_states;
-    //so m_xl will not be used more
-
-    //m_xl = start_obs; 
-
-    /*     if (muDur != NULL){ 
-    m_d = new int[m_numStates];
-    m_l = new double[m_numStates];
-    for (i = 0; i < m_numStates; i++){
-    m_l[i] = muDur[i]; 
-    }
-    } 
-    else{
-    m_d = NULL;
-    m_l = NULL;
-    }
-    */
-    
-    CvMatr32f m_Gamma = icvCreateMatrix_32f( num_states, m_maxNumObs );
-    int* m_csi = (int*)cvAlloc( num_states * m_maxNumObs * sizeof(int) );
-    
-    //stores maximal result for every ending observation */
-    CvVect32f   m_MaxGamma = prob;
-    
-
-//    assert( m_xl + max_num_obs <= num_obs );
-
-    /*??m_q          = new int*[m_maxNumObs - m_minNumObs];
-      ??for (i = 0; i < m_maxNumObs - m_minNumObs; i++)
-      ??     m_q[i] = new int[m_minNumObs + i + 1];
-    */
-
-    /******************************************************************/
-    /*    Viterbi initialization                                      */
-    /* set initial state probabilities, in logarithmic scale */
-    for (i = 0; i < m_numStates; i++)
-    {
-        m_pi[i] = -BIG_FLT;
-    }
-    m_pi[0] = 0.0f;
-    
-    for  (i = 0; i < num_states; i++)
-    {
-        m_Gamma[0 * num_states + i] = m_pi[i] + m_b[0 * num_states + i];
-        m_csi[0 * num_states + i] = 0;   
-    }
-    
-    /******************************************************************/
-    /*    Viterbi recursion                                           */
-    
-    if ( m_HMMType == _CV_CAUSAL ) //causal model
-    {
-        int t,j;
-        
-        for (t = 1 ; t < m_maxNumObs; t++)
-        {
-            // evaluate self-to-self transition for state 0
-            m_Gamma[t * num_states + 0] = m_Gamma[(t-1) * num_states + 0] + m_a[0];
-            m_csi[t * num_states + 0] = 0;
-            
-            for (j = 1; j < num_states; j++)
-            {  
-                float self = m_Gamma[ (t-1) * num_states + j] + m_a[ j * num_states + j];
-                float prev = m_Gamma[ (t-1) * num_states +(j-1)] + m_a[ (j-1) * num_states + j];
-                
-                if ( prev > self )
-                {
-                    m_csi[t * num_states + j] = j-1;
-                    m_Gamma[t * num_states + j] = prev;
-                }
-                else
-                {
-                    m_csi[t * num_states + j] = j;
-                    m_Gamma[t * num_states + j] = self;
-                }
-                
-                m_Gamma[t * num_states + j] = m_Gamma[t * num_states + j] + m_b[t * num_states + j];   
-            }                                                                    
-        }
-    }
-    else if ( m_HMMType == _CV_ERGODIC ) //ergodic model 
-    { 
-        int t;
-        for (t = 1 ; t < m_maxNumObs; t++)
-        {     
-            for (j = 0; j < num_states; j++)
-            {   
-                int i;
-                m_Gamma[ t*num_states + j] = m_Gamma[(t-1) * num_states + 0] + m_a[0*num_states+j];
-                m_csi[t *num_states + j] = 0;
-                
-                for (i = 1; i < num_states; i++)
-                {
-                    float currGamma = m_Gamma[(t-1) *num_states + i] + m_a[i *num_states + j];       
-                    if (currGamma > m_Gamma[t *num_states + j])
-                    { 
-                        m_Gamma[t * num_states + j] = currGamma;
-                        m_csi[t * num_states + j] = i;
-                    }
-                } 
-                m_Gamma[t *num_states + j] = m_Gamma[t *num_states + j] + m_b[t * num_states + j];
-            }             
-        }                  
-    }
-
-    for( last_obs = m_minNumObs-1, i = 0; last_obs < m_maxNumObs; last_obs++, i++ )
-    {
-        int t;
-
-        /******************************************************************/
-        /*    Viterbi termination                                         */
-    
-        if ( m_ProbType == _CV_LAST_STATE )
-        {
-            m_MaxGamma[i] = m_Gamma[last_obs * num_states + num_states - 1];
-            q[i][last_obs] = num_states - 1;
-        }
-        else if( m_ProbType == _CV_BEST_STATE )
-        {
-            int k;
-            q[i][last_obs] = 0;  
-            m_MaxGamma[i] = m_Gamma[last_obs * num_states + 0]; 
-        
-            for(k = 1; k < num_states; k++)
-            { 
-                if ( m_Gamma[last_obs * num_states + k] > m_MaxGamma[i] )
-                {
-                    m_MaxGamma[i] = m_Gamma[last_obs * num_states + k];
-                    q[i][last_obs] = k;
-                }    
-            }
-        } 
-    
-        /******************************************************************/
-        /*    Viterbi backtracking                                        */
-        for  (t = last_obs-1; t >= 0; t--)
-        {
-            q[i][t] = m_csi[(t+1) * num_states + q[i][t+1] ];   
-        } 
-    }            
-    
-    /* memory free */
-    cvFree( &m_pi );
-    cvFree( &m_csi );
-    icvDeleteMatrix( m_Gamma );   
-       
-    return CV_NO_ERR;
-} 
-
-/*F///////////////////////////////////////////////////////////////////////////////////////
-//    Name: icvEViterbi
-//    Purpose: The function calculates the embedded Viterbi algorithm
-//             for 1 image 
-//    Context:
-//    Parameters:  
-//             obs_info - observations
-//             hmm      - HMM
-//                
-//    Returns: the Embedded Viterbi probability (float) 
-//             and do state segmentation of observations
-//
-//    Notes: 
-//F*/
-static float CV_STDCALL icvEViterbi( CvImgObsInfo* obs_info, CvEHMM* hmm )
-{
-    int    i, j, counter;
-    float  log_likelihood;
-
-    float inv_obs_x = 1.f / obs_info->obs_x;
-
-    CvEHMMState* first_state = hmm->u.ehmm->u.state;
-    
-    /* memory allocation for superB */
-    CvMatr32f superB = icvCreateMatrix_32f(hmm->num_states, obs_info->obs_y );
-    
-    /* memory allocation for q */
-    int*** q = (int***)cvAlloc( hmm->num_states * sizeof(int**) );
-    int* super_q = (int*)cvAlloc( obs_info->obs_y * sizeof(int) );
-    
-    for (i = 0; i < hmm->num_states; i++)
-    {
-        q[i] = (int**)cvAlloc( obs_info->obs_y * sizeof(int*) );
-        
-        for (j = 0; j < obs_info->obs_y ; j++)
-        {
-            q[i][j] = (int*)cvAlloc( obs_info->obs_x * sizeof(int) );
-        }
-    }             
-    
-    /* start Viterbi segmentation */
-    for (i = 0; i < hmm->num_states; i++)
-    {
-        CvEHMM* ehmm = &(hmm->u.ehmm[i]);
-        
-        for (j = 0; j < obs_info->obs_y; j++)
-        {
-            float max_gamma;
-            
-            /* 1D HMM Viterbi segmentation */
-            icvViterbiSegmentation( ehmm->num_states, obs_info->obs_x, 
-                ehmm->transP, ehmm->obsProb[j], 0, 
-                _CV_LAST_STATE, &q[i][j], obs_info->obs_x,
-                obs_info->obs_x, &max_gamma);
-            
-            superB[j * hmm->num_states + i] = max_gamma * inv_obs_x;
-        }
-    }
-    
-    /* perform global Viterbi segmentation (i.e. process higher-level HMM) */
-    
-    icvViterbiSegmentation( hmm->num_states, obs_info->obs_y, 
-                             hmm->transP, superB, 0, 
-                             _CV_LAST_STATE, &super_q, obs_info->obs_y,
-                             obs_info->obs_y, &log_likelihood );
-    
-    log_likelihood /= obs_info->obs_y ;   
-    
-    
-    counter = 0;
-    /* assign new state to observation vectors */
-    for (i = 0; i < obs_info->obs_y; i++)
-    {   
-        for (j = 0; j < obs_info->obs_x; j++, counter++)
-        {
-            int superstate = super_q[i];
-            int state = (int)(hmm->u.ehmm[superstate].u.state - first_state);
-            
-            obs_info->state[2 * counter] = superstate;
-            obs_info->state[2 * counter + 1] = state + q[superstate][i][j];
-        }
-    }
-    
-    /* memory deallocation for superB */
-    icvDeleteMatrix( superB );
-    
-    /*memory deallocation for q */
-    for (i = 0; i < hmm->num_states; i++)
-    {
-        for (j = 0; j < obs_info->obs_y ; j++)
-        {
-            cvFree( &q[i][j] );
-        }
-        cvFree( &q[i] );
-    }
-    
-    cvFree( &q );
-    cvFree( &super_q );
-    
-    return log_likelihood;
-}  
-
-static CvStatus CV_STDCALL
-icvEstimateHMMStateParams( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm )
-{
-    /* compute gamma, weights, means, vars */
-    int k, i, j, m;
-    int total = 0;
-    int vect_len = obs_info_array[0]->obs_size;
-
-    float start_log_var_val = LN2PI * vect_len;
-
-    CvVect32f tmp_vect = icvCreateVector_32f( vect_len );
-    
-    CvEHMMState* first_state = hmm->u.ehmm[0].u.state;
-
-    assert( sizeof(float) == sizeof(int) );
-
-    for(i = 0; i < hmm->num_states; i++ )
-    {
-        total+= hmm->u.ehmm[i].num_states;
-    }
-
-    /***************Gamma***********************/
-    /* initialize gamma */
-    for( i = 0; i < total; i++ )
-    {
-        for (m = 0; m < first_state[i].num_mix; m++)
-        {
-            ((int*)(first_state[i].weight))[m] = 0;
-        }     
-    }
-    
-    /* maybe gamma must be computed in mixsegm process ?? */
-
-    /* compute gamma */
-    for (k = 0; k < num_img; k++)
-    {
-        CvImgObsInfo* info = obs_info_array[k];
-        int num_obs = info->obs_y * info->obs_x;
-
-        for (i = 0; i < num_obs; i++)
-        {
-            int state, mixture;
-            state = info->state[2*i + 1];
-            mixture = info->mix[i];
-            /* computes gamma - number of observations corresponding 
-               to every mixture of every state */ 
-            ((int*)(first_state[state].weight))[mixture] += 1;              
-        }
-    }     
-    /***************Mean and Var***********************/
-    /* compute means and variances of every item */
-    /* initially variance placed to inv_var */
-    /* zero mean and variance */
-    for (i = 0; i < total; i++)
-    {
-        memset( (void*)first_state[i].mu, 0, first_state[i].num_mix * vect_len * 
-                                                                         sizeof(float) );
-        memset( (void*)first_state[i].inv_var, 0, first_state[i].num_mix * vect_len * 
-                                                                         sizeof(float) );
-    }
-    
-    /* compute sums */
-    for (i = 0; i < num_img; i++)
-    {
-        CvImgObsInfo* info = obs_info_array[i];
-        int total_obs = info->obs_x * info->obs_y;
-
-        float* vector = info->obs;
-
-        for (j = 0; j < total_obs; j++, vector+=vect_len )
-        {   
-            int state = info->state[2 * j + 1];
-            int mixture = info->mix[j]; 
-            
-            CvVect32f mean  = first_state[state].mu + mixture * vect_len;
-            CvVect32f mean2 = first_state[state].inv_var + mixture * vect_len;
-            
-            icvAddVector_32f( mean, vector, mean, vect_len );
-            for( k = 0; k < vect_len; k++ )
-                mean2[k] += vector[k]*vector[k];
-        }   
-    }
-    
-    /*compute the means and variances */
-    /* assume gamma already computed */
-    for (i = 0; i < total; i++)
-    {           
-        CvEHMMState* state = &(first_state[i]);
-
-        for (m = 0; m < state->num_mix; m++)
-        {
-            int k;
-            CvVect32f mu  = state->mu + m * vect_len;
-            CvVect32f invar = state->inv_var + m * vect_len;             
-            
-            if ( ((int*)state->weight)[m] > 1)
-            {
-                float inv_gamma = 1.f/((int*)(state->weight))[m];
-            
-                icvScaleVector_32f( mu, mu, vect_len, inv_gamma);
-                icvScaleVector_32f( invar, invar, vect_len, inv_gamma);
-            }
-
-            icvMulVectors_32f(mu, mu, tmp_vect, vect_len);
-            icvSubVector_32f( invar, tmp_vect, invar, vect_len);     
-            
-            /* low bound of variance - 100 (Ara's experimental result) */
-            for( k = 0; k < vect_len; k++ )
-            {
-                invar[k] = (invar[k] > 100.f) ? invar[k] : 100.f;
-            }
-
-            /* compute log_var */
-            state->log_var_val[m] = start_log_var_val;
-            for( k = 0; k < vect_len; k++ )
-            {
-                state->log_var_val[m] += (float)log( invar[k] );
-            }           
-
-            /* SMOLI 27.10.2000 */
-            state->log_var_val[m] *= 0.5;
-
-
-            /* compute inv_var = 1/sqrt(2*variance) */
-            icvScaleVector_32f(invar, invar, vect_len, 2.f );
-            cvbInvSqrt( invar, invar, vect_len );
-        }
-    }
-  
-    /***************Weights***********************/
-    /* normilize gammas - i.e. compute mixture weights */
-    
-    //compute weights
-    for (i = 0; i < total; i++)
-    {           
-        int gamma_total = 0;
-        float norm;
-
-        for (m = 0; m < first_state[i].num_mix; m++)
-        {
-            gamma_total += ((int*)(first_state[i].weight))[m];  
-        }
-
-        norm = gamma_total ? (1.f/(float)gamma_total) : 0.f;
-            
-        for (m = 0; m < first_state[i].num_mix; m++)
-        {
-            first_state[i].weight[m] = ((int*)(first_state[i].weight))[m] * norm;
-        } 
-    }                                               
-
-    icvDeleteVector( tmp_vect);
-    return CV_NO_ERR; 
-}   
-
-/*
-CvStatus icvLightingCorrection8uC1R( uchar* img, CvSize roi, int src_step )
-{
-    int i, j;
-    int width = roi.width;
-    int height = roi.height;
-    
-    float x1, x2, y1, y2;
-    int f[3] = {0, 0, 0};
-    float a[3] = {0, 0, 0};
-    
-    float h1;
-    float h2;
-    
-    float c1,c2;
-    
-    float min = FLT_MAX;
-    float max = -FLT_MAX;
-    float correction;
-    
-    float* float_img = icvAlloc( width * height * sizeof(float) );
-    
-    x1 = width * (width + 1) / 2.0f; // Sum (1, ... , width)
-    x2 = width * (width + 1 ) * (2 * width + 1) / 6.0f; // Sum (1^2, ... , width^2)
-    y1 = height * (height + 1)/2.0f; // Sum (1, ... , width)
-    y2 = height * (height + 1 ) * (2 * height + 1) / 6.0f; // Sum (1^2, ... , width^2)
-    
-    
-    // extract grayvalues
-    for (i = 0; i < height; i++)
-    {
-        for (j = 0; j < width; j++)
-        {
-            f[2] = f[2] + j * img[i*src_step + j];
-            f[1] = f[1] + i * img[i*src_step + j];
-            f[0] = f[0] +     img[i*src_step + j];
-        }
-    }
-    
-    h1 = (float)f[0] * (float)x1 / (float)width;
-    h2 = (float)f[0] * (float)y1 / (float)height;
-    
-    a[2] = ((float)f[2] - h1) / (float)(x2*height - x1*x1*height/(float)width);
-    a[1] = ((float)f[1] - h2) / (float)(y2*width - y1*y1*width/(float)height);
-    a[0] = (float)f[0]/(float)(width*height) - (float)y1*a[1]/(float)height - 
-        (float)x1*a[2]/(float)width;
-    
-    for (i = 0; i < height; i++) 
-    {    
-        for (j = 0; j < width; j++)
-        {
-            
-            correction = a[0] + a[1]*(float)i + a[2]*(float)j;
-            
-            float_img[i*width + j] = img[i*src_step + j] - correction;
-            
-            if (float_img[i*width + j] < min) min = float_img[i*width+j];
-            if (float_img[i*width + j] > max) max = float_img[i*width+j];
-        }
-    }
-    
-    //rescaling to the range 0:255
-    c2 = 0;
-    if (max == min)
-        c2 = 255.0f;
-    else
-        c2 = 255.0f/(float)(max - min);
-    
-    c1 = (-(float)min)*c2;
-    
-    for (i = 0; i < height; i++)
-    {
-        for (j = 0; j < width; j++)
-        {
-            int value = (int)floor(c2*float_img[i*width + j] + c1);
-            if (value < 0) value = 0;
-            if (value > 255) value = 255;
-            img[i*src_step + j] = (uchar)value;
-        }
-    }
-
-    cvFree( &float_img );
-    return CV_NO_ERR;
-}
-                              
-
-CvStatus icvLightingCorrection( icvImage* img ) 
-{
-    CvSize roi;
-    if ( img->type != IPL_DEPTH_8U || img->channels != 1 )
-    return CV_BADFACTOR_ERR;
-
-    roi = _cvSize( img->roi.width, img->roi.height );
-    
-    return _cvLightingCorrection8uC1R( img->data + img->roi.y * img->step + img->roi.x, 
-                                        roi, img->step );
-
-}
-
-*/
-
-CV_IMPL CvEHMM*
-cvCreate2DHMM( int *state_number, int *num_mix, int obs_size )
-{
-    CvEHMM* hmm = 0;
-
-    CV_FUNCNAME( "cvCreate2DHMM" );
-
-    __BEGIN__;
-
-    IPPI_CALL( icvCreate2DHMM( &hmm, state_number, num_mix, obs_size ));
-
-    __END__;
-
-    return hmm;
-}
-
-CV_IMPL void
-cvRelease2DHMM( CvEHMM ** hmm )
-{
-    CV_FUNCNAME( "cvRelease2DHMM" );
-
-    __BEGIN__;
-
-    IPPI_CALL( icvRelease2DHMM( hmm ));
-    __END__;
-}
-
-CV_IMPL CvImgObsInfo*
-cvCreateObsInfo( CvSize num_obs, int obs_size )
-{
-    CvImgObsInfo *obs_info = 0;
-    
-    CV_FUNCNAME( "cvCreateObsInfo" );
-
-    __BEGIN__;
-
-    IPPI_CALL( icvCreateObsInfo( &obs_info, num_obs, obs_size ));
-
-    __END__;
-
-    return obs_info;
-}
-
-CV_IMPL void
-cvReleaseObsInfo( CvImgObsInfo ** obs_info )
-{
-    CV_FUNCNAME( "cvReleaseObsInfo" );
-
-    __BEGIN__;
-
-    IPPI_CALL( icvReleaseObsInfo( obs_info ));
-
-    __END__;
-}
-
-
-CV_IMPL void
-cvUniformImgSegm( CvImgObsInfo * obs_info, CvEHMM * hmm )
-{
-    CV_FUNCNAME( "cvUniformImgSegm" );
-
-    __BEGIN__;
-
-    IPPI_CALL( icvUniformImgSegm( obs_info, hmm ));
-    __CLEANUP__;
-    __END__;
-}
-
-CV_IMPL void
-cvInitMixSegm( CvImgObsInfo ** obs_info_array, int num_img, CvEHMM * hmm )
-{
-    CV_FUNCNAME( "cvInitMixSegm" );
-
-    __BEGIN__;
-
-    IPPI_CALL( icvInitMixSegm( obs_info_array, num_img, hmm ));
-
-    __END__;
-}
-
-CV_IMPL void
-cvEstimateHMMStateParams( CvImgObsInfo ** obs_info_array, int num_img, CvEHMM * hmm )
-{
-    CV_FUNCNAME( "cvEstimateHMMStateParams" );
-
-    __BEGIN__;
-
-    IPPI_CALL( icvEstimateHMMStateParams( obs_info_array, num_img, hmm ));
-
-    __END__;
-}
-
-CV_IMPL void
-cvEstimateTransProb( CvImgObsInfo ** obs_info_array, int num_img, CvEHMM * hmm )
-{
-    CV_FUNCNAME( "cvEstimateTransProb" );
-
-    __BEGIN__;
-
-    IPPI_CALL( icvEstimateTransProb( obs_info_array, num_img, hmm ));
-
-    __END__;
-
-}
-
-CV_IMPL void
-cvEstimateObsProb( CvImgObsInfo * obs_info, CvEHMM * hmm )
-{
-    CV_FUNCNAME( "cvEstimateObsProb" );
-
-    __BEGIN__;
-
-    IPPI_CALL( icvEstimateObsProb( obs_info, hmm ));
-
-    __END__;
-}
-
-CV_IMPL float
-cvEViterbi( CvImgObsInfo * obs_info, CvEHMM * hmm )
-{
-    float result = FLT_MAX;
-
-    CV_FUNCNAME( "cvEViterbi" );
-
-    __BEGIN__;
-
-    if( (obs_info == NULL) || (hmm == NULL) )
-        CV_ERROR( CV_BadDataPtr, "Null pointer." );
-
-    result = icvEViterbi( obs_info, hmm );
-    
-    __END__;
-    
-    return result;
-}
-
-CV_IMPL void
-cvMixSegmL2( CvImgObsInfo ** obs_info_array, int num_img, CvEHMM * hmm )
-{
-    CV_FUNCNAME( "cvMixSegmL2" );
-
-    __BEGIN__;
-
-    IPPI_CALL( icvMixSegmL2( obs_info_array, num_img, hmm ));
-
-    __END__;
-}
-
-/* End of file */
-