1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
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.
8 //
9 //
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
21 //
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.
25 //
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.
28 //
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.
39 //
40 //M*/
41
42 #include "_cvaux.h"
43
44 #define LN2PI 1.837877f
45 #define BIG_FLT 1.e+10f
46
47
48 #define _CV_ERGODIC 1
49 #define _CV_CAUSAL 2
50
51 #define _CV_LAST_STATE 1
52 #define _CV_BEST_STATE 2
53
54
55 //*F///////////////////////////////////////////////////////////////////////////////////////
56 // Name: _cvCreateObsInfo
57 // Purpose: The function allocates memory for CvImgObsInfo structure
58 // and its inner stuff
59 // Context:
60 // Parameters: obs_info - addres of pointer to CvImgObsInfo structure
61 // num_hor_obs - number of horizontal observation vectors
62 // num_ver_obs - number of horizontal observation vectors
63 // obs_size - length of observation vector
64 //
65 // Returns: error status
66 //
67 // Notes:
68 //F*/
icvCreateObsInfo(CvImgObsInfo ** obs_info,CvSize num_obs,int obs_size)69 static CvStatus CV_STDCALL icvCreateObsInfo( CvImgObsInfo** obs_info,
70 CvSize num_obs, int obs_size )
71 {
72 int total = num_obs.height * num_obs.width;
73
74 CvImgObsInfo* obs = (CvImgObsInfo*)cvAlloc( sizeof( CvImgObsInfo) );
75
76 obs->obs_x = num_obs.width;
77 obs->obs_y = num_obs.height;
78
79 obs->obs = (float*)cvAlloc( total * obs_size * sizeof(float) );
80
81 obs->state = (int*)cvAlloc( 2 * total * sizeof(int) );
82 obs->mix = (int*)cvAlloc( total * sizeof(int) );
83
84 obs->obs_size = obs_size;
85
86 obs_info[0] = obs;
87
88 return CV_NO_ERR;
89 }
90
icvReleaseObsInfo(CvImgObsInfo ** p_obs_info)91 static CvStatus CV_STDCALL icvReleaseObsInfo( CvImgObsInfo** p_obs_info )
92 {
93 CvImgObsInfo* obs_info = p_obs_info[0];
94
95 cvFree( &(obs_info->obs) );
96 cvFree( &(obs_info->mix) );
97 cvFree( &(obs_info->state) );
98 cvFree( &(obs_info) );
99
100 p_obs_info[0] = NULL;
101
102 return CV_NO_ERR;
103 }
104
105
106 //*F///////////////////////////////////////////////////////////////////////////////////////
107 // Name: icvCreate2DHMM
108 // Purpose: The function allocates memory for 2-dimensional embedded HMM model
109 // and its inner stuff
110 // Context:
111 // Parameters: hmm - addres of pointer to CvEHMM structure
112 // state_number - array of hmm sizes (size of array == state_number[0]+1 )
113 // num_mix - number of gaussian mixtures in low-level HMM states
114 // size of array is defined by previous array values
115 // obs_size - length of observation vectors
116 //
117 // Returns: error status
118 //
119 // Notes: state_number[0] - number of states in external HMM.
120 // state_number[i] - number of states in embedded HMM
121 //
122 // example for face recognition: state_number = { 5 3 6 6 6 3 },
123 // length of num_mix array = 3+6+6+6+3 = 24//
124 //
125 //F*/
icvCreate2DHMM(CvEHMM ** this_hmm,int * state_number,int * num_mix,int obs_size)126 static CvStatus CV_STDCALL icvCreate2DHMM( CvEHMM** this_hmm,
127 int* state_number, int* num_mix, int obs_size )
128 {
129 int i;
130 int real_states = 0;
131
132 CvEHMMState* all_states;
133 CvEHMM* hmm;
134 int total_mix = 0;
135 float* pointers;
136
137 //compute total number of states of all level in 2d EHMM
138 for( i = 1; i <= state_number[0]; i++ )
139 {
140 real_states += state_number[i];
141 }
142
143 /* allocate memory for all hmms (from all levels) */
144 hmm = (CvEHMM*)cvAlloc( (state_number[0] + 1) * sizeof(CvEHMM) );
145
146 /* set number of superstates */
147 hmm[0].num_states = state_number[0];
148 hmm[0].level = 1;
149
150 /* allocate memory for all states */
151 all_states = (CvEHMMState *)cvAlloc( real_states * sizeof( CvEHMMState ) );
152
153 /* assign number of mixtures */
154 for( i = 0; i < real_states; i++ )
155 {
156 all_states[i].num_mix = num_mix[i];
157 }
158
159 /* compute size of inner of all real states */
160 for( i = 0; i < real_states; i++ )
161 {
162 total_mix += num_mix[i];
163 }
164 /* allocate memory for states stuff */
165 pointers = (float*)cvAlloc( total_mix * (2/*for mu invvar */ * obs_size +
166 2/*for weight and log_var_val*/ ) * sizeof( float) );
167
168 /* organize memory */
169 for( i = 0; i < real_states; i++ )
170 {
171 all_states[i].mu = pointers; pointers += num_mix[i] * obs_size;
172 all_states[i].inv_var = pointers; pointers += num_mix[i] * obs_size;
173
174 all_states[i].log_var_val = pointers; pointers += num_mix[i];
175 all_states[i].weight = pointers; pointers += num_mix[i];
176 }
177
178 /* set pointer to embedded hmm array */
179 hmm->u.ehmm = hmm + 1;
180
181 for( i = 0; i < hmm[0].num_states; i++ )
182 {
183 hmm[i+1].u.state = all_states;
184 all_states += state_number[i+1];
185 hmm[i+1].num_states = state_number[i+1];
186 }
187
188 for( i = 0; i <= state_number[0]; i++ )
189 {
190 hmm[i].transP = icvCreateMatrix_32f( hmm[i].num_states, hmm[i].num_states );
191 hmm[i].obsProb = NULL;
192 hmm[i].level = i ? 0 : 1;
193 }
194
195 /* if all ok - return pointer */
196 *this_hmm = hmm;
197 return CV_NO_ERR;
198 }
199
icvRelease2DHMM(CvEHMM ** phmm)200 static CvStatus CV_STDCALL icvRelease2DHMM( CvEHMM** phmm )
201 {
202 CvEHMM* hmm = phmm[0];
203 int i;
204 for( i = 0; i < hmm[0].num_states + 1; i++ )
205 {
206 icvDeleteMatrix( hmm[i].transP );
207 }
208
209 if (hmm->obsProb != NULL)
210 {
211 int* tmp = ((int*)(hmm->obsProb)) - 3;
212 cvFree( &(tmp) );
213 }
214
215 cvFree( &(hmm->u.ehmm->u.state->mu) );
216 cvFree( &(hmm->u.ehmm->u.state) );
217
218
219 /* free hmm structures */
220 cvFree( phmm );
221
222 phmm[0] = NULL;
223
224 return CV_NO_ERR;
225 }
226
227 /* distance between 2 vectors */
icvSquareDistance(CvVect32f v1,CvVect32f v2,int len)228 static float icvSquareDistance( CvVect32f v1, CvVect32f v2, int len )
229 {
230 int i;
231 double dist0 = 0;
232 double dist1 = 0;
233
234 for( i = 0; i <= len - 4; i += 4 )
235 {
236 double t0 = v1[i] - v2[i];
237 double t1 = v1[i+1] - v2[i+1];
238 dist0 += t0*t0;
239 dist1 += t1*t1;
240
241 t0 = v1[i+2] - v2[i+2];
242 t1 = v1[i+3] - v2[i+3];
243 dist0 += t0*t0;
244 dist1 += t1*t1;
245 }
246
247 for( ; i < len; i++ )
248 {
249 double t0 = v1[i] - v2[i];
250 dist0 += t0*t0;
251 }
252
253 return (float)(dist0 + dist1);
254 }
255
256 /*can be used in CHMM & DHMM */
257 static CvStatus CV_STDCALL
icvUniformImgSegm(CvImgObsInfo * obs_info,CvEHMM * hmm)258 icvUniformImgSegm( CvImgObsInfo* obs_info, CvEHMM* hmm )
259 {
260 #if 1
261 /* implementation is very bad */
262 int i, j, counter = 0;
263 CvEHMMState* first_state;
264 float inv_x = 1.f/obs_info->obs_x;
265 float inv_y = 1.f/obs_info->obs_y;
266
267 /* check arguments */
268 if ( !obs_info || !hmm ) return CV_NULLPTR_ERR;
269
270 first_state = hmm->u.ehmm->u.state;
271
272 for (i = 0; i < obs_info->obs_y; i++)
273 {
274 //bad line (division )
275 int superstate = (int)((i * hmm->num_states)*inv_y);/* /obs_info->obs_y; */
276
277 int index = (int)(hmm->u.ehmm[superstate].u.state - first_state);
278
279 for (j = 0; j < obs_info->obs_x; j++, counter++)
280 {
281 int state = (int)((j * hmm->u.ehmm[superstate].num_states)* inv_x); /* / obs_info->obs_x; */
282
283 obs_info->state[2 * counter] = superstate;
284 obs_info->state[2 * counter + 1] = state + index;
285 }
286 }
287 #else
288 //this is not ready yet
289
290 int i,j,k,m;
291 CvEHMMState* first_state = hmm->u.ehmm->u.state;
292
293 /* check bad arguments */
294 if ( hmm->num_states > obs_info->obs_y ) return CV_BADSIZE_ERR;
295
296 //compute vertical subdivision
297 float row_per_state = (float)obs_info->obs_y / hmm->num_states;
298 float col_per_state[1024]; /* maximum 1024 superstates */
299
300 //for every horizontal band compute subdivision
301 for( i = 0; i < hmm->num_states; i++ )
302 {
303 CvEHMM* ehmm = &(hmm->u.ehmm[i]);
304 col_per_state[i] = (float)obs_info->obs_x / ehmm->num_states;
305 }
306
307 //compute state bounds
308 int ss_bound[1024];
309 for( i = 0; i < hmm->num_states - 1; i++ )
310 {
311 ss_bound[i] = floor( row_per_state * ( i+1 ) );
312 }
313 ss_bound[hmm->num_states - 1] = obs_info->obs_y;
314
315 //work inside every superstate
316
317 int row = 0;
318
319 for( i = 0; i < hmm->num_states; i++ )
320 {
321 CvEHMM* ehmm = &(hmm->u.ehmm[i]);
322 int index = ehmm->u.state - first_state;
323
324 //calc distribution in superstate
325 int es_bound[1024];
326 for( j = 0; j < ehmm->num_states - 1; j++ )
327 {
328 es_bound[j] = floor( col_per_state[i] * ( j+1 ) );
329 }
330 es_bound[ehmm->num_states - 1] = obs_info->obs_x;
331
332 //assign states to first row of superstate
333 int col = 0;
334 for( j = 0; j < ehmm->num_states; j++ )
335 {
336 for( k = col; k < es_bound[j]; k++, col++ )
337 {
338 obs_info->state[row * obs_info->obs_x + 2 * k] = i;
339 obs_info->state[row * obs_info->obs_x + 2 * k + 1] = j + index;
340 }
341 col = es_bound[j];
342 }
343
344 //copy the same to other rows of superstate
345 for( m = row; m < ss_bound[i]; m++ )
346 {
347 memcpy( &(obs_info->state[m * obs_info->obs_x * 2]),
348 &(obs_info->state[row * obs_info->obs_x * 2]), obs_info->obs_x * 2 * sizeof(int) );
349 }
350
351 row = ss_bound[i];
352 }
353
354 #endif
355
356 return CV_NO_ERR;
357 }
358
359
360 /*F///////////////////////////////////////////////////////////////////////////////////////
361 // Name: InitMixSegm
362 // Purpose: The function implements the mixture segmentation of the states of the
363 // embedded HMM
364 // Context: used with the Viterbi training of the embedded HMM
365 // Function uses K-Means algorithm for clustering
366 //
367 // Parameters: obs_info_array - array of pointers to image observations
368 // num_img - length of above array
369 // hmm - pointer to HMM structure
370 //
371 // Returns: error status
372 //
373 // Notes:
374 //F*/
375 static CvStatus CV_STDCALL
icvInitMixSegm(CvImgObsInfo ** obs_info_array,int num_img,CvEHMM * hmm)376 icvInitMixSegm( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm )
377 {
378 int k, i, j;
379 int* num_samples; /* number of observations in every state */
380 int* counter; /* array of counters for every state */
381
382 int** a_class; /* for every state - characteristic array */
383
384 CvVect32f** samples; /* for every state - pointer to observation vectors */
385 int*** samples_mix; /* for every state - array of pointers to vectors mixtures */
386
387 CvTermCriteria criteria = cvTermCriteria( CV_TERMCRIT_EPS|CV_TERMCRIT_ITER,
388 1000, /* iter */
389 0.01f ); /* eps */
390
391 int total = 0;
392
393 CvEHMMState* first_state = hmm->u.ehmm->u.state;
394
395 for( i = 0 ; i < hmm->num_states; i++ )
396 {
397 total += hmm->u.ehmm[i].num_states;
398 }
399
400 /* for every state integer is allocated - number of vectors in state */
401 num_samples = (int*)cvAlloc( total * sizeof(int) );
402
403 /* integer counter is allocated for every state */
404 counter = (int*)cvAlloc( total * sizeof(int) );
405
406 samples = (CvVect32f**)cvAlloc( total * sizeof(CvVect32f*) );
407 samples_mix = (int***)cvAlloc( total * sizeof(int**) );
408
409 /* clear */
410 memset( num_samples, 0 , total*sizeof(int) );
411 memset( counter, 0 , total*sizeof(int) );
412
413
414 /* for every state the number of vectors which belong to it is computed (smth. like histogram) */
415 for (k = 0; k < num_img; k++)
416 {
417 CvImgObsInfo* obs = obs_info_array[k];
418 int count = 0;
419
420 for (i = 0; i < obs->obs_y; i++)
421 {
422 for (j = 0; j < obs->obs_x; j++, count++)
423 {
424 int state = obs->state[ 2 * count + 1];
425 num_samples[state] += 1;
426 }
427 }
428 }
429
430 /* for every state int* is allocated */
431 a_class = (int**)cvAlloc( total*sizeof(int*) );
432
433 for (i = 0; i < total; i++)
434 {
435 a_class[i] = (int*)cvAlloc( num_samples[i] * sizeof(int) );
436 samples[i] = (CvVect32f*)cvAlloc( num_samples[i] * sizeof(CvVect32f) );
437 samples_mix[i] = (int**)cvAlloc( num_samples[i] * sizeof(int*) );
438 }
439
440 /* for every state vectors which belong to state are gathered */
441 for (k = 0; k < num_img; k++)
442 {
443 CvImgObsInfo* obs = obs_info_array[k];
444 int num_obs = ( obs->obs_x ) * ( obs->obs_y );
445 float* vector = obs->obs;
446
447 for (i = 0; i < num_obs; i++, vector+=obs->obs_size )
448 {
449 int state = obs->state[2*i+1];
450
451 samples[state][counter[state]] = vector;
452 samples_mix[state][counter[state]] = &(obs->mix[i]);
453 counter[state]++;
454 }
455 }
456
457 /* clear counters */
458 memset( counter, 0, total*sizeof(int) );
459
460 /* do the actual clustering using the K Means algorithm */
461 for (i = 0; i < total; i++)
462 {
463 if ( first_state[i].num_mix == 1)
464 {
465 for (k = 0; k < num_samples[i]; k++)
466 {
467 /* all vectors belong to one mixture */
468 a_class[i][k] = 0;
469 }
470 }
471 else if( num_samples[i] )
472 {
473 /* clusterize vectors */
474 cvKMeans( first_state[i].num_mix, samples[i], num_samples[i],
475 obs_info_array[0]->obs_size, criteria, a_class[i] );
476 }
477 }
478
479 /* for every vector number of mixture is assigned */
480 for( i = 0; i < total; i++ )
481 {
482 for (j = 0; j < num_samples[i]; j++)
483 {
484 samples_mix[i][j][0] = a_class[i][j];
485 }
486 }
487
488 for (i = 0; i < total; i++)
489 {
490 cvFree( &(a_class[i]) );
491 cvFree( &(samples[i]) );
492 cvFree( &(samples_mix[i]) );
493 }
494
495 cvFree( &a_class );
496 cvFree( &samples );
497 cvFree( &samples_mix );
498 cvFree( &counter );
499 cvFree( &num_samples );
500
501 return CV_NO_ERR;
502 }
503
504 /*F///////////////////////////////////////////////////////////////////////////////////////
505 // Name: ComputeUniModeGauss
506 // Purpose: The function computes the Gaussian pdf for a sample vector
507 // Context:
508 // Parameters: obsVeq - pointer to the sample vector
509 // mu - pointer to the mean vector of the Gaussian pdf
510 // var - pointer to the variance vector of the Gaussian pdf
511 // VecSize - the size of sample vector
512 //
513 // Returns: the pdf of the sample vector given the specified Gaussian
514 //
515 // Notes:
516 //F*/
517 /*static float icvComputeUniModeGauss(CvVect32f vect, CvVect32f mu,
518 CvVect32f inv_var, float log_var_val, int vect_size)
519 {
520 int n;
521 double tmp;
522 double prob;
523
524 prob = -log_var_val;
525
526 for (n = 0; n < vect_size; n++)
527 {
528 tmp = (vect[n] - mu[n]) * inv_var[n];
529 prob = prob - tmp * tmp;
530 }
531 //prob *= 0.5f;
532
533 return (float)prob;
534 }*/
535
536 /*F///////////////////////////////////////////////////////////////////////////////////////
537 // Name: ComputeGaussMixture
538 // Purpose: The function computes the mixture Gaussian pdf of a sample vector.
539 // Context:
540 // Parameters: obsVeq - pointer to the sample vector
541 // mu - two-dimensional pointer to the mean vector of the Gaussian pdf;
542 // the first dimension is indexed over the number of mixtures and
543 // the second dimension is indexed along the size of the mean vector
544 // var - two-dimensional pointer to the variance vector of the Gaussian pdf;
545 // the first dimension is indexed over the number of mixtures and
546 // the second dimension is indexed along the size of the variance vector
547 // VecSize - the size of sample vector
548 // weight - pointer to the wights of the Gaussian mixture
549 // NumMix - the number of Gaussian mixtures
550 //
551 // Returns: the pdf of the sample vector given the specified Gaussian mixture.
552 //
553 // Notes:
554 //F*/
555 /* Calculate probability of observation at state in logarithmic scale*/
556 /*static float
557 icvComputeGaussMixture( CvVect32f vect, float* mu,
558 float* inv_var, float* log_var_val,
559 int vect_size, float* weight, int num_mix )
560 {
561 double prob, l_prob;
562
563 prob = 0.0f;
564
565 if (num_mix == 1)
566 {
567 return icvComputeUniModeGauss( vect, mu, inv_var, log_var_val[0], vect_size);
568 }
569 else
570 {
571 int m;
572 for (m = 0; m < num_mix; m++)
573 {
574 if ( weight[m] > 0.0)
575 {
576 l_prob = icvComputeUniModeGauss(vect, mu + m*vect_size,
577 inv_var + m * vect_size,
578 log_var_val[m],
579 vect_size);
580
581 prob = prob + weight[m]*exp((double)l_prob);
582 }
583 }
584 prob = log(prob);
585 }
586 return (float)prob;
587 }*/
588
589
590 /*F///////////////////////////////////////////////////////////////////////////////////////
591 // Name: EstimateObsProb
592 // Purpose: The function computes the probability of every observation in every state
593 // Context:
594 // Parameters: obs_info - observations
595 // hmm - hmm
596 // Returns: error status
597 //
598 // Notes:
599 //F*/
icvEstimateObsProb(CvImgObsInfo * obs_info,CvEHMM * hmm)600 static CvStatus CV_STDCALL icvEstimateObsProb( CvImgObsInfo* obs_info, CvEHMM* hmm )
601 {
602 int i, j;
603 int total_states = 0;
604
605 /* check if matrix exist and check current size
606 if not sufficient - realloc */
607 int status = 0; /* 1 - not allocated, 2 - allocated but small size,
608 3 - size is enough, but distribution is bad, 0 - all ok */
609
610 for( j = 0; j < hmm->num_states; j++ )
611 {
612 total_states += hmm->u.ehmm[j].num_states;
613 }
614
615 if ( hmm->obsProb == NULL )
616 {
617 /* allocare memory */
618 int need_size = ( obs_info->obs_x * obs_info->obs_y * total_states * sizeof(float) +
619 obs_info->obs_y * hmm->num_states * sizeof( CvMatr32f) );
620
621 int* buffer = (int*)cvAlloc( need_size + 3 * sizeof(int) );
622 buffer[0] = need_size;
623 buffer[1] = obs_info->obs_y;
624 buffer[2] = obs_info->obs_x;
625 hmm->obsProb = (float**) (buffer + 3);
626 status = 3;
627
628 }
629 else
630 {
631 /* check current size */
632 int* total= (int*)(((int*)(hmm->obsProb)) - 3);
633 int need_size = ( obs_info->obs_x * obs_info->obs_y * total_states * sizeof(float) +
634 obs_info->obs_y * hmm->num_states * sizeof( CvMatr32f/*(float*)*/ ) );
635
636 assert( sizeof(float*) == sizeof(int) );
637
638 if ( need_size > (*total) )
639 {
640 int* buffer = ((int*)(hmm->obsProb)) - 3;
641 cvFree( &buffer);
642 buffer = (int*)cvAlloc( need_size + 3 * sizeof(int));
643 buffer[0] = need_size;
644 buffer[1] = obs_info->obs_y;
645 buffer[2] = obs_info->obs_x;
646
647 hmm->obsProb = (float**)(buffer + 3);
648
649 status = 3;
650 }
651 }
652 if (!status)
653 {
654 int* obsx = ((int*)(hmm->obsProb)) - 1;
655 int* obsy = ((int*)(hmm->obsProb)) - 2;
656
657 assert( (*obsx > 0) && (*obsy > 0) );
658
659 /* is good distribution? */
660 if ( (obs_info->obs_x > (*obsx) ) || (obs_info->obs_y > (*obsy) ) )
661 status = 3;
662 }
663
664 /* if bad status - do reallocation actions */
665 assert( (status == 0) || (status == 3) );
666
667 if ( status )
668 {
669 float** tmp = hmm->obsProb;
670 float* tmpf;
671
672 /* distribute pointers of ehmm->obsProb */
673 for( i = 0; i < hmm->num_states; i++ )
674 {
675 hmm->u.ehmm[i].obsProb = tmp;
676 tmp += obs_info->obs_y;
677 }
678
679 tmpf = (float*)tmp;
680
681 /* distribute pointers of ehmm->obsProb[j] */
682 for( i = 0; i < hmm->num_states; i++ )
683 {
684 CvEHMM* ehmm = &( hmm->u.ehmm[i] );
685
686 for( j = 0; j < obs_info->obs_y; j++ )
687 {
688 ehmm->obsProb[j] = tmpf;
689 tmpf += ehmm->num_states * obs_info->obs_x;
690 }
691 }
692 }/* end of pointer distribution */
693
694 #if 1
695 {
696 #define MAX_BUF_SIZE 1200
697 float local_log_mix_prob[MAX_BUF_SIZE];
698 double local_mix_prob[MAX_BUF_SIZE];
699 int vect_size = obs_info->obs_size;
700 CvStatus res = CV_NO_ERR;
701
702 float* log_mix_prob = local_log_mix_prob;
703 double* mix_prob = local_mix_prob;
704
705 int max_size = 0;
706 int obs_x = obs_info->obs_x;
707
708 /* calculate temporary buffer size */
709 for( i = 0; i < hmm->num_states; i++ )
710 {
711 CvEHMM* ehmm = &(hmm->u.ehmm[i]);
712 CvEHMMState* state = ehmm->u.state;
713
714 int max_mix = 0;
715 for( j = 0; j < ehmm->num_states; j++ )
716 {
717 int t = state[j].num_mix;
718 if( max_mix < t ) max_mix = t;
719 }
720 max_mix *= ehmm->num_states;
721 if( max_size < max_mix ) max_size = max_mix;
722 }
723
724 max_size *= obs_x * vect_size;
725
726 /* allocate buffer */
727 if( max_size > MAX_BUF_SIZE )
728 {
729 log_mix_prob = (float*)cvAlloc( max_size*(sizeof(float) + sizeof(double)));
730 if( !log_mix_prob ) return CV_OUTOFMEM_ERR;
731 mix_prob = (double*)(log_mix_prob + max_size);
732 }
733
734 memset( log_mix_prob, 0, max_size*sizeof(float));
735
736 /*****************computing probabilities***********************/
737
738 /* loop through external states */
739 for( i = 0; i < hmm->num_states; i++ )
740 {
741 CvEHMM* ehmm = &(hmm->u.ehmm[i]);
742 CvEHMMState* state = ehmm->u.state;
743
744 int max_mix = 0;
745 int n_states = ehmm->num_states;
746
747 /* determine maximal number of mixtures (again) */
748 for( j = 0; j < ehmm->num_states; j++ )
749 {
750 int t = state[j].num_mix;
751 if( max_mix < t ) max_mix = t;
752 }
753
754 /* loop through rows of the observation matrix */
755 for( j = 0; j < obs_info->obs_y; j++ )
756 {
757 int m, n;
758
759 float* obs = obs_info->obs + j * obs_x * vect_size;
760 float* log_mp = max_mix > 1 ? log_mix_prob : ehmm->obsProb[j];
761 double* mp = mix_prob;
762
763 /* several passes are done below */
764
765 /* 1. calculate logarithms of probabilities for each mixture */
766
767 /* loop through mixtures */
768 for( m = 0; m < max_mix; m++ )
769 {
770 /* set pointer to first observation in the line */
771 float* vect = obs;
772
773 /* cycles through obseravtions in the line */
774 for( n = 0; n < obs_x; n++, vect += vect_size, log_mp += n_states )
775 {
776 int k, l;
777 for( l = 0; l < n_states; l++ )
778 {
779 if( state[l].num_mix > m )
780 {
781 float* mu = state[l].mu + m*vect_size;
782 float* inv_var = state[l].inv_var + m*vect_size;
783 double prob = -state[l].log_var_val[m];
784 for( k = 0; k < vect_size; k++ )
785 {
786 double t = (vect[k] - mu[k])*inv_var[k];
787 prob -= t*t;
788 }
789 log_mp[l] = MAX( (float)prob, -500 );
790 }
791 }
792 }
793 }
794
795 /* skip the rest if there is a single mixture */
796 if( max_mix == 1 ) continue;
797
798 /* 2. calculate exponent of log_mix_prob
799 (i.e. probability for each mixture) */
800 cvbFastExp( log_mix_prob, mix_prob, max_mix * obs_x * n_states );
801
802 /* 3. sum all mixtures with weights */
803 /* 3a. first mixture - simply scale by weight */
804 for( n = 0; n < obs_x; n++, mp += n_states )
805 {
806 int l;
807 for( l = 0; l < n_states; l++ )
808 {
809 mp[l] *= state[l].weight[0];
810 }
811 }
812
813 /* 3b. add other mixtures */
814 for( m = 1; m < max_mix; m++ )
815 {
816 int ofs = -m*obs_x*n_states;
817 for( n = 0; n < obs_x; n++, mp += n_states )
818 {
819 int l;
820 for( l = 0; l < n_states; l++ )
821 {
822 if( m < state[l].num_mix )
823 {
824 mp[l + ofs] += mp[l] * state[l].weight[m];
825 }
826 }
827 }
828 }
829
830 /* 4. Put logarithms of summary probabilities to the destination matrix */
831 cvbFastLog( mix_prob, ehmm->obsProb[j], obs_x * n_states );
832 }
833 }
834
835 if( log_mix_prob != local_log_mix_prob ) cvFree( &log_mix_prob );
836 return res;
837 #undef MAX_BUF_SIZE
838 }
839 #else
840 for( i = 0; i < hmm->num_states; i++ )
841 {
842 CvEHMM* ehmm = &(hmm->u.ehmm[i]);
843 CvEHMMState* state = ehmm->u.state;
844
845 for( j = 0; j < obs_info->obs_y; j++ )
846 {
847 int k,m;
848
849 int obs_index = j * obs_info->obs_x;
850
851 float* B = ehmm->obsProb[j];
852
853 /* cycles through obs and states */
854 for( k = 0; k < obs_info->obs_x; k++ )
855 {
856 CvVect32f vect = (obs_info->obs) + (obs_index + k) * vect_size;
857
858 float* matr_line = B + k * ehmm->num_states;
859
860 for( m = 0; m < ehmm->num_states; m++ )
861 {
862 matr_line[m] = icvComputeGaussMixture( vect, state[m].mu, state[m].inv_var,
863 state[m].log_var_val, vect_size, state[m].weight,
864 state[m].num_mix );
865 }
866 }
867 }
868 }
869 #endif
870 }
871
872
873 /*F///////////////////////////////////////////////////////////////////////////////////////
874 // Name: EstimateTransProb
875 // Purpose: The function calculates the state and super state transition probabilities
876 // of the model given the images,
877 // the state segmentation and the input parameters
878 // Context:
879 // Parameters: obs_info_array - array of pointers to image observations
880 // num_img - length of above array
881 // hmm - pointer to HMM structure
882 // Returns: void
883 //
884 // Notes:
885 //F*/
886 static CvStatus CV_STDCALL
icvEstimateTransProb(CvImgObsInfo ** obs_info_array,int num_img,CvEHMM * hmm)887 icvEstimateTransProb( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm )
888 {
889 int i, j, k;
890
891 CvEHMMState* first_state = hmm->u.ehmm->u.state;
892 /* as a counter we will use transP matrix */
893
894 /* initialization */
895
896 /* clear transP */
897 icvSetZero_32f( hmm->transP, hmm->num_states, hmm->num_states );
898 for (i = 0; i < hmm->num_states; i++ )
899 {
900 icvSetZero_32f( hmm->u.ehmm[i].transP , hmm->u.ehmm[i].num_states, hmm->u.ehmm[i].num_states );
901 }
902
903 /* compute the counters */
904 for (i = 0; i < num_img; i++)
905 {
906 int counter = 0;
907 CvImgObsInfo* info = obs_info_array[i];
908
909 for (j = 0; j < info->obs_y; j++)
910 {
911 for (k = 0; k < info->obs_x; k++, counter++)
912 {
913 /* compute how many transitions from state to state
914 occured both in horizontal and vertical direction */
915 int superstate, state;
916 int nextsuperstate, nextstate;
917 int begin_ind;
918
919 superstate = info->state[2 * counter];
920 begin_ind = (int)(hmm->u.ehmm[superstate].u.state - first_state);
921 state = info->state[ 2 * counter + 1] - begin_ind;
922
923 if (j < info->obs_y - 1)
924 {
925 int transP_size = hmm->num_states;
926
927 nextsuperstate = info->state[ 2*(counter + info->obs_x) ];
928
929 hmm->transP[superstate * transP_size + nextsuperstate] += 1;
930 }
931
932 if (k < info->obs_x - 1)
933 {
934 int transP_size = hmm->u.ehmm[superstate].num_states;
935
936 nextstate = info->state[2*(counter+1) + 1] - begin_ind;
937 hmm->u.ehmm[superstate].transP[ state * transP_size + nextstate] += 1;
938 }
939 }
940 }
941 }
942 /* estimate superstate matrix */
943 for( i = 0; i < hmm->num_states; i++)
944 {
945 float total = 0;
946 float inv_total;
947 for( j = 0; j < hmm->num_states; j++)
948 {
949 total += hmm->transP[i * hmm->num_states + j];
950 }
951 //assert( total );
952
953 inv_total = total ? 1.f/total : 0;
954
955 for( j = 0; j < hmm->num_states; j++)
956 {
957 hmm->transP[i * hmm->num_states + j] =
958 hmm->transP[i * hmm->num_states + j] ?
959 (float)log( hmm->transP[i * hmm->num_states + j] * inv_total ) : -BIG_FLT;
960 }
961 }
962
963 /* estimate other matrices */
964 for( k = 0; k < hmm->num_states; k++ )
965 {
966 CvEHMM* ehmm = &(hmm->u.ehmm[k]);
967
968 for( i = 0; i < ehmm->num_states; i++)
969 {
970 float total = 0;
971 float inv_total;
972 for( j = 0; j < ehmm->num_states; j++)
973 {
974 total += ehmm->transP[i*ehmm->num_states + j];
975 }
976 //assert( total );
977 inv_total = total ? 1.f/total : 0;
978
979 for( j = 0; j < ehmm->num_states; j++)
980 {
981 ehmm->transP[i * ehmm->num_states + j] =
982 (ehmm->transP[i * ehmm->num_states + j]) ?
983 (float)log( ehmm->transP[i * ehmm->num_states + j] * inv_total) : -BIG_FLT ;
984 }
985 }
986 }
987 return CV_NO_ERR;
988 }
989
990
991 /*F///////////////////////////////////////////////////////////////////////////////////////
992 // Name: MixSegmL2
993 // Purpose: The function implements the mixture segmentation of the states of the
994 // embedded HMM
995 // Context: used with the Viterbi training of the embedded HMM
996 //
997 // Parameters:
998 // obs_info_array
999 // num_img
1000 // hmm
1001 // Returns: void
1002 //
1003 // Notes:
1004 //F*/
1005 static CvStatus CV_STDCALL
icvMixSegmL2(CvImgObsInfo ** obs_info_array,int num_img,CvEHMM * hmm)1006 icvMixSegmL2( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm )
1007 {
1008 int k, i, j, m;
1009
1010 CvEHMMState* state = hmm->u.ehmm[0].u.state;
1011
1012
1013 for (k = 0; k < num_img; k++)
1014 {
1015 int counter = 0;
1016 CvImgObsInfo* info = obs_info_array[k];
1017
1018 for (i = 0; i < info->obs_y; i++)
1019 {
1020 for (j = 0; j < info->obs_x; j++, counter++)
1021 {
1022 int e_state = info->state[2 * counter + 1];
1023 float min_dist;
1024
1025 min_dist = icvSquareDistance((info->obs) + (counter * info->obs_size),
1026 state[e_state].mu, info->obs_size);
1027 info->mix[counter] = 0;
1028
1029 for (m = 1; m < state[e_state].num_mix; m++)
1030 {
1031 float dist=icvSquareDistance( (info->obs) + (counter * info->obs_size),
1032 state[e_state].mu + m * info->obs_size,
1033 info->obs_size);
1034 if (dist < min_dist)
1035 {
1036 min_dist = dist;
1037 /* assign mixture with smallest distance */
1038 info->mix[counter] = m;
1039 }
1040 }
1041 }
1042 }
1043 }
1044 return CV_NO_ERR;
1045 }
1046
1047 /*
1048 CvStatus icvMixSegmProb(CvImgObsInfo* obs_info, int num_img, CvEHMM* hmm )
1049 {
1050 int k, i, j, m;
1051
1052 CvEHMMState* state = hmm->ehmm[0].state_info;
1053
1054
1055 for (k = 0; k < num_img; k++)
1056 {
1057 int counter = 0;
1058 CvImgObsInfo* info = obs_info + k;
1059
1060 for (i = 0; i < info->obs_y; i++)
1061 {
1062 for (j = 0; j < info->obs_x; j++, counter++)
1063 {
1064 int e_state = info->in_state[counter];
1065 float max_prob;
1066
1067 max_prob = icvComputeUniModeGauss( info->obs[counter], state[e_state].mu[0],
1068 state[e_state].inv_var[0],
1069 state[e_state].log_var[0],
1070 info->obs_size );
1071 info->mix[counter] = 0;
1072
1073 for (m = 1; m < state[e_state].num_mix; m++)
1074 {
1075 float prob=icvComputeUniModeGauss(info->obs[counter], state[e_state].mu[m],
1076 state[e_state].inv_var[m],
1077 state[e_state].log_var[m],
1078 info->obs_size);
1079 if (prob > max_prob)
1080 {
1081 max_prob = prob;
1082 // assign mixture with greatest probability.
1083 info->mix[counter] = m;
1084 }
1085 }
1086 }
1087 }
1088 }
1089
1090 return CV_NO_ERR;
1091 }
1092 */
1093 static CvStatus CV_STDCALL
icvViterbiSegmentation(int num_states,int,CvMatr32f transP,CvMatr32f B,int start_obs,int prob_type,int ** q,int min_num_obs,int max_num_obs,float * prob)1094 icvViterbiSegmentation( int num_states, int /*num_obs*/, CvMatr32f transP,
1095 CvMatr32f B, int start_obs, int prob_type,
1096 int** q, int min_num_obs, int max_num_obs,
1097 float* prob )
1098 {
1099 // memory allocation
1100 int i, j, last_obs;
1101 int m_HMMType = _CV_ERGODIC; /* _CV_CAUSAL or _CV_ERGODIC */
1102
1103 int m_ProbType = prob_type; /* _CV_LAST_STATE or _CV_BEST_STATE */
1104
1105 int m_minNumObs = min_num_obs; /*??*/
1106 int m_maxNumObs = max_num_obs; /*??*/
1107
1108 int m_numStates = num_states;
1109
1110 float* m_pi = (float*)cvAlloc( num_states* sizeof(float) );
1111 CvMatr32f m_a = transP;
1112
1113 // offset brobability matrix to starting observation
1114 CvMatr32f m_b = B + start_obs * num_states;
1115 //so m_xl will not be used more
1116
1117 //m_xl = start_obs;
1118
1119 /* if (muDur != NULL){
1120 m_d = new int[m_numStates];
1121 m_l = new double[m_numStates];
1122 for (i = 0; i < m_numStates; i++){
1123 m_l[i] = muDur[i];
1124 }
1125 }
1126 else{
1127 m_d = NULL;
1128 m_l = NULL;
1129 }
1130 */
1131
1132 CvMatr32f m_Gamma = icvCreateMatrix_32f( num_states, m_maxNumObs );
1133 int* m_csi = (int*)cvAlloc( num_states * m_maxNumObs * sizeof(int) );
1134
1135 //stores maximal result for every ending observation */
1136 CvVect32f m_MaxGamma = prob;
1137
1138
1139 // assert( m_xl + max_num_obs <= num_obs );
1140
1141 /*??m_q = new int*[m_maxNumObs - m_minNumObs];
1142 ??for (i = 0; i < m_maxNumObs - m_minNumObs; i++)
1143 ?? m_q[i] = new int[m_minNumObs + i + 1];
1144 */
1145
1146 /******************************************************************/
1147 /* Viterbi initialization */
1148 /* set initial state probabilities, in logarithmic scale */
1149 for (i = 0; i < m_numStates; i++)
1150 {
1151 m_pi[i] = -BIG_FLT;
1152 }
1153 m_pi[0] = 0.0f;
1154
1155 for (i = 0; i < num_states; i++)
1156 {
1157 m_Gamma[0 * num_states + i] = m_pi[i] + m_b[0 * num_states + i];
1158 m_csi[0 * num_states + i] = 0;
1159 }
1160
1161 /******************************************************************/
1162 /* Viterbi recursion */
1163
1164 if ( m_HMMType == _CV_CAUSAL ) //causal model
1165 {
1166 int t,j;
1167
1168 for (t = 1 ; t < m_maxNumObs; t++)
1169 {
1170 // evaluate self-to-self transition for state 0
1171 m_Gamma[t * num_states + 0] = m_Gamma[(t-1) * num_states + 0] + m_a[0];
1172 m_csi[t * num_states + 0] = 0;
1173
1174 for (j = 1; j < num_states; j++)
1175 {
1176 float self = m_Gamma[ (t-1) * num_states + j] + m_a[ j * num_states + j];
1177 float prev = m_Gamma[ (t-1) * num_states +(j-1)] + m_a[ (j-1) * num_states + j];
1178
1179 if ( prev > self )
1180 {
1181 m_csi[t * num_states + j] = j-1;
1182 m_Gamma[t * num_states + j] = prev;
1183 }
1184 else
1185 {
1186 m_csi[t * num_states + j] = j;
1187 m_Gamma[t * num_states + j] = self;
1188 }
1189
1190 m_Gamma[t * num_states + j] = m_Gamma[t * num_states + j] + m_b[t * num_states + j];
1191 }
1192 }
1193 }
1194 else if ( m_HMMType == _CV_ERGODIC ) //ergodic model
1195 {
1196 int t;
1197 for (t = 1 ; t < m_maxNumObs; t++)
1198 {
1199 for (j = 0; j < num_states; j++)
1200 {
1201 int i;
1202 m_Gamma[ t*num_states + j] = m_Gamma[(t-1) * num_states + 0] + m_a[0*num_states+j];
1203 m_csi[t *num_states + j] = 0;
1204
1205 for (i = 1; i < num_states; i++)
1206 {
1207 float currGamma = m_Gamma[(t-1) *num_states + i] + m_a[i *num_states + j];
1208 if (currGamma > m_Gamma[t *num_states + j])
1209 {
1210 m_Gamma[t * num_states + j] = currGamma;
1211 m_csi[t * num_states + j] = i;
1212 }
1213 }
1214 m_Gamma[t *num_states + j] = m_Gamma[t *num_states + j] + m_b[t * num_states + j];
1215 }
1216 }
1217 }
1218
1219 for( last_obs = m_minNumObs-1, i = 0; last_obs < m_maxNumObs; last_obs++, i++ )
1220 {
1221 int t;
1222
1223 /******************************************************************/
1224 /* Viterbi termination */
1225
1226 if ( m_ProbType == _CV_LAST_STATE )
1227 {
1228 m_MaxGamma[i] = m_Gamma[last_obs * num_states + num_states - 1];
1229 q[i][last_obs] = num_states - 1;
1230 }
1231 else if( m_ProbType == _CV_BEST_STATE )
1232 {
1233 int k;
1234 q[i][last_obs] = 0;
1235 m_MaxGamma[i] = m_Gamma[last_obs * num_states + 0];
1236
1237 for(k = 1; k < num_states; k++)
1238 {
1239 if ( m_Gamma[last_obs * num_states + k] > m_MaxGamma[i] )
1240 {
1241 m_MaxGamma[i] = m_Gamma[last_obs * num_states + k];
1242 q[i][last_obs] = k;
1243 }
1244 }
1245 }
1246
1247 /******************************************************************/
1248 /* Viterbi backtracking */
1249 for (t = last_obs-1; t >= 0; t--)
1250 {
1251 q[i][t] = m_csi[(t+1) * num_states + q[i][t+1] ];
1252 }
1253 }
1254
1255 /* memory free */
1256 cvFree( &m_pi );
1257 cvFree( &m_csi );
1258 icvDeleteMatrix( m_Gamma );
1259
1260 return CV_NO_ERR;
1261 }
1262
1263 /*F///////////////////////////////////////////////////////////////////////////////////////
1264 // Name: icvEViterbi
1265 // Purpose: The function calculates the embedded Viterbi algorithm
1266 // for 1 image
1267 // Context:
1268 // Parameters:
1269 // obs_info - observations
1270 // hmm - HMM
1271 //
1272 // Returns: the Embedded Viterbi probability (float)
1273 // and do state segmentation of observations
1274 //
1275 // Notes:
1276 //F*/
icvEViterbi(CvImgObsInfo * obs_info,CvEHMM * hmm)1277 static float CV_STDCALL icvEViterbi( CvImgObsInfo* obs_info, CvEHMM* hmm )
1278 {
1279 int i, j, counter;
1280 float log_likelihood;
1281
1282 float inv_obs_x = 1.f / obs_info->obs_x;
1283
1284 CvEHMMState* first_state = hmm->u.ehmm->u.state;
1285
1286 /* memory allocation for superB */
1287 CvMatr32f superB = icvCreateMatrix_32f(hmm->num_states, obs_info->obs_y );
1288
1289 /* memory allocation for q */
1290 int*** q = (int***)cvAlloc( hmm->num_states * sizeof(int**) );
1291 int* super_q = (int*)cvAlloc( obs_info->obs_y * sizeof(int) );
1292
1293 for (i = 0; i < hmm->num_states; i++)
1294 {
1295 q[i] = (int**)cvAlloc( obs_info->obs_y * sizeof(int*) );
1296
1297 for (j = 0; j < obs_info->obs_y ; j++)
1298 {
1299 q[i][j] = (int*)cvAlloc( obs_info->obs_x * sizeof(int) );
1300 }
1301 }
1302
1303 /* start Viterbi segmentation */
1304 for (i = 0; i < hmm->num_states; i++)
1305 {
1306 CvEHMM* ehmm = &(hmm->u.ehmm[i]);
1307
1308 for (j = 0; j < obs_info->obs_y; j++)
1309 {
1310 float max_gamma;
1311
1312 /* 1D HMM Viterbi segmentation */
1313 icvViterbiSegmentation( ehmm->num_states, obs_info->obs_x,
1314 ehmm->transP, ehmm->obsProb[j], 0,
1315 _CV_LAST_STATE, &q[i][j], obs_info->obs_x,
1316 obs_info->obs_x, &max_gamma);
1317
1318 superB[j * hmm->num_states + i] = max_gamma * inv_obs_x;
1319 }
1320 }
1321
1322 /* perform global Viterbi segmentation (i.e. process higher-level HMM) */
1323
1324 icvViterbiSegmentation( hmm->num_states, obs_info->obs_y,
1325 hmm->transP, superB, 0,
1326 _CV_LAST_STATE, &super_q, obs_info->obs_y,
1327 obs_info->obs_y, &log_likelihood );
1328
1329 log_likelihood /= obs_info->obs_y ;
1330
1331
1332 counter = 0;
1333 /* assign new state to observation vectors */
1334 for (i = 0; i < obs_info->obs_y; i++)
1335 {
1336 for (j = 0; j < obs_info->obs_x; j++, counter++)
1337 {
1338 int superstate = super_q[i];
1339 int state = (int)(hmm->u.ehmm[superstate].u.state - first_state);
1340
1341 obs_info->state[2 * counter] = superstate;
1342 obs_info->state[2 * counter + 1] = state + q[superstate][i][j];
1343 }
1344 }
1345
1346 /* memory deallocation for superB */
1347 icvDeleteMatrix( superB );
1348
1349 /*memory deallocation for q */
1350 for (i = 0; i < hmm->num_states; i++)
1351 {
1352 for (j = 0; j < obs_info->obs_y ; j++)
1353 {
1354 cvFree( &q[i][j] );
1355 }
1356 cvFree( &q[i] );
1357 }
1358
1359 cvFree( &q );
1360 cvFree( &super_q );
1361
1362 return log_likelihood;
1363 }
1364
1365 static CvStatus CV_STDCALL
icvEstimateHMMStateParams(CvImgObsInfo ** obs_info_array,int num_img,CvEHMM * hmm)1366 icvEstimateHMMStateParams( CvImgObsInfo** obs_info_array, int num_img, CvEHMM* hmm )
1367 {
1368 /* compute gamma, weights, means, vars */
1369 int k, i, j, m;
1370 int total = 0;
1371 int vect_len = obs_info_array[0]->obs_size;
1372
1373 float start_log_var_val = LN2PI * vect_len;
1374
1375 CvVect32f tmp_vect = icvCreateVector_32f( vect_len );
1376
1377 CvEHMMState* first_state = hmm->u.ehmm[0].u.state;
1378
1379 assert( sizeof(float) == sizeof(int) );
1380
1381 for(i = 0; i < hmm->num_states; i++ )
1382 {
1383 total+= hmm->u.ehmm[i].num_states;
1384 }
1385
1386 /***************Gamma***********************/
1387 /* initialize gamma */
1388 for( i = 0; i < total; i++ )
1389 {
1390 for (m = 0; m < first_state[i].num_mix; m++)
1391 {
1392 ((int*)(first_state[i].weight))[m] = 0;
1393 }
1394 }
1395
1396 /* maybe gamma must be computed in mixsegm process ?? */
1397
1398 /* compute gamma */
1399 for (k = 0; k < num_img; k++)
1400 {
1401 CvImgObsInfo* info = obs_info_array[k];
1402 int num_obs = info->obs_y * info->obs_x;
1403
1404 for (i = 0; i < num_obs; i++)
1405 {
1406 int state, mixture;
1407 state = info->state[2*i + 1];
1408 mixture = info->mix[i];
1409 /* computes gamma - number of observations corresponding
1410 to every mixture of every state */
1411 ((int*)(first_state[state].weight))[mixture] += 1;
1412 }
1413 }
1414 /***************Mean and Var***********************/
1415 /* compute means and variances of every item */
1416 /* initially variance placed to inv_var */
1417 /* zero mean and variance */
1418 for (i = 0; i < total; i++)
1419 {
1420 memset( (void*)first_state[i].mu, 0, first_state[i].num_mix * vect_len *
1421 sizeof(float) );
1422 memset( (void*)first_state[i].inv_var, 0, first_state[i].num_mix * vect_len *
1423 sizeof(float) );
1424 }
1425
1426 /* compute sums */
1427 for (i = 0; i < num_img; i++)
1428 {
1429 CvImgObsInfo* info = obs_info_array[i];
1430 int total_obs = info->obs_x * info->obs_y;
1431
1432 float* vector = info->obs;
1433
1434 for (j = 0; j < total_obs; j++, vector+=vect_len )
1435 {
1436 int state = info->state[2 * j + 1];
1437 int mixture = info->mix[j];
1438
1439 CvVect32f mean = first_state[state].mu + mixture * vect_len;
1440 CvVect32f mean2 = first_state[state].inv_var + mixture * vect_len;
1441
1442 icvAddVector_32f( mean, vector, mean, vect_len );
1443 for( k = 0; k < vect_len; k++ )
1444 mean2[k] += vector[k]*vector[k];
1445 }
1446 }
1447
1448 /*compute the means and variances */
1449 /* assume gamma already computed */
1450 for (i = 0; i < total; i++)
1451 {
1452 CvEHMMState* state = &(first_state[i]);
1453
1454 for (m = 0; m < state->num_mix; m++)
1455 {
1456 int k;
1457 CvVect32f mu = state->mu + m * vect_len;
1458 CvVect32f invar = state->inv_var + m * vect_len;
1459
1460 if ( ((int*)state->weight)[m] > 1)
1461 {
1462 float inv_gamma = 1.f/((int*)(state->weight))[m];
1463
1464 icvScaleVector_32f( mu, mu, vect_len, inv_gamma);
1465 icvScaleVector_32f( invar, invar, vect_len, inv_gamma);
1466 }
1467
1468 icvMulVectors_32f(mu, mu, tmp_vect, vect_len);
1469 icvSubVector_32f( invar, tmp_vect, invar, vect_len);
1470
1471 /* low bound of variance - 100 (Ara's experimental result) */
1472 for( k = 0; k < vect_len; k++ )
1473 {
1474 invar[k] = (invar[k] > 100.f) ? invar[k] : 100.f;
1475 }
1476
1477 /* compute log_var */
1478 state->log_var_val[m] = start_log_var_val;
1479 for( k = 0; k < vect_len; k++ )
1480 {
1481 state->log_var_val[m] += (float)log( invar[k] );
1482 }
1483
1484 /* SMOLI 27.10.2000 */
1485 state->log_var_val[m] *= 0.5;
1486
1487
1488 /* compute inv_var = 1/sqrt(2*variance) */
1489 icvScaleVector_32f(invar, invar, vect_len, 2.f );
1490 cvbInvSqrt( invar, invar, vect_len );
1491 }
1492 }
1493
1494 /***************Weights***********************/
1495 /* normilize gammas - i.e. compute mixture weights */
1496
1497 //compute weights
1498 for (i = 0; i < total; i++)
1499 {
1500 int gamma_total = 0;
1501 float norm;
1502
1503 for (m = 0; m < first_state[i].num_mix; m++)
1504 {
1505 gamma_total += ((int*)(first_state[i].weight))[m];
1506 }
1507
1508 norm = gamma_total ? (1.f/(float)gamma_total) : 0.f;
1509
1510 for (m = 0; m < first_state[i].num_mix; m++)
1511 {
1512 first_state[i].weight[m] = ((int*)(first_state[i].weight))[m] * norm;
1513 }
1514 }
1515
1516 icvDeleteVector( tmp_vect);
1517 return CV_NO_ERR;
1518 }
1519
1520 /*
1521 CvStatus icvLightingCorrection8uC1R( uchar* img, CvSize roi, int src_step )
1522 {
1523 int i, j;
1524 int width = roi.width;
1525 int height = roi.height;
1526
1527 float x1, x2, y1, y2;
1528 int f[3] = {0, 0, 0};
1529 float a[3] = {0, 0, 0};
1530
1531 float h1;
1532 float h2;
1533
1534 float c1,c2;
1535
1536 float min = FLT_MAX;
1537 float max = -FLT_MAX;
1538 float correction;
1539
1540 float* float_img = icvAlloc( width * height * sizeof(float) );
1541
1542 x1 = width * (width + 1) / 2.0f; // Sum (1, ... , width)
1543 x2 = width * (width + 1 ) * (2 * width + 1) / 6.0f; // Sum (1^2, ... , width^2)
1544 y1 = height * (height + 1)/2.0f; // Sum (1, ... , width)
1545 y2 = height * (height + 1 ) * (2 * height + 1) / 6.0f; // Sum (1^2, ... , width^2)
1546
1547
1548 // extract grayvalues
1549 for (i = 0; i < height; i++)
1550 {
1551 for (j = 0; j < width; j++)
1552 {
1553 f[2] = f[2] + j * img[i*src_step + j];
1554 f[1] = f[1] + i * img[i*src_step + j];
1555 f[0] = f[0] + img[i*src_step + j];
1556 }
1557 }
1558
1559 h1 = (float)f[0] * (float)x1 / (float)width;
1560 h2 = (float)f[0] * (float)y1 / (float)height;
1561
1562 a[2] = ((float)f[2] - h1) / (float)(x2*height - x1*x1*height/(float)width);
1563 a[1] = ((float)f[1] - h2) / (float)(y2*width - y1*y1*width/(float)height);
1564 a[0] = (float)f[0]/(float)(width*height) - (float)y1*a[1]/(float)height -
1565 (float)x1*a[2]/(float)width;
1566
1567 for (i = 0; i < height; i++)
1568 {
1569 for (j = 0; j < width; j++)
1570 {
1571
1572 correction = a[0] + a[1]*(float)i + a[2]*(float)j;
1573
1574 float_img[i*width + j] = img[i*src_step + j] - correction;
1575
1576 if (float_img[i*width + j] < min) min = float_img[i*width+j];
1577 if (float_img[i*width + j] > max) max = float_img[i*width+j];
1578 }
1579 }
1580
1581 //rescaling to the range 0:255
1582 c2 = 0;
1583 if (max == min)
1584 c2 = 255.0f;
1585 else
1586 c2 = 255.0f/(float)(max - min);
1587
1588 c1 = (-(float)min)*c2;
1589
1590 for (i = 0; i < height; i++)
1591 {
1592 for (j = 0; j < width; j++)
1593 {
1594 int value = (int)floor(c2*float_img[i*width + j] + c1);
1595 if (value < 0) value = 0;
1596 if (value > 255) value = 255;
1597 img[i*src_step + j] = (uchar)value;
1598 }
1599 }
1600
1601 cvFree( &float_img );
1602 return CV_NO_ERR;
1603 }
1604
1605
1606 CvStatus icvLightingCorrection( icvImage* img )
1607 {
1608 CvSize roi;
1609 if ( img->type != IPL_DEPTH_8U || img->channels != 1 )
1610 return CV_BADFACTOR_ERR;
1611
1612 roi = _cvSize( img->roi.width, img->roi.height );
1613
1614 return _cvLightingCorrection8uC1R( img->data + img->roi.y * img->step + img->roi.x,
1615 roi, img->step );
1616
1617 }
1618
1619 */
1620
1621 CV_IMPL CvEHMM*
cvCreate2DHMM(int * state_number,int * num_mix,int obs_size)1622 cvCreate2DHMM( int *state_number, int *num_mix, int obs_size )
1623 {
1624 CvEHMM* hmm = 0;
1625
1626 CV_FUNCNAME( "cvCreate2DHMM" );
1627
1628 __BEGIN__;
1629
1630 IPPI_CALL( icvCreate2DHMM( &hmm, state_number, num_mix, obs_size ));
1631
1632 __END__;
1633
1634 return hmm;
1635 }
1636
1637 CV_IMPL void
cvRelease2DHMM(CvEHMM ** hmm)1638 cvRelease2DHMM( CvEHMM ** hmm )
1639 {
1640 CV_FUNCNAME( "cvRelease2DHMM" );
1641
1642 __BEGIN__;
1643
1644 IPPI_CALL( icvRelease2DHMM( hmm ));
1645 __END__;
1646 }
1647
1648 CV_IMPL CvImgObsInfo*
cvCreateObsInfo(CvSize num_obs,int obs_size)1649 cvCreateObsInfo( CvSize num_obs, int obs_size )
1650 {
1651 CvImgObsInfo *obs_info = 0;
1652
1653 CV_FUNCNAME( "cvCreateObsInfo" );
1654
1655 __BEGIN__;
1656
1657 IPPI_CALL( icvCreateObsInfo( &obs_info, num_obs, obs_size ));
1658
1659 __END__;
1660
1661 return obs_info;
1662 }
1663
1664 CV_IMPL void
cvReleaseObsInfo(CvImgObsInfo ** obs_info)1665 cvReleaseObsInfo( CvImgObsInfo ** obs_info )
1666 {
1667 CV_FUNCNAME( "cvReleaseObsInfo" );
1668
1669 __BEGIN__;
1670
1671 IPPI_CALL( icvReleaseObsInfo( obs_info ));
1672
1673 __END__;
1674 }
1675
1676
1677 CV_IMPL void
cvUniformImgSegm(CvImgObsInfo * obs_info,CvEHMM * hmm)1678 cvUniformImgSegm( CvImgObsInfo * obs_info, CvEHMM * hmm )
1679 {
1680 CV_FUNCNAME( "cvUniformImgSegm" );
1681
1682 __BEGIN__;
1683
1684 IPPI_CALL( icvUniformImgSegm( obs_info, hmm ));
1685 __CLEANUP__;
1686 __END__;
1687 }
1688
1689 CV_IMPL void
cvInitMixSegm(CvImgObsInfo ** obs_info_array,int num_img,CvEHMM * hmm)1690 cvInitMixSegm( CvImgObsInfo ** obs_info_array, int num_img, CvEHMM * hmm )
1691 {
1692 CV_FUNCNAME( "cvInitMixSegm" );
1693
1694 __BEGIN__;
1695
1696 IPPI_CALL( icvInitMixSegm( obs_info_array, num_img, hmm ));
1697
1698 __END__;
1699 }
1700
1701 CV_IMPL void
cvEstimateHMMStateParams(CvImgObsInfo ** obs_info_array,int num_img,CvEHMM * hmm)1702 cvEstimateHMMStateParams( CvImgObsInfo ** obs_info_array, int num_img, CvEHMM * hmm )
1703 {
1704 CV_FUNCNAME( "cvEstimateHMMStateParams" );
1705
1706 __BEGIN__;
1707
1708 IPPI_CALL( icvEstimateHMMStateParams( obs_info_array, num_img, hmm ));
1709
1710 __END__;
1711 }
1712
1713 CV_IMPL void
cvEstimateTransProb(CvImgObsInfo ** obs_info_array,int num_img,CvEHMM * hmm)1714 cvEstimateTransProb( CvImgObsInfo ** obs_info_array, int num_img, CvEHMM * hmm )
1715 {
1716 CV_FUNCNAME( "cvEstimateTransProb" );
1717
1718 __BEGIN__;
1719
1720 IPPI_CALL( icvEstimateTransProb( obs_info_array, num_img, hmm ));
1721
1722 __END__;
1723
1724 }
1725
1726 CV_IMPL void
cvEstimateObsProb(CvImgObsInfo * obs_info,CvEHMM * hmm)1727 cvEstimateObsProb( CvImgObsInfo * obs_info, CvEHMM * hmm )
1728 {
1729 CV_FUNCNAME( "cvEstimateObsProb" );
1730
1731 __BEGIN__;
1732
1733 IPPI_CALL( icvEstimateObsProb( obs_info, hmm ));
1734
1735 __END__;
1736 }
1737
1738 CV_IMPL float
cvEViterbi(CvImgObsInfo * obs_info,CvEHMM * hmm)1739 cvEViterbi( CvImgObsInfo * obs_info, CvEHMM * hmm )
1740 {
1741 float result = FLT_MAX;
1742
1743 CV_FUNCNAME( "cvEViterbi" );
1744
1745 __BEGIN__;
1746
1747 if( (obs_info == NULL) || (hmm == NULL) )
1748 CV_ERROR( CV_BadDataPtr, "Null pointer." );
1749
1750 result = icvEViterbi( obs_info, hmm );
1751
1752 __END__;
1753
1754 return result;
1755 }
1756
1757 CV_IMPL void
cvMixSegmL2(CvImgObsInfo ** obs_info_array,int num_img,CvEHMM * hmm)1758 cvMixSegmL2( CvImgObsInfo ** obs_info_array, int num_img, CvEHMM * hmm )
1759 {
1760 CV_FUNCNAME( "cvMixSegmL2" );
1761
1762 __BEGIN__;
1763
1764 IPPI_CALL( icvMixSegmL2( obs_info_array, num_img, hmm ));
1765
1766 __END__;
1767 }
1768
1769 /* End of file */
1770
1771