cvhmm.cpp.svn-base

来自「非结构化路识别」· SVN-BASE 代码 · 共 1,633 行 · 第 1/4 页

SVN-BASE
1,633
字号
/*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 "_cv.h"
#include <float.h>
#include "_cvutils.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*/      
IPCVAPI_IMPL(CvStatus, icvCreateObsInfo, ( CvImgObsInfo** obs_info, 
                                           CvSize num_obs, int obs_size ))
{
    int total = num_obs.height * num_obs.width;
 
    CvImgObsInfo* obs = (CvImgObsInfo*)icvAlloc( sizeof( CvImgObsInfo) );
    
    obs->obs_x = num_obs.width;
    obs->obs_y = num_obs.height;

    obs->obs = (float*)icvAlloc( total * obs_size * sizeof(float) );

    obs->state = (int*)icvAlloc( 2 * total * sizeof(int) );
    obs->mix = (int*)icvAlloc( total * sizeof(int) );  
        
    obs->obs_size = obs_size;

    obs_info[0] = obs;
 
    return CV_NO_ERR;
}

IPCVAPI_IMPL(CvStatus, icvReleaseObsInfo, ( CvImgObsInfo** p_obs_info ))
{
    CvImgObsInfo* obs_info = p_obs_info[0];

    icvFree( &(obs_info->obs) );
    icvFree( &(obs_info->mix) );
    icvFree( &(obs_info->state) ); 
    icvFree( &(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*/
IPCVAPI_IMPL(CvStatus, 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*)icvAlloc( (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 *)icvAlloc( 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*)icvAlloc( 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;
} 

IPCVAPI_IMPL(CvStatus, 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;
        icvFree( &(tmp)  );
    }

    icvFree( &(hmm->u.ehmm->u.state->mu) );
    icvFree( &(hmm->u.ehmm->u.state) );


    /* free hmm structures */
    icvFree( phmm );

    phmm[0] = NULL;

    return CV_NO_ERR;
}     

/* distance between 2 vectors */
IPCVAPI_IMPL( 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 */
IPCVAPI_IMPL(CvStatus, 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 = 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*/
IPCVAPI_IMPL(CvStatus, 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*)icvAlloc( total * sizeof(int) );
    
    /* integer counter is allocated for every state */
    counter = (int*)icvAlloc( total * sizeof(int) );
    
    samples = (CvVect32f**)icvAlloc( total * sizeof(CvVect32f*) ); 
    samples_mix = (int***)icvAlloc( total * sizeof(int**) ); 
    

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?