1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
47 #define LN2PI 1.837877f
48 #define BIG_FLT 1.e+10f
54 #define _CV_LAST_STATE 1
55 #define _CV_BEST_STATE 2
57 //*F///////////////////////////////////////////////////////////////////////////////////////
58 // Name: icvForward1DHMM
59 // Purpose: The function performs baum-welsh algorithm
61 // Parameters: obs_info - addres of pointer to CvImgObsInfo structure
62 // num_hor_obs - number of horizontal observation vectors
63 // num_ver_obs - number of horizontal observation vectors
64 // obs_size - length of observation vector
66 // Returns: error status
71 CvStatus icvForward1DHMM( int num_states, int num_obs, CvMatr64d A,
75 // assume that observation and transition
76 // probabilities already computed
77 int m_HMMType = _CV_CAUSAL;
78 double* m_pi = icvAlloc( num_states* sizeof( double) );
84 double* alpha = icvAlloc( num_states*num_obs * sizeof( double ) );
86 /* All calculations will be in non-logarithmic domain */
89 /* set initial state probabilities */
91 for (i = 1; i < num_states; i++)
96 for (i = 0; i < num_states; i++)
98 alpha[i] = m_pi[i] * m_b[ i];
101 /******************************************************************/
104 if ( m_HMMType == _CV_ERGODIC )
107 for (t = 1 ; t < num_obs; t++)
109 for (j = 0; j < num_states; j++)
114 for (i = 0; i < num_states; i++)
116 sum += alpha[(t - 1) * num_states + i] * A[i * num_states + j];
119 alpha[(t - 1) * num_states + j] = sum * B[t * num_states + j];
121 /* add computed alpha to scale factor */
122 sum_alpha += alpha[(t - 1) * num_states + j];
125 double scale = 1/sum_alpha;
128 for (j = 0; j < num_states; j++)
130 alpha[(t - 1) * num_states + j] *= scale;
142 //*F///////////////////////////////////////////////////////////////////////////////////////
143 // Name: icvCreateObsInfo
144 // Purpose: The function allocates memory for CvImgObsInfo structure
145 // and its inner stuff
147 // Parameters: obs_info - addres of pointer to CvImgObsInfo structure
148 // num_hor_obs - number of horizontal observation vectors
149 // num_ver_obs - number of horizontal observation vectors
150 // obs_size - length of observation vector
152 // Returns: error status
156 /*CvStatus icvCreateObsInfo( CvImgObsInfo** obs_info,
157 CvSize num_obs, int obs_size )
159 int total = num_obs.height * num_obs.width;
161 CvImgObsInfo* obs = (CvImgObsInfo*)icvAlloc( sizeof( CvImgObsInfo) );
163 obs->obs_x = num_obs.width;
164 obs->obs_y = num_obs.height;
166 obs->obs = (float*)icvAlloc( total * obs_size * sizeof(float) );
168 obs->state = (int*)icvAlloc( 2 * total * sizeof(int) );
169 obs->mix = (int*)icvAlloc( total * sizeof(int) );
171 obs->obs_size = obs_size;
178 /*CvStatus icvReleaseObsInfo( CvImgObsInfo** p_obs_info )
180 CvImgObsInfo* obs_info = p_obs_info[0];
182 icvFree( &(obs_info->obs) );
183 icvFree( &(obs_info->mix) );
184 icvFree( &(obs_info->state) );
185 icvFree( &(obs_info) );
187 p_obs_info[0] = NULL;
193 //*F///////////////////////////////////////////////////////////////////////////////////////
194 // Name: icvCreate1DHMM
195 // Purpose: The function allocates memory for 1-dimensional HMM
196 // and its inner stuff
198 // Parameters: hmm - addres of pointer to CvEHMM structure
199 // state_number - number of states in HMM
200 // num_mix - number of gaussian mixtures in HMM states
201 // size of array is defined by previous parameter
202 // obs_size - length of observation vectors
204 // Returns: error status
207 CvStatus icvCreate1DHMM( CvEHMM** this_hmm,
208 int state_number, int* num_mix, int obs_size )
211 int real_states = state_number;
213 CvEHMMState* all_states;
218 /* allocate memory for hmm */
219 hmm = (CvEHMM*)icvAlloc( sizeof(CvEHMM) );
221 /* set number of superstates */
222 hmm->num_states = state_number;
225 /* allocate memory for all states */
226 all_states = (CvEHMMState *)icvAlloc( real_states * sizeof( CvEHMMState ) );
228 /* assign number of mixtures */
229 for( i = 0; i < real_states; i++ )
231 all_states[i].num_mix = num_mix[i];
234 /* compute size of inner of all real states */
235 for( i = 0; i < real_states; i++ )
237 total_mix += num_mix[i];
239 /* allocate memory for states stuff */
240 pointers = (float*)icvAlloc( total_mix * (2/*for mu invvar */ * obs_size +
241 2/*for weight and log_var_val*/ ) * sizeof( float) );
243 /* organize memory */
244 for( i = 0; i < real_states; i++ )
246 all_states[i].mu = pointers; pointers += num_mix[i] * obs_size;
247 all_states[i].inv_var = pointers; pointers += num_mix[i] * obs_size;
249 all_states[i].log_var_val = pointers; pointers += num_mix[i];
250 all_states[i].weight = pointers; pointers += num_mix[i];
252 hmm->u.state = all_states;
254 hmm->transP = icvCreateMatrix_32f( hmm->num_states, hmm->num_states );
257 /* if all ok - return pointer */
262 CvStatus icvRelease1DHMM( CvEHMM** phmm )
264 CvEHMM* hmm = phmm[0];
265 icvDeleteMatrix( hmm->transP );
267 if (hmm->obsProb != NULL)
269 int* tmp = ((int*)(hmm->obsProb)) - 3;
273 icvFree( &(hmm->u.state->mu) );
274 icvFree( &(hmm->u.state) );
281 /*can be used in CHMM & DHMM */
282 CvStatus icvUniform1DSegm( Cv1DObsInfo* obs_info, CvEHMM* hmm )
284 /* implementation is very bad */
286 CvEHMMState* first_state;
288 /* check arguments */
289 if ( !obs_info || !hmm ) return CV_NULLPTR_ERR;
291 first_state = hmm->u.state;
293 for (i = 0; i < obs_info->obs_x; i++)
295 //bad line (division )
296 int state = (i * hmm->num_states)/obs_info->obs_x;
297 obs_info->state[i] = state;
304 /*F///////////////////////////////////////////////////////////////////////////////////////
306 // Purpose: The function implements the mixture segmentation of the states of the embedded HMM
307 // Context: used with the Viterbi training of the embedded HMM
308 // Function uses K-Means algorithm for clustering
310 // Parameters: obs_info_array - array of pointers to image observations
311 // num_img - length of above array
312 // hmm - pointer to HMM structure
314 // Returns: error status
318 CvStatus icvInit1DMixSegm(Cv1DObsInfo** obs_info_array, int num_img, CvEHMM* hmm)
321 int* num_samples; /* number of observations in every state */
322 int* counter; /* array of counters for every state */
324 int** a_class; /* for every state - characteristic array */
326 CvVect32f** samples; /* for every state - pointer to observation vectors */
327 int*** samples_mix; /* for every state - array of pointers to vectors mixtures */
329 CvTermCriteria criteria = cvTermCriteria( CV_TERMCRIT_EPS|CV_TERMCRIT_ITER,
333 int total = hmm->num_states;
334 CvEHMMState* first_state = hmm->u.state;
336 /* for every state integer is allocated - number of vectors in state */
337 num_samples = (int*)icvAlloc( total * sizeof(int) );
339 /* integer counter is allocated for every state */
340 counter = (int*)icvAlloc( total * sizeof(int) );
342 samples = (CvVect32f**)icvAlloc( total * sizeof(CvVect32f*) );
343 samples_mix = (int***)icvAlloc( total * sizeof(int**) );
346 memset( num_samples, 0 , total*sizeof(int) );
347 memset( counter, 0 , total*sizeof(int) );
350 /* for every state the number of vectors which belong to it is computed (smth. like histogram) */
351 for (k = 0; k < num_img; k++)
353 CvImgObsInfo* obs = obs_info_array[k];
355 for (i = 0; i < obs->obs_x; i++)
357 int state = obs->state[ i ];
358 num_samples[state] += 1;
362 /* for every state int* is allocated */
363 a_class = (int**)icvAlloc( total*sizeof(int*) );
365 for (i = 0; i < total; i++)
367 a_class[i] = (int*)icvAlloc( num_samples[i] * sizeof(int) );
368 samples[i] = (CvVect32f*)icvAlloc( num_samples[i] * sizeof(CvVect32f) );
369 samples_mix[i] = (int**)icvAlloc( num_samples[i] * sizeof(int*) );
372 /* for every state vectors which belong to state are gathered */
373 for (k = 0; k < num_img; k++)
375 CvImgObsInfo* obs = obs_info_array[k];
376 int num_obs = obs->obs_x;
377 float* vector = obs->obs;
379 for (i = 0; i < num_obs; i++, vector+=obs->obs_size )
381 int state = obs->state[i];
383 samples[state][counter[state]] = vector;
384 samples_mix[state][counter[state]] = &(obs->mix[i]);
390 memset( counter, 0, total*sizeof(int) );
392 /* do the actual clustering using the K Means algorithm */
393 for (i = 0; i < total; i++)
395 if ( first_state[i].num_mix == 1)
397 for (k = 0; k < num_samples[i]; k++)
399 /* all vectors belong to one mixture */
403 else if( num_samples[i] )
405 /* clusterize vectors */
406 icvKMeans( first_state[i].num_mix, samples[i], num_samples[i],
407 obs_info_array[0]->obs_size, criteria, a_class[i] );
411 /* for every vector number of mixture is assigned */
412 for( i = 0; i < total; i++ )
414 for (j = 0; j < num_samples[i]; j++)
416 samples_mix[i][j][0] = a_class[i][j];
420 for (i = 0; i < total; i++)
422 icvFree( &(a_class[i]) );
423 icvFree( &(samples[i]) );
424 icvFree( &(samples_mix[i]) );
429 icvFree( &samples_mix );
431 icvFree( &num_samples );
437 /*F///////////////////////////////////////////////////////////////////////////////////////
438 // Name: ComputeUniModeGauss
439 // Purpose: The function computes the Gaussian pdf for a sample vector
441 // Parameters: obsVeq - pointer to the sample vector
442 // mu - pointer to the mean vector of the Gaussian pdf
443 // var - pointer to the variance vector of the Gaussian pdf
444 // VecSize - the size of sample vector
446 // Returns: the pdf of the sample vector given the specified Gaussian
450 /*float icvComputeUniModeGauss(CvVect32f vect, CvVect32f mu,
451 CvVect32f inv_var, float log_var_val, int vect_size)
459 for (n = 0; n < vect_size; n++)
461 tmp = (vect[n] - mu[n]) * inv_var[n];
462 prob = prob - tmp * tmp;
469 /*F///////////////////////////////////////////////////////////////////////////////////////
470 // Name: ComputeGaussMixture
471 // Purpose: The function computes the mixture Gaussian pdf of a sample vector.
473 // Parameters: obsVeq - pointer to the sample vector
474 // mu - two-dimensional pointer to the mean vector of the Gaussian pdf;
475 // the first dimension is indexed over the number of mixtures and
476 // the second dimension is indexed along the size of the mean vector
477 // var - two-dimensional pointer to the variance vector of the Gaussian pdf;
478 // the first dimension is indexed over the number of mixtures and
479 // the second dimension is indexed along the size of the variance vector
480 // VecSize - the size of sample vector
481 // weight - pointer to the wights of the Gaussian mixture
482 // NumMix - the number of Gaussian mixtures
484 // Returns: the pdf of the sample vector given the specified Gaussian mixture.
488 /* Calculate probability of observation at state in logarithmic scale*/
489 /*float icvComputeGaussMixture( CvVect32f vect, float* mu,
490 float* inv_var, float* log_var_val,
491 int vect_size, float* weight, int num_mix )
499 return icvComputeUniModeGauss( vect, mu, inv_var, log_var_val[0], vect_size);
504 for (m = 0; m < num_mix; m++)
506 if ( weight[m] > 0.0)
508 l_prob = icvComputeUniModeGauss(vect, mu + m*vect_size,
509 inv_var + m * vect_size,
513 prob = prob + weight[m]*exp((double)l_prob);
522 /*F///////////////////////////////////////////////////////////////////////////////////////
523 // Name: EstimateObsProb
524 // Purpose: The function computes the probability of every observation in every state
526 // Parameters: obs_info - observations
528 // Returns: error status
532 CvStatus icvEstimate1DObsProb(CvImgObsInfo* obs_info, CvEHMM* hmm )
535 int total_states = 0;
537 /* check if matrix exist and check current size
538 if not sufficient - realloc */
539 int status = 0; /* 1 - not allocated, 2 - allocated but small size,
540 3 - size is enough, but distribution is bad, 0 - all ok */
542 /*for( j = 0; j < hmm->num_states; j++ )
544 total_states += hmm->u.ehmm[j].num_states;
546 total_states = hmm->num_states;
548 if ( hmm->obsProb == NULL )
550 /* allocare memory */
551 int need_size = ( obs_info->obs_x /* * obs_info->obs_y*/ * total_states * sizeof(float) /* +
552 obs_info->obs_y * hmm->num_states * sizeof( CvMatr32f) */);
554 int* buffer = (int*)icvAlloc( need_size + 3 * sizeof(int) );
555 buffer[0] = need_size;
556 buffer[1] = obs_info->obs_y;
557 buffer[2] = obs_info->obs_x;
558 hmm->obsProb = (float**) (buffer + 3);
564 /* check current size */
565 int* total= (int*)(((int*)(hmm->obsProb)) - 3);
566 int need_size = ( obs_info->obs_x /* * obs_info->obs_y*/ * total_states * sizeof(float) /* +
567 obs_info->obs_y * hmm->num_states * sizeof( CvMatr32f(float*) )*/ );
569 assert( sizeof(float*) == sizeof(int) );
571 if ( need_size > (*total) )
573 int* buffer = ((int*)(hmm->obsProb)) - 3;
575 buffer = (int*)icvAlloc( need_size + 3);
576 buffer[0] = need_size;
577 buffer[1] = obs_info->obs_y;
578 buffer[2] = obs_info->obs_x;
580 hmm->obsProb = (float**)(buffer + 3);
587 int* obsx = ((int*)(hmm->obsProb)) - 1;
588 //int* obsy = ((int*)(hmm->obsProb)) - 2;
590 assert( /*(*obsy > 0) &&*/ (*obsx > 0) );
592 /* is good distribution? */
593 if ( (obs_info->obs_x > (*obsx) ) /* || (obs_info->obs_y > (*obsy) ) */ )
597 assert( (status == 0) || (status == 3) );
598 /* if bad status - do reallocation actions */
601 float** tmp = hmm->obsProb;
604 /* distribute pointers of ehmm->obsProb */
605 /* for( i = 0; i < hmm->num_states; i++ )
607 hmm->u.ehmm[i].obsProb = tmp;
608 tmp += obs_info->obs_y;
611 //tmpf = (float*)tmp;
613 /* distribute pointers of ehmm->obsProb[j] */
614 /* for( i = 0; i < hmm->num_states; i++ )
616 CvEHMM* ehmm = &( hmm->u.ehmm[i] );
618 for( j = 0; j < obs_info->obs_y; j++ )
620 ehmm->obsProb[j] = tmpf;
621 tmpf += ehmm->num_states * obs_info->obs_x;
627 }/* end of pointer distribution */
631 #define MAX_BUF_SIZE 1200
632 float local_log_mix_prob[MAX_BUF_SIZE];
633 double local_mix_prob[MAX_BUF_SIZE];
634 int vect_size = obs_info->obs_size;
635 CvStatus res = CV_NO_ERR;
637 float* log_mix_prob = local_log_mix_prob;
638 double* mix_prob = local_mix_prob;
641 int obs_x = obs_info->obs_x;
643 /* calculate temporary buffer size */
644 //for( i = 0; i < hmm->num_states; i++ )
646 // CvEHMM* ehmm = &(hmm->u.ehmm[i]);
647 CvEHMMState* state = hmm->u.state;
650 for( j = 0; j < hmm->num_states; j++ )
652 int t = state[j].num_mix;
653 if( max_mix < t ) max_mix = t;
655 max_mix *= hmm->num_states;
656 /*if( max_size < max_mix )*/ max_size = max_mix;
659 max_size *= obs_x * vect_size;
661 /* allocate buffer */
662 if( max_size > MAX_BUF_SIZE )
664 log_mix_prob = (float*)icvAlloc( max_size*(sizeof(float) + sizeof(double)));
665 if( !log_mix_prob ) return CV_OUTOFMEM_ERR;
666 mix_prob = (double*)(log_mix_prob + max_size);
669 memset( log_mix_prob, 0, max_size*sizeof(float));
671 /*****************computing probabilities***********************/
673 /* loop through external states */
674 //for( i = 0; i < hmm->num_states; i++ )
676 // CvEHMM* ehmm = &(hmm->u.ehmm[i]);
677 CvEHMMState* state = hmm->u.state;
680 int n_states = hmm->num_states;
682 /* determine maximal number of mixtures (again) */
683 for( j = 0; j < hmm->num_states; j++ )
685 int t = state[j].num_mix;
686 if( max_mix < t ) max_mix = t;
689 /* loop through rows of the observation matrix */
690 //for( j = 0; j < obs_info->obs_y; j++ )
694 float* obs = obs_info->obs;/* + j * obs_x * vect_size; */
695 float* log_mp = max_mix > 1 ? log_mix_prob : (float*)(hmm->obsProb);
696 double* mp = mix_prob;
698 /* several passes are done below */
700 /* 1. calculate logarithms of probabilities for each mixture */
702 /* loop through mixtures */
703 /* !!!! */ for( m = 0; m < max_mix; m++ )
705 /* set pointer to first observation in the line */
708 /* cycles through obseravtions in the line */
709 for( n = 0; n < obs_x; n++, vect += vect_size, log_mp += n_states )
712 for( l = 0; l < n_states; l++ )
714 if( state[l].num_mix > m )
716 float* mu = state[l].mu + m*vect_size;
717 float* inv_var = state[l].inv_var + m*vect_size;
718 double prob = -state[l].log_var_val[m];
719 for( k = 0; k < vect_size; k++ )
721 double t = (vect[k] - mu[k])*inv_var[k];
724 log_mp[l] = MAX( (float)prob, -500 );
730 /* skip the rest if there is a single mixture */
733 /* 2. calculate exponent of log_mix_prob
734 (i.e. probability for each mixture) */
735 res = icvbExp_32f64f( log_mix_prob, mix_prob,
736 max_mix * obs_x * n_states );
737 if( res < 0 ) goto processing_exit;
739 /* 3. sum all mixtures with weights */
740 /* 3a. first mixture - simply scale by weight */
741 for( n = 0; n < obs_x; n++, mp += n_states )
744 for( l = 0; l < n_states; l++ )
746 mp[l] *= state[l].weight[0];
750 /* 3b. add other mixtures */
751 for( m = 1; m < max_mix; m++ )
753 int ofs = -m*obs_x*n_states;
754 for( n = 0; n < obs_x; n++, mp += n_states )
757 for( l = 0; l < n_states; l++ )
759 if( m < state[l].num_mix )
761 mp[l + ofs] += mp[l] * state[l].weight[m];
767 /* 4. Put logarithms of summary probabilities to the destination matrix */
768 res = icvbLog_64f32f( mix_prob, (float*)(hmm->obsProb),//[j],
770 if( res < 0 ) goto processing_exit;
777 if( log_mix_prob != local_log_mix_prob ) icvFree( &log_mix_prob );
782 /* for( i = 0; i < hmm->num_states; i++ )
784 CvEHMM* ehmm = &(hmm->u.ehmm[i]);
785 CvEHMMState* state = ehmm->u.state;
787 for( j = 0; j < obs_info->obs_y; j++ )
791 int obs_index = j * obs_info->obs_x;
793 float* B = ehmm->obsProb[j];
795 // cycles through obs and states
796 for( k = 0; k < obs_info->obs_x; k++ )
798 CvVect32f vect = (obs_info->obs) + (obs_index + k) * vect_size;
800 float* matr_line = B + k * ehmm->num_states;
802 for( m = 0; m < ehmm->num_states; m++ )
804 matr_line[m] = icvComputeGaussMixture( vect, state[m].mu, state[m].inv_var,
805 state[m].log_var_val, vect_size, state[m].weight,
816 /*F///////////////////////////////////////////////////////////////////////////////////////
817 // Name: EstimateTransProb
818 // Purpose: The function calculates the state and super state transition probabilities
819 // of the model given the images,
820 // the state segmentation and the input parameters
822 // Parameters: obs_info_array - array of pointers to image observations
823 // num_img - length of above array
824 // hmm - pointer to HMM structure
829 CvStatus icvEstimate1DTransProb( Cv1DObsInfo** obs_info_array,
835 /* as a counter we will use transP matrix */
840 icvSetZero_32f( hmm->transP, hmm->num_states, hmm->num_states );
843 /* compute the counters */
844 for (i = 0; i < num_seq; i++)
847 Cv1DObsInfo* info = obs_info_array[i];
849 for (k = 0; k < info->obs_x; k++, counter++)
851 /* compute how many transitions from state to state
856 state = info->state[counter];
858 if (k < info->obs_x - 1)
860 int transP_size = hmm->num_states;
862 nextstate = info->state[counter+1];
863 hmm->transP[ state * transP_size + nextstate] += 1;
868 /* estimate superstate matrix */
869 for( i = 0; i < hmm->num_states; i++)
873 for( j = 0; j < hmm->num_states; j++)
875 total += hmm->transP[i * hmm->num_states + j];
879 inv_total = total ? 1.f/total : 0;
881 for( j = 0; j < hmm->num_states; j++)
883 hmm->transP[i * hmm->num_states + j] =
884 hmm->transP[i * hmm->num_states + j] ?
885 (float)log( hmm->transP[i * hmm->num_states + j] * inv_total ) : -BIG_FLT;
893 /*F///////////////////////////////////////////////////////////////////////////////////////
895 // Purpose: The function implements the mixture segmentation of the states of the embedded HMM
896 // Context: used with the Viterbi training of the embedded HMM
906 CvStatus icv1DMixSegmL2(CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm )
910 CvEHMMState* state = hmm->u.state;
912 for (k = 0; k < num_img; k++)
915 CvImgObsInfo* info = obs_info_array[k];
917 for (i = 0; i < info->obs_x; i++)
919 int e_state = info->state[i];
922 min_dist = icvSquareDistance((info->obs) + (i * info->obs_size),
923 state[e_state].mu, info->obs_size);
926 for (m = 1; m < state[e_state].num_mix; m++)
928 float dist=icvSquareDistance( (info->obs) + (i * info->obs_size),
929 state[e_state].mu + m * info->obs_size,
934 /* assign mixture with smallest distance */
943 /*F///////////////////////////////////////////////////////////////////////////////////////
945 // Purpose: The function calculates the embedded Viterbi algorithm
949 // obs_info - observations
952 // Returns: the Embedded Viterbi probability (float)
953 // and do state segmentation of observations
957 float icvViterbi(Cv1DObsInfo* obs_info, CvEHMM* hmm)
960 float log_likelihood;
962 //CvEHMMState* first_state = hmm->u.state;
964 /* memory allocation for superB */
965 /*CvMatr32f superB = picvCreateMatrix_32f(hmm->num_states, obs_info->obs_x );*/
967 /* memory allocation for q */
968 int* super_q = (int*)icvAlloc( obs_info->obs_x * sizeof(int) );
970 /* perform Viterbi segmentation (process 1D HMM) */
971 icvViterbiSegmentation( hmm->num_states, obs_info->obs_x,
972 hmm->transP, (float*)(hmm->obsProb), 0,
973 _CV_LAST_STATE, &super_q, obs_info->obs_x,
974 obs_info->obs_x, &log_likelihood );
976 log_likelihood /= obs_info->obs_x ;
979 /* assign new state to observation vectors */
980 for (i = 0; i < obs_info->obs_x; i++)
982 int state = super_q[i];
983 obs_info->state[i] = state;
986 /* memory deallocation for superB */
987 /*picvDeleteMatrix( superB );*/
990 return log_likelihood;
993 CvStatus icvEstimate1DHMMStateParams(CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm)
996 /* compute gamma, weights, means, vars */
1000 int vect_len = obs_info_array[0]->obs_size;
1002 float start_log_var_val = LN2PI * vect_len;
1004 CvVect32f tmp_vect = icvCreateVector_32f( vect_len );
1006 CvEHMMState* first_state = hmm->u.state;
1008 assert( sizeof(float) == sizeof(int) );
1010 total+= hmm->num_states;
1012 /***************Gamma***********************/
1013 /* initialize gamma */
1014 for( i = 0; i < total; i++ )
1016 for (m = 0; m < first_state[i].num_mix; m++)
1018 ((int*)(first_state[i].weight))[m] = 0;
1022 /* maybe gamma must be computed in mixsegm process ?? */
1026 for (k = 0; k < num_img; k++)
1028 CvImgObsInfo* info = obs_info_array[k];
1029 int num_obs = info->obs_y * info->obs_x;
1031 for (i = 0; i < num_obs; i++)
1034 state = info->state[i];
1035 mixture = info->mix[i];
1036 /* computes gamma - number of observations corresponding
1037 to every mixture of every state */
1038 ((int*)(first_state[state].weight))[mixture] += 1;
1041 /***************Mean and Var***********************/
1042 /* compute means and variances of every item */
1043 /* initially variance placed to inv_var */
1044 /* zero mean and variance */
1045 for (i = 0; i < total; i++)
1047 memset( (void*)first_state[i].mu, 0, first_state[i].num_mix * vect_len *
1049 memset( (void*)first_state[i].inv_var, 0, first_state[i].num_mix * vect_len *
1054 for (i = 0; i < num_img; i++)
1056 CvImgObsInfo* info = obs_info_array[i];
1057 int total_obs = info->obs_x;// * info->obs_y;
1059 float* vector = info->obs;
1061 for (j = 0; j < total_obs; j++, vector+=vect_len )
1063 int state = info->state[j];
1064 int mixture = info->mix[j];
1066 CvVect32f mean = first_state[state].mu + mixture * vect_len;
1067 CvVect32f mean2 = first_state[state].inv_var + mixture * vect_len;
1069 icvAddVector_32f( mean, vector, mean, vect_len );
1070 icvAddSquare_32f_C1IR( vector, vect_len * sizeof(float),
1071 mean2, vect_len * sizeof(float), cvSize(vect_len, 1) );
1075 /*compute the means and variances */
1076 /* assume gamma already computed */
1078 for (i = 0; i < total; i++)
1080 CvEHMMState* state = &(first_state[i]);
1082 for (m = 0; m < state->num_mix; m++)
1085 CvVect32f mu = state->mu + m * vect_len;
1086 CvVect32f invar = state->inv_var + m * vect_len;
1088 if ( ((int*)state->weight)[m] > 1)
1090 float inv_gamma = 1.f/((int*)(state->weight))[m];
1092 icvScaleVector_32f( mu, mu, vect_len, inv_gamma);
1093 icvScaleVector_32f( invar, invar, vect_len, inv_gamma);
1096 icvMulVectors_32f(mu, mu, tmp_vect, vect_len);
1097 icvSubVector_32f( invar, tmp_vect, invar, vect_len);
1099 /* low bound of variance - 0.01 (Ara's experimental result) */
1100 for( k = 0; k < vect_len; k++ )
1102 invar[k] = (invar[k] > 0.01f) ? invar[k] : 0.01f;
1105 /* compute log_var */
1106 state->log_var_val[m] = start_log_var_val;
1107 for( k = 0; k < vect_len; k++ )
1109 state->log_var_val[m] += (float)log( invar[k] );
1112 state->log_var_val[m] *= 0.5;
1114 /* compute inv_var = 1/sqrt(2*variance) */
1115 icvScaleVector_32f(invar, invar, vect_len, 2.f );
1116 icvbInvSqrt_32f(invar, invar, vect_len );
1120 /***************Weights***********************/
1121 /* normilize gammas - i.e. compute mixture weights */
1124 for (i = 0; i < total; i++)
1126 int gamma_total = 0;
1129 for (m = 0; m < first_state[i].num_mix; m++)
1131 gamma_total += ((int*)(first_state[i].weight))[m];
1134 norm = gamma_total ? (1.f/(float)gamma_total) : 0.f;
1136 for (m = 0; m < first_state[i].num_mix; m++)
1138 first_state[i].weight[m] = ((int*)(first_state[i].weight))[m] * norm;
1142 icvDeleteVector( tmp_vect);