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 //
12 // Copyright (C) 2000, Intel Corporation, all rights reserved.
13 // Third party copyrights are property of their respective owners.
14 //
15 // Redistribution and use in source and binary forms, with or without modification,
16 // are permitted provided that the following conditions are met:
17 //
18 // * Redistribution's of source code must retain the above copyright notice,
19 // this list of conditions and the following disclaimer.
20 //
21 // * Redistribution's in binary form must reproduce the above copyright notice,
22 // this list of conditions and the following disclaimer in the documentation
23 // and/or other materials provided with the distribution.
24 //
25 // * The name of Intel Corporation may not be used to endorse or promote products
26 // derived from this software without specific prior written permission.
27 //
28 // This software is provided by the copyright holders and contributors "as is" and
29 // any express or implied warranties, including, but not limited to, the implied
30 // warranties of merchantability and fitness for a particular purpose are disclaimed.
31 // In no event shall the Intel Corporation or contributors be liable for any direct,
32 // indirect, incidental, special, exemplary, or consequential damages
33 // (including, but not limited to, procurement of substitute goods or services;
34 // loss of use, data, or profits; or business interruption) however caused
35 // and on any theory of liability, whether in contract, strict liability,
36 // or tort (including negligence or otherwise) arising in any way out of
37 // the use of this software, even if advised of the possibility of such damage.
38 //
39 //M*/
40
41 #include "_ml.h"
42
43
CvStatModel()44 CvStatModel::CvStatModel()
45 {
46 default_model_name = "my_stat_model";
47 }
48
49
~CvStatModel()50 CvStatModel::~CvStatModel()
51 {
52 clear();
53 }
54
55
clear()56 void CvStatModel::clear()
57 {
58 }
59
60
save(const char * filename,const char * name)61 void CvStatModel::save( const char* filename, const char* name )
62 {
63 CvFileStorage* fs = 0;
64
65 CV_FUNCNAME( "CvStatModel::save" );
66
67 __BEGIN__;
68
69 CV_CALL( fs = cvOpenFileStorage( filename, 0, CV_STORAGE_WRITE ));
70 if( !fs )
71 CV_ERROR( CV_StsError, "Could not open the file storage. Check the path and permissions" );
72
73 write( fs, name ? name : default_model_name );
74
75 __END__;
76
77 cvReleaseFileStorage( &fs );
78 }
79
80
load(const char * filename,const char * name)81 void CvStatModel::load( const char* filename, const char* name )
82 {
83 CvFileStorage* fs = 0;
84
85 CV_FUNCNAME( "CvStatModel::load" );
86
87 __BEGIN__;
88
89 CvFileNode* model_node = 0;
90
91 CV_CALL( fs = cvOpenFileStorage( filename, 0, CV_STORAGE_READ ));
92 if( !fs )
93 EXIT;
94
95 if( name )
96 model_node = cvGetFileNodeByName( fs, 0, name );
97 else
98 {
99 CvFileNode* root = cvGetRootFileNode( fs );
100 if( root->data.seq->total > 0 )
101 model_node = (CvFileNode*)cvGetSeqElem( root->data.seq, 0 );
102 }
103
104 read( fs, model_node );
105
106 __END__;
107
108 cvReleaseFileStorage( &fs );
109 }
110
111
write(CvFileStorage *,const char *)112 void CvStatModel::write( CvFileStorage*, const char* )
113 {
114 OPENCV_ERROR( CV_StsNotImplemented, "CvStatModel::write", "" );
115 }
116
117
read(CvFileStorage *,CvFileNode *)118 void CvStatModel::read( CvFileStorage*, CvFileNode* )
119 {
120 OPENCV_ERROR( CV_StsNotImplemented, "CvStatModel::read", "" );
121 }
122
123
124 /* Calculates upper triangular matrix S, where A is a symmetrical matrix A=S'*S */
cvChol(CvMat * A,CvMat * S)125 CV_IMPL void cvChol( CvMat* A, CvMat* S )
126 {
127 int dim = A->rows;
128
129 int i, j, k;
130 float sum;
131
132 for( i = 0; i < dim; i++ )
133 {
134 for( j = 0; j < i; j++ )
135 CV_MAT_ELEM(*S, float, i, j) = 0;
136
137 sum = 0;
138 for( k = 0; k < i; k++ )
139 sum += CV_MAT_ELEM(*S, float, k, i) * CV_MAT_ELEM(*S, float, k, i);
140
141 CV_MAT_ELEM(*S, float, i, i) = (float)sqrt(CV_MAT_ELEM(*A, float, i, i) - sum);
142
143 for( j = i + 1; j < dim; j++ )
144 {
145 sum = 0;
146 for( k = 0; k < i; k++ )
147 sum += CV_MAT_ELEM(*S, float, k, i) * CV_MAT_ELEM(*S, float, k, j);
148
149 CV_MAT_ELEM(*S, float, i, j) =
150 (CV_MAT_ELEM(*A, float, i, j) - sum) / CV_MAT_ELEM(*S, float, i, i);
151
152 }
153 }
154 }
155
156 /* Generates <sample> from multivariate normal distribution, where <mean> - is an
157 average row vector, <cov> - symmetric covariation matrix */
cvRandMVNormal(CvMat * mean,CvMat * cov,CvMat * sample,CvRNG * rng)158 CV_IMPL void cvRandMVNormal( CvMat* mean, CvMat* cov, CvMat* sample, CvRNG* rng )
159 {
160 int dim = sample->cols;
161 int amount = sample->rows;
162
163 CvRNG state = rng ? *rng : cvRNG(time(0));
164 cvRandArr(&state, sample, CV_RAND_NORMAL, cvScalarAll(0), cvScalarAll(1) );
165
166 CvMat* utmat = cvCreateMat(dim, dim, sample->type);
167 CvMat* vect = cvCreateMatHeader(1, dim, sample->type);
168
169 cvChol(cov, utmat);
170
171 int i;
172 for( i = 0; i < amount; i++ )
173 {
174 cvGetRow(sample, vect, i);
175 cvMatMulAdd(vect, utmat, mean, vect);
176 }
177
178 cvReleaseMat(&vect);
179 cvReleaseMat(&utmat);
180 }
181
182
183 /* Generates <sample> of <amount> points from a discrete variate xi,
184 where Pr{xi = k} == probs[k], 0 < k < len - 1. */
cvRandSeries(float probs[],int len,int sample[],int amount)185 CV_IMPL void cvRandSeries( float probs[], int len, int sample[], int amount )
186 {
187 CvMat* univals = cvCreateMat(1, amount, CV_32FC1);
188 float* knots = (float*)cvAlloc( len * sizeof(float) );
189
190 int i, j;
191
192 CvRNG state = cvRNG(-1);
193 cvRandArr(&state, univals, CV_RAND_UNI, cvScalarAll(0), cvScalarAll(1) );
194
195 knots[0] = probs[0];
196 for( i = 1; i < len; i++ )
197 knots[i] = knots[i - 1] + probs[i];
198
199 for( i = 0; i < amount; i++ )
200 for( j = 0; j < len; j++ )
201 {
202 if ( CV_MAT_ELEM(*univals, float, 0, i) <= knots[j] )
203 {
204 sample[i] = j;
205 break;
206 }
207 }
208
209 cvFree(&knots);
210 }
211
212 /* Generates <sample> from gaussian mixture distribution */
cvRandGaussMixture(CvMat * means[],CvMat * covs[],float weights[],int clsnum,CvMat * sample,CvMat * sampClasses)213 CV_IMPL void cvRandGaussMixture( CvMat* means[],
214 CvMat* covs[],
215 float weights[],
216 int clsnum,
217 CvMat* sample,
218 CvMat* sampClasses )
219 {
220 int dim = sample->cols;
221 int amount = sample->rows;
222
223 int i, clss;
224
225 int* sample_clsnum = (int*)cvAlloc( amount * sizeof(int) );
226 CvMat** utmats = (CvMat**)cvAlloc( clsnum * sizeof(CvMat*) );
227 CvMat* vect = cvCreateMatHeader(1, dim, CV_32FC1);
228
229 CvMat* classes;
230 if( sampClasses )
231 classes = sampClasses;
232 else
233 classes = cvCreateMat(1, amount, CV_32FC1);
234
235 CvRNG state = cvRNG(-1);
236 cvRandArr(&state, sample, CV_RAND_NORMAL, cvScalarAll(0), cvScalarAll(1));
237
238 cvRandSeries(weights, clsnum, sample_clsnum, amount);
239
240 for( i = 0; i < clsnum; i++ )
241 {
242 utmats[i] = cvCreateMat(dim, dim, CV_32FC1);
243 cvChol(covs[i], utmats[i]);
244 }
245
246 for( i = 0; i < amount; i++ )
247 {
248 CV_MAT_ELEM(*classes, float, 0, i) = (float)sample_clsnum[i];
249 cvGetRow(sample, vect, i);
250 clss = sample_clsnum[i];
251 cvMatMulAdd(vect, utmats[clss], means[clss], vect);
252 }
253
254 if( !sampClasses )
255 cvReleaseMat(&classes);
256 for( i = 0; i < clsnum; i++ )
257 cvReleaseMat(&utmats[i]);
258 cvFree(&utmats);
259 cvFree(&sample_clsnum);
260 cvReleaseMat(&vect);
261 }
262
263
icvGenerateRandomClusterCenters(int seed,const CvMat * data,int num_of_clusters,CvMat * _centers)264 CvMat* icvGenerateRandomClusterCenters ( int seed, const CvMat* data,
265 int num_of_clusters, CvMat* _centers )
266 {
267 CvMat* centers = _centers;
268
269 CV_FUNCNAME("icvGenerateRandomClusterCenters");
270 __BEGIN__;
271
272 CvRNG rng;
273 CvMat data_comp, centers_comp;
274 CvPoint minLoc, maxLoc; // Not used, just for function "cvMinMaxLoc"
275 double minVal, maxVal;
276 int i;
277 int dim = data ? data->cols : 0;
278
279 if( ICV_IS_MAT_OF_TYPE(data, CV_32FC1) )
280 {
281 if( _centers && !ICV_IS_MAT_OF_TYPE (_centers, CV_32FC1) )
282 {
283 CV_ERROR(CV_StsBadArg,"");
284 }
285 else if( !_centers )
286 CV_CALL(centers = cvCreateMat (num_of_clusters, dim, CV_32FC1));
287 }
288 else if( ICV_IS_MAT_OF_TYPE(data, CV_64FC1) )
289 {
290 if( _centers && !ICV_IS_MAT_OF_TYPE (_centers, CV_64FC1) )
291 {
292 CV_ERROR(CV_StsBadArg,"");
293 }
294 else if( !_centers )
295 CV_CALL(centers = cvCreateMat (num_of_clusters, dim, CV_64FC1));
296 }
297 else
298 CV_ERROR (CV_StsBadArg,"");
299
300 if( num_of_clusters < 1 )
301 CV_ERROR (CV_StsBadArg,"");
302
303 rng = cvRNG(seed);
304 for (i = 0; i < dim; i++)
305 {
306 CV_CALL(cvGetCol (data, &data_comp, i));
307 CV_CALL(cvMinMaxLoc (&data_comp, &minVal, &maxVal, &minLoc, &maxLoc));
308 CV_CALL(cvGetCol (centers, ¢ers_comp, i));
309 CV_CALL(cvRandArr (&rng, ¢ers_comp, CV_RAND_UNI, cvScalarAll(minVal), cvScalarAll(maxVal)));
310 }
311
312 __END__;
313
314 if( (cvGetErrStatus () < 0) || (centers != _centers) )
315 cvReleaseMat (¢ers);
316
317 return _centers ? _centers : centers;
318 } // end of icvGenerateRandomClusterCenters
319
320 // By S. Dilman - begin -
321
322 #define ICV_RAND_MAX 4294967296 // == 2^32
323
cvRandRoundUni(CvMat * center,float radius_small,float radius_large,CvMat * desired_matrix,CvRNG * rng_state_ptr)324 CV_IMPL void cvRandRoundUni (CvMat* center,
325 float radius_small,
326 float radius_large,
327 CvMat* desired_matrix,
328 CvRNG* rng_state_ptr)
329 {
330 float rad, norm, coefficient;
331 int dim, size, i, j;
332 CvMat *cov, sample;
333 CvRNG rng_local;
334
335 CV_FUNCNAME("cvRandRoundUni");
336 __BEGIN__
337
338 rng_local = *rng_state_ptr;
339
340 CV_ASSERT ((radius_small >= 0) &&
341 (radius_large > 0) &&
342 (radius_small <= radius_large));
343 CV_ASSERT (center && desired_matrix && rng_state_ptr);
344 CV_ASSERT (center->rows == 1);
345 CV_ASSERT (center->cols == desired_matrix->cols);
346
347 dim = desired_matrix->cols;
348 size = desired_matrix->rows;
349 cov = cvCreateMat (dim, dim, CV_32FC1);
350 cvSetIdentity (cov);
351 cvRandMVNormal (center, cov, desired_matrix, &rng_local);
352
353 for (i = 0; i < size; i++)
354 {
355 rad = (float)(cvRandReal(&rng_local)*(radius_large - radius_small) + radius_small);
356 cvGetRow (desired_matrix, &sample, i);
357 norm = (float) cvNorm (&sample, 0, CV_L2);
358 coefficient = rad / norm;
359 for (j = 0; j < dim; j++)
360 CV_MAT_ELEM (sample, float, 0, j) *= coefficient;
361 }
362
363 __END__
364
365 }
366
367 // By S. Dilman - end -
368
369 /* Aij <- Aji for i > j if lower_to_upper != 0
370 for i < j if lower_to_upper = 0 */
cvCompleteSymm(CvMat * matrix,int lower_to_upper)371 void cvCompleteSymm( CvMat* matrix, int lower_to_upper )
372 {
373 CV_FUNCNAME("cvCompleteSymm");
374
375 __BEGIN__;
376
377 int rows, cols;
378 int i, j;
379 int step;
380
381 if( !CV_IS_MAT(matrix))
382 CV_ERROR(CV_StsBadArg, "Invalid matrix argument");
383
384 rows = matrix->rows;
385 cols = matrix->cols;
386 step = matrix->step / CV_ELEM_SIZE(matrix->type);
387
388 switch(CV_MAT_TYPE(matrix->type))
389 {
390 case CV_32FC1:
391 {
392 float* dst = matrix->data.fl;
393 if( !lower_to_upper )
394 for( i = 1; i < rows; i++ )
395 {
396 const float* src = (const float*)(matrix->data.fl + i);
397 dst += step;
398 for( j = 0; j < i; j++, src += step )
399 dst[j] = src[0];
400 }
401 else
402 for( i = 0; i < rows-1; i++, dst += step )
403 {
404 const float* src = (const float*)(matrix->data.fl + (i+1)*step + i);
405 for( j = i+1; j < cols; j++, src += step )
406 dst[j] = src[0];
407 }
408 }
409 break;
410 case CV_64FC1:
411 {
412 double* dst = matrix->data.db;
413 if( !lower_to_upper )
414 for( i = 1; i < rows; i++ )
415 {
416 const double* src = (const double*)(matrix->data.db + i);
417 dst += step;
418 for( j = 0; j < i; j++, src += step )
419 dst[j] = src[0];
420 }
421 else
422 for( i = 0; i < rows-1; i++, dst += step )
423 {
424 const double* src = (const double*)(matrix->data.db + (i+1)*step + i);
425 for( j = i+1; j < cols; j++, src += step )
426 dst[j] = src[0];
427 }
428 }
429 break;
430 }
431
432 __END__;
433 }
434
435
436 static int CV_CDECL
icvCmpIntegers(const void * a,const void * b)437 icvCmpIntegers( const void* a, const void* b )
438 {
439 return *(const int*)a - *(const int*)b;
440 }
441
442
443 static int CV_CDECL
icvCmpIntegersPtr(const void * _a,const void * _b)444 icvCmpIntegersPtr( const void* _a, const void* _b )
445 {
446 int a = **(const int**)_a;
447 int b = **(const int**)_b;
448 return (a < b ? -1 : 0)|(a > b);
449 }
450
451
icvCmpSparseVecElems(const void * a,const void * b)452 static int icvCmpSparseVecElems( const void* a, const void* b )
453 {
454 return ((CvSparseVecElem32f*)a)->idx - ((CvSparseVecElem32f*)b)->idx;
455 }
456
457
458 CvMat*
cvPreprocessIndexArray(const CvMat * idx_arr,int data_arr_size,bool check_for_duplicates)459 cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, bool check_for_duplicates )
460 {
461 CvMat* idx = 0;
462
463 CV_FUNCNAME( "cvPreprocessIndexArray" );
464
465 __BEGIN__;
466
467 int i, idx_total, idx_selected = 0, step, type, prev = INT_MIN, is_sorted = 1;
468 uchar* srcb = 0;
469 int* srci = 0;
470 int* dsti;
471
472 if( !CV_IS_MAT(idx_arr) )
473 CV_ERROR( CV_StsBadArg, "Invalid index array" );
474
475 if( idx_arr->rows != 1 && idx_arr->cols != 1 )
476 CV_ERROR( CV_StsBadSize, "the index array must be 1-dimensional" );
477
478 idx_total = idx_arr->rows + idx_arr->cols - 1;
479 srcb = idx_arr->data.ptr;
480 srci = idx_arr->data.i;
481
482 type = CV_MAT_TYPE(idx_arr->type);
483 step = CV_IS_MAT_CONT(idx_arr->type) ? 1 : idx_arr->step/CV_ELEM_SIZE(type);
484
485 switch( type )
486 {
487 case CV_8UC1:
488 case CV_8SC1:
489 // idx_arr is array of 1's and 0's -
490 // i.e. it is a mask of the selected components
491 if( idx_total != data_arr_size )
492 CV_ERROR( CV_StsUnmatchedSizes,
493 "Component mask should contain as many elements as the total number of input variables" );
494
495 for( i = 0; i < idx_total; i++ )
496 idx_selected += srcb[i*step] != 0;
497
498 if( idx_selected == 0 )
499 CV_ERROR( CV_StsOutOfRange, "No components/input_variables is selected!" );
500
501 if( idx_selected == idx_total )
502 EXIT;
503 break;
504 case CV_32SC1:
505 // idx_arr is array of integer indices of selected components
506 if( idx_total > data_arr_size )
507 CV_ERROR( CV_StsOutOfRange,
508 "index array may not contain more elements than the total number of input variables" );
509 idx_selected = idx_total;
510 // check if sorted already
511 for( i = 0; i < idx_total; i++ )
512 {
513 int val = srci[i*step];
514 if( val >= prev )
515 {
516 is_sorted = 0;
517 break;
518 }
519 prev = val;
520 }
521 break;
522 default:
523 CV_ERROR( CV_StsUnsupportedFormat, "Unsupported index array data type "
524 "(it should be 8uC1, 8sC1 or 32sC1)" );
525 }
526
527 CV_CALL( idx = cvCreateMat( 1, idx_selected, CV_32SC1 ));
528 dsti = idx->data.i;
529
530 if( type < CV_32SC1 )
531 {
532 for( i = 0; i < idx_total; i++ )
533 if( srcb[i*step] )
534 *dsti++ = i;
535 }
536 else
537 {
538 for( i = 0; i < idx_total; i++ )
539 dsti[i] = srci[i*step];
540
541 if( !is_sorted )
542 qsort( dsti, idx_total, sizeof(dsti[0]), icvCmpIntegers );
543
544 if( dsti[0] < 0 || dsti[idx_total-1] >= data_arr_size )
545 CV_ERROR( CV_StsOutOfRange, "the index array elements are out of range" );
546
547 if( check_for_duplicates )
548 {
549 for( i = 1; i < idx_total; i++ )
550 if( dsti[i] <= dsti[i-1] )
551 CV_ERROR( CV_StsBadArg, "There are duplicated index array elements" );
552 }
553 }
554
555 __END__;
556
557 if( cvGetErrStatus() < 0 )
558 cvReleaseMat( &idx );
559
560 return idx;
561 }
562
563
564 CvMat*
cvPreprocessVarType(const CvMat * var_type,const CvMat * var_idx,int var_all,int * response_type)565 cvPreprocessVarType( const CvMat* var_type, const CvMat* var_idx,
566 int var_all, int* response_type )
567 {
568 CvMat* out_var_type = 0;
569 CV_FUNCNAME( "cvPreprocessVarType" );
570
571 if( response_type )
572 *response_type = -1;
573
574 __BEGIN__;
575
576 int i, tm_size, tm_step;
577 int* map = 0;
578 const uchar* src;
579 uchar* dst;
580 int var_count = var_all;
581
582 if( !CV_IS_MAT(var_type) )
583 CV_ERROR( var_type ? CV_StsBadArg : CV_StsNullPtr, "Invalid or absent var_type array" );
584
585 if( var_type->rows != 1 && var_type->cols != 1 )
586 CV_ERROR( CV_StsBadSize, "var_type array must be 1-dimensional" );
587
588 if( !CV_IS_MASK_ARR(var_type))
589 CV_ERROR( CV_StsUnsupportedFormat, "type mask must be 8uC1 or 8sC1 array" );
590
591 tm_size = var_type->rows + var_type->cols - 1;
592 tm_step = var_type->step ? var_type->step/CV_ELEM_SIZE(var_type->type) : 1;
593
594 if( /*tm_size != var_count &&*/ tm_size != var_count + 1 )
595 CV_ERROR( CV_StsBadArg,
596 "type mask must be of <input var count> + 1 size" );
597
598 if( response_type && tm_size > var_count )
599 *response_type = var_type->data.ptr[var_count*tm_step] != 0;
600
601 if( var_idx )
602 {
603 if( !CV_IS_MAT(var_idx) || CV_MAT_TYPE(var_idx->type) != CV_32SC1 ||
604 var_idx->rows != 1 && var_idx->cols != 1 || !CV_IS_MAT_CONT(var_idx->type) )
605 CV_ERROR( CV_StsBadArg, "var index array should be continuous 1-dimensional integer vector" );
606 if( var_idx->rows + var_idx->cols - 1 > var_count )
607 CV_ERROR( CV_StsBadSize, "var index array is too large" );
608 map = var_idx->data.i;
609 var_count = var_idx->rows + var_idx->cols - 1;
610 }
611
612 CV_CALL( out_var_type = cvCreateMat( 1, var_count, CV_8UC1 ));
613 src = var_type->data.ptr;
614 dst = out_var_type->data.ptr;
615
616 for( i = 0; i < var_count; i++ )
617 {
618 int idx = map ? map[i] : i;
619 assert( (unsigned)idx < (unsigned)tm_size );
620 dst[i] = (uchar)(src[idx*tm_step] != 0);
621 }
622
623 __END__;
624
625 return out_var_type;
626 }
627
628
629 CvMat*
cvPreprocessOrderedResponses(const CvMat * responses,const CvMat * sample_idx,int sample_all)630 cvPreprocessOrderedResponses( const CvMat* responses, const CvMat* sample_idx, int sample_all )
631 {
632 CvMat* out_responses = 0;
633
634 CV_FUNCNAME( "cvPreprocessOrderedResponses" );
635
636 __BEGIN__;
637
638 int i, r_type, r_step;
639 const int* map = 0;
640 float* dst;
641 int sample_count = sample_all;
642
643 if( !CV_IS_MAT(responses) )
644 CV_ERROR( CV_StsBadArg, "Invalid response array" );
645
646 if( responses->rows != 1 && responses->cols != 1 )
647 CV_ERROR( CV_StsBadSize, "Response array must be 1-dimensional" );
648
649 if( responses->rows + responses->cols - 1 != sample_count )
650 CV_ERROR( CV_StsUnmatchedSizes,
651 "Response array must contain as many elements as the total number of samples" );
652
653 r_type = CV_MAT_TYPE(responses->type);
654 if( r_type != CV_32FC1 && r_type != CV_32SC1 )
655 CV_ERROR( CV_StsUnsupportedFormat, "Unsupported response type" );
656
657 r_step = responses->step ? responses->step / CV_ELEM_SIZE(responses->type) : 1;
658
659 if( r_type == CV_32FC1 && CV_IS_MAT_CONT(responses->type) && !sample_idx )
660 {
661 out_responses = (CvMat*)responses;
662 EXIT;
663 }
664
665 if( sample_idx )
666 {
667 if( !CV_IS_MAT(sample_idx) || CV_MAT_TYPE(sample_idx->type) != CV_32SC1 ||
668 sample_idx->rows != 1 && sample_idx->cols != 1 || !CV_IS_MAT_CONT(sample_idx->type) )
669 CV_ERROR( CV_StsBadArg, "sample index array should be continuous 1-dimensional integer vector" );
670 if( sample_idx->rows + sample_idx->cols - 1 > sample_count )
671 CV_ERROR( CV_StsBadSize, "sample index array is too large" );
672 map = sample_idx->data.i;
673 sample_count = sample_idx->rows + sample_idx->cols - 1;
674 }
675
676 CV_CALL( out_responses = cvCreateMat( 1, sample_count, CV_32FC1 ));
677
678 dst = out_responses->data.fl;
679 if( r_type == CV_32FC1 )
680 {
681 const float* src = responses->data.fl;
682 for( i = 0; i < sample_count; i++ )
683 {
684 int idx = map ? map[i] : i;
685 assert( (unsigned)idx < (unsigned)sample_all );
686 dst[i] = src[idx*r_step];
687 }
688 }
689 else
690 {
691 const int* src = responses->data.i;
692 for( i = 0; i < sample_count; i++ )
693 {
694 int idx = map ? map[i] : i;
695 assert( (unsigned)idx < (unsigned)sample_all );
696 dst[i] = (float)src[idx*r_step];
697 }
698 }
699
700 __END__;
701
702 return out_responses;
703 }
704
705 CvMat*
cvPreprocessCategoricalResponses(const CvMat * responses,const CvMat * sample_idx,int sample_all,CvMat ** out_response_map,CvMat ** class_counts)706 cvPreprocessCategoricalResponses( const CvMat* responses,
707 const CvMat* sample_idx, int sample_all,
708 CvMat** out_response_map, CvMat** class_counts )
709 {
710 CvMat* out_responses = 0;
711 int** response_ptr = 0;
712
713 CV_FUNCNAME( "cvPreprocessCategoricalResponses" );
714
715 if( out_response_map )
716 *out_response_map = 0;
717
718 if( class_counts )
719 *class_counts = 0;
720
721 __BEGIN__;
722
723 int i, r_type, r_step;
724 int cls_count = 1, prev_cls, prev_i;
725 const int* map = 0;
726 const int* srci;
727 const float* srcfl;
728 int* dst;
729 int* cls_map;
730 int* cls_counts = 0;
731 int sample_count = sample_all;
732
733 if( !CV_IS_MAT(responses) )
734 CV_ERROR( CV_StsBadArg, "Invalid response array" );
735
736 if( responses->rows != 1 && responses->cols != 1 )
737 CV_ERROR( CV_StsBadSize, "Response array must be 1-dimensional" );
738
739 if( responses->rows + responses->cols - 1 != sample_count )
740 CV_ERROR( CV_StsUnmatchedSizes,
741 "Response array must contain as many elements as the total number of samples" );
742
743 r_type = CV_MAT_TYPE(responses->type);
744 if( r_type != CV_32FC1 && r_type != CV_32SC1 )
745 CV_ERROR( CV_StsUnsupportedFormat, "Unsupported response type" );
746
747 r_step = responses->step ? responses->step / CV_ELEM_SIZE(responses->type) : 1;
748
749 if( sample_idx )
750 {
751 if( !CV_IS_MAT(sample_idx) || CV_MAT_TYPE(sample_idx->type) != CV_32SC1 ||
752 sample_idx->rows != 1 && sample_idx->cols != 1 || !CV_IS_MAT_CONT(sample_idx->type) )
753 CV_ERROR( CV_StsBadArg, "sample index array should be continuous 1-dimensional integer vector" );
754 if( sample_idx->rows + sample_idx->cols - 1 > sample_count )
755 CV_ERROR( CV_StsBadSize, "sample index array is too large" );
756 map = sample_idx->data.i;
757 sample_count = sample_idx->rows + sample_idx->cols - 1;
758 }
759
760 CV_CALL( out_responses = cvCreateMat( 1, sample_count, CV_32SC1 ));
761
762 if( !out_response_map )
763 CV_ERROR( CV_StsNullPtr, "out_response_map pointer is NULL" );
764
765 CV_CALL( response_ptr = (int**)cvAlloc( sample_count*sizeof(response_ptr[0])));
766
767 srci = responses->data.i;
768 srcfl = responses->data.fl;
769 dst = out_responses->data.i;
770
771 for( i = 0; i < sample_count; i++ )
772 {
773 int idx = map ? map[i] : i;
774 assert( (unsigned)idx < (unsigned)sample_all );
775 if( r_type == CV_32SC1 )
776 dst[i] = srci[idx*r_step];
777 else
778 {
779 float rf = srcfl[idx*r_step];
780 int ri = cvRound(rf);
781 if( ri != rf )
782 {
783 char buf[100];
784 sprintf( buf, "response #%d is not integral", idx );
785 CV_ERROR( CV_StsBadArg, buf );
786 }
787 dst[i] = ri;
788 }
789 response_ptr[i] = dst + i;
790 }
791
792 qsort( response_ptr, sample_count, sizeof(int*), icvCmpIntegersPtr );
793
794 // count the classes
795 for( i = 1; i < sample_count; i++ )
796 cls_count += *response_ptr[i] != *response_ptr[i-1];
797
798 if( cls_count < 2 )
799 CV_ERROR( CV_StsBadArg, "There is only a single class" );
800
801 CV_CALL( *out_response_map = cvCreateMat( 1, cls_count, CV_32SC1 ));
802
803 if( class_counts )
804 {
805 CV_CALL( *class_counts = cvCreateMat( 1, cls_count, CV_32SC1 ));
806 cls_counts = (*class_counts)->data.i;
807 }
808
809 // compact the class indices and build the map
810 prev_cls = ~*response_ptr[0];
811 cls_count = -1;
812 cls_map = (*out_response_map)->data.i;
813
814 for( i = 0, prev_i = -1; i < sample_count; i++ )
815 {
816 int cur_cls = *response_ptr[i];
817 if( cur_cls != prev_cls )
818 {
819 if( cls_counts && cls_count >= 0 )
820 cls_counts[cls_count] = i - prev_i;
821 cls_map[++cls_count] = prev_cls = cur_cls;
822 prev_i = i;
823 }
824 *response_ptr[i] = cls_count;
825 }
826
827 if( cls_counts )
828 cls_counts[cls_count] = i - prev_i;
829
830 __END__;
831
832 cvFree( &response_ptr );
833
834 return out_responses;
835 }
836
837
838 const float**
cvGetTrainSamples(const CvMat * train_data,int tflag,const CvMat * var_idx,const CvMat * sample_idx,int * _var_count,int * _sample_count,bool always_copy_data)839 cvGetTrainSamples( const CvMat* train_data, int tflag,
840 const CvMat* var_idx, const CvMat* sample_idx,
841 int* _var_count, int* _sample_count,
842 bool always_copy_data )
843 {
844 float** samples = 0;
845
846 CV_FUNCNAME( "cvGetTrainSamples" );
847
848 __BEGIN__;
849
850 int i, j, var_count, sample_count, s_step, v_step;
851 bool copy_data;
852 const float* data;
853 const int *s_idx, *v_idx;
854
855 if( !CV_IS_MAT(train_data) )
856 CV_ERROR( CV_StsBadArg, "Invalid or NULL training data matrix" );
857
858 var_count = var_idx ? var_idx->cols + var_idx->rows - 1 :
859 tflag == CV_ROW_SAMPLE ? train_data->cols : train_data->rows;
860 sample_count = sample_idx ? sample_idx->cols + sample_idx->rows - 1 :
861 tflag == CV_ROW_SAMPLE ? train_data->rows : train_data->cols;
862
863 if( _var_count )
864 *_var_count = var_count;
865
866 if( _sample_count )
867 *_sample_count = sample_count;
868
869 copy_data = tflag != CV_ROW_SAMPLE || var_idx || always_copy_data;
870
871 CV_CALL( samples = (float**)cvAlloc(sample_count*sizeof(samples[0]) +
872 (copy_data ? 1 : 0)*var_count*sample_count*sizeof(samples[0][0])) );
873 data = train_data->data.fl;
874 s_step = train_data->step / sizeof(samples[0][0]);
875 v_step = 1;
876 s_idx = sample_idx ? sample_idx->data.i : 0;
877 v_idx = var_idx ? var_idx->data.i : 0;
878
879 if( !copy_data )
880 {
881 for( i = 0; i < sample_count; i++ )
882 samples[i] = (float*)(data + (s_idx ? s_idx[i] : i)*s_step);
883 }
884 else
885 {
886 samples[0] = (float*)(samples + sample_count);
887 if( tflag != CV_ROW_SAMPLE )
888 CV_SWAP( s_step, v_step, i );
889
890 for( i = 0; i < sample_count; i++ )
891 {
892 float* dst = samples[i] = samples[0] + i*var_count;
893 const float* src = data + (s_idx ? s_idx[i] : i)*s_step;
894
895 if( !v_idx )
896 for( j = 0; j < var_count; j++ )
897 dst[j] = src[j*v_step];
898 else
899 for( j = 0; j < var_count; j++ )
900 dst[j] = src[v_idx[j]*v_step];
901 }
902 }
903
904 __END__;
905
906 return (const float**)samples;
907 }
908
909
910 void
cvCheckTrainData(const CvMat * train_data,int tflag,const CvMat * missing_mask,int * var_all,int * sample_all)911 cvCheckTrainData( const CvMat* train_data, int tflag,
912 const CvMat* missing_mask,
913 int* var_all, int* sample_all )
914 {
915 CV_FUNCNAME( "cvCheckTrainData" );
916
917 if( var_all )
918 *var_all = 0;
919
920 if( sample_all )
921 *sample_all = 0;
922
923 __BEGIN__;
924
925 // check parameter types and sizes
926 if( !CV_IS_MAT(train_data) || CV_MAT_TYPE(train_data->type) != CV_32FC1 )
927 CV_ERROR( CV_StsBadArg, "train data must be floating-point matrix" );
928
929 if( missing_mask )
930 {
931 if( !CV_IS_MAT(missing_mask) || !CV_IS_MASK_ARR(missing_mask) ||
932 !CV_ARE_SIZES_EQ(train_data, missing_mask) )
933 CV_ERROR( CV_StsBadArg,
934 "missing value mask must be 8-bit matrix of the same size as training data" );
935 }
936
937 if( tflag != CV_ROW_SAMPLE && tflag != CV_COL_SAMPLE )
938 CV_ERROR( CV_StsBadArg,
939 "Unknown training data layout (must be CV_ROW_SAMPLE or CV_COL_SAMPLE)" );
940
941 if( var_all )
942 *var_all = tflag == CV_ROW_SAMPLE ? train_data->cols : train_data->rows;
943
944 if( sample_all )
945 *sample_all = tflag == CV_ROW_SAMPLE ? train_data->rows : train_data->cols;
946
947 __END__;
948 }
949
950
951 int
cvPrepareTrainData(const char *,const CvMat * train_data,int tflag,const CvMat * responses,int response_type,const CvMat * var_idx,const CvMat * sample_idx,bool always_copy_data,const float *** out_train_samples,int * _sample_count,int * _var_count,int * _var_all,CvMat ** out_responses,CvMat ** out_response_map,CvMat ** out_var_idx,CvMat ** out_sample_idx)952 cvPrepareTrainData( const char* /*funcname*/,
953 const CvMat* train_data, int tflag,
954 const CvMat* responses, int response_type,
955 const CvMat* var_idx,
956 const CvMat* sample_idx,
957 bool always_copy_data,
958 const float*** out_train_samples,
959 int* _sample_count,
960 int* _var_count,
961 int* _var_all,
962 CvMat** out_responses,
963 CvMat** out_response_map,
964 CvMat** out_var_idx,
965 CvMat** out_sample_idx )
966 {
967 int ok = 0;
968 CvMat* _var_idx = 0;
969 CvMat* _sample_idx = 0;
970 CvMat* _responses = 0;
971 int sample_all = 0, sample_count = 0, var_all = 0, var_count = 0;
972
973 CV_FUNCNAME( "cvPrepareTrainData" );
974
975 // step 0. clear all the output pointers to ensure we do not try
976 // to call free() with uninitialized pointers
977 if( out_responses )
978 *out_responses = 0;
979
980 if( out_response_map )
981 *out_response_map = 0;
982
983 if( out_var_idx )
984 *out_var_idx = 0;
985
986 if( out_sample_idx )
987 *out_sample_idx = 0;
988
989 if( out_train_samples )
990 *out_train_samples = 0;
991
992 if( _sample_count )
993 *_sample_count = 0;
994
995 if( _var_count )
996 *_var_count = 0;
997
998 if( _var_all )
999 *_var_all = 0;
1000
1001 __BEGIN__;
1002
1003 if( !out_train_samples )
1004 CV_ERROR( CV_StsBadArg, "output pointer to train samples is NULL" );
1005
1006 CV_CALL( cvCheckTrainData( train_data, tflag, 0, &var_all, &sample_all ));
1007
1008 if( sample_idx )
1009 CV_CALL( _sample_idx = cvPreprocessIndexArray( sample_idx, sample_all ));
1010 if( var_idx )
1011 CV_CALL( _var_idx = cvPreprocessIndexArray( var_idx, var_all ));
1012
1013 if( responses )
1014 {
1015 if( !out_responses )
1016 CV_ERROR( CV_StsNullPtr, "output response pointer is NULL" );
1017
1018 if( response_type == CV_VAR_NUMERICAL )
1019 {
1020 CV_CALL( _responses = cvPreprocessOrderedResponses( responses,
1021 _sample_idx, sample_all ));
1022 }
1023 else
1024 {
1025 CV_CALL( _responses = cvPreprocessCategoricalResponses( responses,
1026 _sample_idx, sample_all, out_response_map, 0 ));
1027 }
1028 }
1029
1030 CV_CALL( *out_train_samples =
1031 cvGetTrainSamples( train_data, tflag, _var_idx, _sample_idx,
1032 &var_count, &sample_count, always_copy_data ));
1033
1034 ok = 1;
1035
1036 __END__;
1037
1038 if( ok )
1039 {
1040 if( out_responses )
1041 *out_responses = _responses, _responses = 0;
1042
1043 if( out_var_idx )
1044 *out_var_idx = _var_idx, _var_idx = 0;
1045
1046 if( out_sample_idx )
1047 *out_sample_idx = _sample_idx, _sample_idx = 0;
1048
1049 if( _sample_count )
1050 *_sample_count = sample_count;
1051
1052 if( _var_count )
1053 *_var_count = var_count;
1054
1055 if( _var_all )
1056 *_var_all = var_all;
1057 }
1058 else
1059 {
1060 if( out_response_map )
1061 cvReleaseMat( out_response_map );
1062 cvFree( out_train_samples );
1063 }
1064
1065 if( _responses != responses )
1066 cvReleaseMat( &_responses );
1067 cvReleaseMat( &_var_idx );
1068 cvReleaseMat( &_sample_idx );
1069
1070 return ok;
1071 }
1072
1073
1074 typedef struct CvSampleResponsePair
1075 {
1076 const float* sample;
1077 const uchar* mask;
1078 int response;
1079 int index;
1080 }
1081 CvSampleResponsePair;
1082
1083
1084 static int
icvCmpSampleResponsePairs(const void * a,const void * b)1085 CV_CDECL icvCmpSampleResponsePairs( const void* a, const void* b )
1086 {
1087 int ra = ((const CvSampleResponsePair*)a)->response;
1088 int rb = ((const CvSampleResponsePair*)b)->response;
1089 int ia = ((const CvSampleResponsePair*)a)->index;
1090 int ib = ((const CvSampleResponsePair*)b)->index;
1091
1092 return ra < rb ? -1 : ra > rb ? 1 : ia - ib;
1093 //return (ra > rb ? -1 : 0)|(ra < rb);
1094 }
1095
1096
1097 void
cvSortSamplesByClasses(const float ** samples,const CvMat * classes,int * class_ranges,const uchar ** mask)1098 cvSortSamplesByClasses( const float** samples, const CvMat* classes,
1099 int* class_ranges, const uchar** mask )
1100 {
1101 CvSampleResponsePair* pairs = 0;
1102 CV_FUNCNAME( "cvSortSamplesByClasses" );
1103
1104 __BEGIN__;
1105
1106 int i, k = 0, sample_count;
1107
1108 if( !samples || !classes || !class_ranges )
1109 CV_ERROR( CV_StsNullPtr, "INTERNAL ERROR: some of the args are NULL pointers" );
1110
1111 if( classes->rows != 1 || CV_MAT_TYPE(classes->type) != CV_32SC1 )
1112 CV_ERROR( CV_StsBadArg, "classes array must be a single row of integers" );
1113
1114 sample_count = classes->cols;
1115 CV_CALL( pairs = (CvSampleResponsePair*)cvAlloc( (sample_count+1)*sizeof(pairs[0])));
1116
1117 for( i = 0; i < sample_count; i++ )
1118 {
1119 pairs[i].sample = samples[i];
1120 pairs[i].mask = (mask) ? (mask[i]) : 0;
1121 pairs[i].response = classes->data.i[i];
1122 pairs[i].index = i;
1123 assert( classes->data.i[i] >= 0 );
1124 }
1125
1126 qsort( pairs, sample_count, sizeof(pairs[0]), icvCmpSampleResponsePairs );
1127 pairs[sample_count].response = -1;
1128 class_ranges[0] = 0;
1129
1130 for( i = 0; i < sample_count; i++ )
1131 {
1132 samples[i] = pairs[i].sample;
1133 if (mask)
1134 mask[i] = pairs[i].mask;
1135 classes->data.i[i] = pairs[i].response;
1136
1137 if( pairs[i].response != pairs[i+1].response )
1138 class_ranges[++k] = i+1;
1139 }
1140
1141 __END__;
1142
1143 cvFree( &pairs );
1144 }
1145
1146
1147 void
cvPreparePredictData(const CvArr * _sample,int dims_all,const CvMat * comp_idx,int class_count,const CvMat * prob,float ** _row_sample,int as_sparse)1148 cvPreparePredictData( const CvArr* _sample, int dims_all,
1149 const CvMat* comp_idx, int class_count,
1150 const CvMat* prob, float** _row_sample,
1151 int as_sparse )
1152 {
1153 float* row_sample = 0;
1154 int* inverse_comp_idx = 0;
1155
1156 CV_FUNCNAME( "cvPreparePredictData" );
1157
1158 __BEGIN__;
1159
1160 const CvMat* sample = (const CvMat*)_sample;
1161 float* sample_data;
1162 int sample_step;
1163 int is_sparse = CV_IS_SPARSE_MAT(sample);
1164 int d, sizes[CV_MAX_DIM];
1165 int i, dims_selected;
1166 int vec_size;
1167
1168 if( !is_sparse && !CV_IS_MAT(sample) )
1169 CV_ERROR( !sample ? CV_StsNullPtr : CV_StsBadArg, "The sample is not a valid vector" );
1170
1171 if( cvGetElemType( sample ) != CV_32FC1 )
1172 CV_ERROR( CV_StsUnsupportedFormat, "Input sample must have 32fC1 type" );
1173
1174 CV_CALL( d = cvGetDims( sample, sizes ));
1175
1176 if( !(is_sparse && d == 1 || !is_sparse && d == 2 && (sample->rows == 1 || sample->cols == 1)) )
1177 CV_ERROR( CV_StsBadSize, "Input sample must be 1-dimensional vector" );
1178
1179 if( d == 1 )
1180 sizes[1] = 1;
1181
1182 if( sizes[0] + sizes[1] - 1 != dims_all )
1183 CV_ERROR( CV_StsUnmatchedSizes,
1184 "The sample size is different from what has been used for training" );
1185
1186 if( !_row_sample )
1187 CV_ERROR( CV_StsNullPtr, "INTERNAL ERROR: The row_sample pointer is NULL" );
1188
1189 if( comp_idx && (!CV_IS_MAT(comp_idx) || comp_idx->rows != 1 ||
1190 CV_MAT_TYPE(comp_idx->type) != CV_32SC1) )
1191 CV_ERROR( CV_StsBadArg, "INTERNAL ERROR: invalid comp_idx" );
1192
1193 dims_selected = comp_idx ? comp_idx->cols : dims_all;
1194
1195 if( prob )
1196 {
1197 if( !CV_IS_MAT(prob) )
1198 CV_ERROR( CV_StsBadArg, "The output matrix of probabilities is invalid" );
1199
1200 if( (prob->rows != 1 && prob->cols != 1) ||
1201 CV_MAT_TYPE(prob->type) != CV_32FC1 &&
1202 CV_MAT_TYPE(prob->type) != CV_64FC1 )
1203 CV_ERROR( CV_StsBadSize,
1204 "The matrix of probabilities must be 1-dimensional vector of 32fC1 type" );
1205
1206 if( prob->rows + prob->cols - 1 != class_count )
1207 CV_ERROR( CV_StsUnmatchedSizes,
1208 "The vector of probabilities must contain as many elements as "
1209 "the number of classes in the training set" );
1210 }
1211
1212 vec_size = !as_sparse ? dims_selected*sizeof(row_sample[0]) :
1213 (dims_selected + 1)*sizeof(CvSparseVecElem32f);
1214
1215 if( CV_IS_MAT(sample) )
1216 {
1217 sample_data = sample->data.fl;
1218 sample_step = sample->step / sizeof(row_sample[0]);
1219
1220 if( !comp_idx && sample_step <= 1 && !as_sparse )
1221 *_row_sample = sample_data;
1222 else
1223 {
1224 CV_CALL( row_sample = (float*)cvAlloc( vec_size ));
1225
1226 if( !comp_idx )
1227 for( i = 0; i < dims_selected; i++ )
1228 row_sample[i] = sample_data[sample_step*i];
1229 else
1230 {
1231 int* comp = comp_idx->data.i;
1232 if( !sample_step )
1233 for( i = 0; i < dims_selected; i++ )
1234 row_sample[i] = sample_data[comp[i]];
1235 else
1236 for( i = 0; i < dims_selected; i++ )
1237 row_sample[i] = sample_data[sample_step*comp[i]];
1238 }
1239
1240 *_row_sample = row_sample;
1241 }
1242
1243 if( as_sparse )
1244 {
1245 const float* src = (const float*)row_sample;
1246 CvSparseVecElem32f* dst = (CvSparseVecElem32f*)row_sample;
1247
1248 dst[dims_selected].idx = -1;
1249 for( i = dims_selected - 1; i >= 0; i-- )
1250 {
1251 dst[i].idx = i;
1252 dst[i].val = src[i];
1253 }
1254 }
1255 }
1256 else
1257 {
1258 CvSparseNode* node;
1259 CvSparseMatIterator mat_iterator;
1260 const CvSparseMat* sparse = (const CvSparseMat*)sample;
1261 assert( is_sparse );
1262
1263 node = cvInitSparseMatIterator( sparse, &mat_iterator );
1264 CV_CALL( row_sample = (float*)cvAlloc( vec_size ));
1265
1266 if( comp_idx )
1267 {
1268 CV_CALL( inverse_comp_idx = (int*)cvAlloc( dims_all*sizeof(int) ));
1269 memset( inverse_comp_idx, -1, dims_all*sizeof(int) );
1270 for( i = 0; i < dims_selected; i++ )
1271 inverse_comp_idx[comp_idx->data.i[i]] = i;
1272 }
1273
1274 if( !as_sparse )
1275 {
1276 memset( row_sample, 0, vec_size );
1277
1278 for( ; node != 0; node = cvGetNextSparseNode(&mat_iterator) )
1279 {
1280 int idx = *CV_NODE_IDX( sparse, node );
1281 if( inverse_comp_idx )
1282 {
1283 idx = inverse_comp_idx[idx];
1284 if( idx < 0 )
1285 continue;
1286 }
1287 row_sample[idx] = *(float*)CV_NODE_VAL( sparse, node );
1288 }
1289 }
1290 else
1291 {
1292 CvSparseVecElem32f* ptr = (CvSparseVecElem32f*)row_sample;
1293
1294 for( ; node != 0; node = cvGetNextSparseNode(&mat_iterator) )
1295 {
1296 int idx = *CV_NODE_IDX( sparse, node );
1297 if( inverse_comp_idx )
1298 {
1299 idx = inverse_comp_idx[idx];
1300 if( idx < 0 )
1301 continue;
1302 }
1303 ptr->idx = idx;
1304 ptr->val = *(float*)CV_NODE_VAL( sparse, node );
1305 ptr++;
1306 }
1307
1308 qsort( row_sample, ptr - (CvSparseVecElem32f*)row_sample,
1309 sizeof(ptr[0]), icvCmpSparseVecElems );
1310 ptr->idx = -1;
1311 }
1312
1313 *_row_sample = row_sample;
1314 }
1315
1316 __END__;
1317
1318 if( inverse_comp_idx )
1319 cvFree( &inverse_comp_idx );
1320
1321 if( cvGetErrStatus() < 0 && _row_sample )
1322 {
1323 cvFree( &row_sample );
1324 *_row_sample = 0;
1325 }
1326 }
1327
1328
1329 static void
icvConvertDataToSparse(const uchar * src,int src_step,int src_type,uchar * dst,int dst_step,int dst_type,CvSize size,int * idx)1330 icvConvertDataToSparse( const uchar* src, int src_step, int src_type,
1331 uchar* dst, int dst_step, int dst_type,
1332 CvSize size, int* idx )
1333 {
1334 CV_FUNCNAME( "icvConvertDataToSparse" );
1335
1336 __BEGIN__;
1337
1338 int i, j;
1339 src_type = CV_MAT_TYPE(src_type);
1340 dst_type = CV_MAT_TYPE(dst_type);
1341
1342 if( CV_MAT_CN(src_type) != 1 || CV_MAT_CN(dst_type) != 1 )
1343 CV_ERROR( CV_StsUnsupportedFormat, "The function supports only single-channel arrays" );
1344
1345 if( src_step == 0 )
1346 src_step = CV_ELEM_SIZE(src_type);
1347
1348 if( dst_step == 0 )
1349 dst_step = CV_ELEM_SIZE(dst_type);
1350
1351 // if there is no "idx" and if both arrays are continuous,
1352 // do the whole processing (copying or conversion) in a single loop
1353 if( !idx && CV_ELEM_SIZE(src_type)*size.width == src_step &&
1354 CV_ELEM_SIZE(dst_type)*size.width == dst_step )
1355 {
1356 size.width *= size.height;
1357 size.height = 1;
1358 }
1359
1360 if( src_type == dst_type )
1361 {
1362 int full_width = CV_ELEM_SIZE(dst_type)*size.width;
1363
1364 if( full_width == sizeof(int) ) // another common case: copy int's or float's
1365 for( i = 0; i < size.height; i++, src += src_step )
1366 *(int*)(dst + dst_step*(idx ? idx[i] : i)) = *(int*)src;
1367 else
1368 for( i = 0; i < size.height; i++, src += src_step )
1369 memcpy( dst + dst_step*(idx ? idx[i] : i), src, full_width );
1370 }
1371 else if( src_type == CV_32SC1 && (dst_type == CV_32FC1 || dst_type == CV_64FC1) )
1372 for( i = 0; i < size.height; i++, src += src_step )
1373 {
1374 uchar* _dst = dst + dst_step*(idx ? idx[i] : i);
1375 if( dst_type == CV_32FC1 )
1376 for( j = 0; j < size.width; j++ )
1377 ((float*)_dst)[j] = (float)((int*)src)[j];
1378 else
1379 for( j = 0; j < size.width; j++ )
1380 ((double*)_dst)[j] = ((int*)src)[j];
1381 }
1382 else if( (src_type == CV_32FC1 || src_type == CV_64FC1) && dst_type == CV_32SC1 )
1383 for( i = 0; i < size.height; i++, src += src_step )
1384 {
1385 uchar* _dst = dst + dst_step*(idx ? idx[i] : i);
1386 if( src_type == CV_32FC1 )
1387 for( j = 0; j < size.width; j++ )
1388 ((int*)_dst)[j] = cvRound(((float*)src)[j]);
1389 else
1390 for( j = 0; j < size.width; j++ )
1391 ((int*)_dst)[j] = cvRound(((double*)src)[j]);
1392 }
1393 else if( src_type == CV_32FC1 && dst_type == CV_64FC1 ||
1394 src_type == CV_64FC1 && dst_type == CV_32FC1 )
1395 for( i = 0; i < size.height; i++, src += src_step )
1396 {
1397 uchar* _dst = dst + dst_step*(idx ? idx[i] : i);
1398 if( src_type == CV_32FC1 )
1399 for( j = 0; j < size.width; j++ )
1400 ((double*)_dst)[j] = ((float*)src)[j];
1401 else
1402 for( j = 0; j < size.width; j++ )
1403 ((float*)_dst)[j] = (float)((double*)src)[j];
1404 }
1405 else
1406 CV_ERROR( CV_StsUnsupportedFormat, "Unsupported combination of input and output vectors" );
1407
1408 __END__;
1409 }
1410
1411
1412 void
cvWritebackLabels(const CvMat * labels,CvMat * dst_labels,const CvMat * centers,CvMat * dst_centers,const CvMat * probs,CvMat * dst_probs,const CvMat * sample_idx,int samples_all,const CvMat * comp_idx,int dims_all)1413 cvWritebackLabels( const CvMat* labels, CvMat* dst_labels,
1414 const CvMat* centers, CvMat* dst_centers,
1415 const CvMat* probs, CvMat* dst_probs,
1416 const CvMat* sample_idx, int samples_all,
1417 const CvMat* comp_idx, int dims_all )
1418 {
1419 CV_FUNCNAME( "cvWritebackLabels" );
1420
1421 __BEGIN__;
1422
1423 int samples_selected = samples_all, dims_selected = dims_all;
1424
1425 if( dst_labels && !CV_IS_MAT(dst_labels) )
1426 CV_ERROR( CV_StsBadArg, "Array of output labels is not a valid matrix" );
1427
1428 if( dst_centers )
1429 if( !ICV_IS_MAT_OF_TYPE(dst_centers, CV_32FC1) &&
1430 !ICV_IS_MAT_OF_TYPE(dst_centers, CV_64FC1) )
1431 CV_ERROR( CV_StsBadArg, "Array of cluster centers is not a valid matrix" );
1432
1433 if( dst_probs && !CV_IS_MAT(dst_probs) )
1434 CV_ERROR( CV_StsBadArg, "Probability matrix is not valid" );
1435
1436 if( sample_idx )
1437 {
1438 CV_ASSERT( sample_idx->rows == 1 && CV_MAT_TYPE(sample_idx->type) == CV_32SC1 );
1439 samples_selected = sample_idx->cols;
1440 }
1441
1442 if( comp_idx )
1443 {
1444 CV_ASSERT( comp_idx->rows == 1 && CV_MAT_TYPE(comp_idx->type) == CV_32SC1 );
1445 dims_selected = comp_idx->cols;
1446 }
1447
1448 if( dst_labels && (!labels || labels->data.ptr != dst_labels->data.ptr) )
1449 {
1450 if( !labels )
1451 CV_ERROR( CV_StsNullPtr, "NULL labels" );
1452
1453 CV_ASSERT( labels->rows == 1 );
1454
1455 if( dst_labels->rows != 1 && dst_labels->cols != 1 )
1456 CV_ERROR( CV_StsBadSize, "Array of output labels should be 1d vector" );
1457
1458 if( dst_labels->rows + dst_labels->cols - 1 != samples_all )
1459 CV_ERROR( CV_StsUnmatchedSizes,
1460 "Size of vector of output labels is not equal to the total number of input samples" );
1461
1462 CV_ASSERT( labels->cols == samples_selected );
1463
1464 CV_CALL( icvConvertDataToSparse( labels->data.ptr, labels->step, labels->type,
1465 dst_labels->data.ptr, dst_labels->step, dst_labels->type,
1466 cvSize( 1, samples_selected ), sample_idx ? sample_idx->data.i : 0 ));
1467 }
1468
1469 if( dst_centers && (!centers || centers->data.ptr != dst_centers->data.ptr) )
1470 {
1471 int i;
1472
1473 if( !centers )
1474 CV_ERROR( CV_StsNullPtr, "NULL centers" );
1475
1476 if( centers->rows != dst_centers->rows )
1477 CV_ERROR( CV_StsUnmatchedSizes, "Invalid number of rows in matrix of output centers" );
1478
1479 if( dst_centers->cols != dims_all )
1480 CV_ERROR( CV_StsUnmatchedSizes,
1481 "Number of columns in matrix of output centers is "
1482 "not equal to the total number of components in the input samples" );
1483
1484 CV_ASSERT( centers->cols == dims_selected );
1485
1486 for( i = 0; i < centers->rows; i++ )
1487 CV_CALL( icvConvertDataToSparse( centers->data.ptr + i*centers->step, 0, centers->type,
1488 dst_centers->data.ptr + i*dst_centers->step, 0, dst_centers->type,
1489 cvSize( 1, dims_selected ), comp_idx ? comp_idx->data.i : 0 ));
1490 }
1491
1492 if( dst_probs && (!probs || probs->data.ptr != dst_probs->data.ptr) )
1493 {
1494 if( !probs )
1495 CV_ERROR( CV_StsNullPtr, "NULL probs" );
1496
1497 if( probs->cols != dst_probs->cols )
1498 CV_ERROR( CV_StsUnmatchedSizes, "Invalid number of columns in output probability matrix" );
1499
1500 if( dst_probs->rows != samples_all )
1501 CV_ERROR( CV_StsUnmatchedSizes,
1502 "Number of rows in output probability matrix is "
1503 "not equal to the total number of input samples" );
1504
1505 CV_ASSERT( probs->rows == samples_selected );
1506
1507 CV_CALL( icvConvertDataToSparse( probs->data.ptr, probs->step, probs->type,
1508 dst_probs->data.ptr, dst_probs->step, dst_probs->type,
1509 cvSize( probs->cols, samples_selected ),
1510 sample_idx ? sample_idx->data.i : 0 ));
1511 }
1512
1513 __END__;
1514 }
1515
1516 #if 0
1517 CV_IMPL void
1518 cvStatModelMultiPredict( const CvStatModel* stat_model,
1519 const CvArr* predict_input,
1520 int flags, CvMat* predict_output,
1521 CvMat* probs, const CvMat* sample_idx )
1522 {
1523 CvMemStorage* storage = 0;
1524 CvMat* sample_idx_buffer = 0;
1525 CvSparseMat** sparse_rows = 0;
1526 int samples_selected = 0;
1527
1528 CV_FUNCNAME( "cvStatModelMultiPredict" );
1529
1530 __BEGIN__;
1531
1532 int i;
1533 int predict_output_step = 1, sample_idx_step = 1;
1534 int type;
1535 int d, sizes[CV_MAX_DIM];
1536 int tflag = flags == CV_COL_SAMPLE;
1537 int samples_all, dims_all;
1538 int is_sparse = CV_IS_SPARSE_MAT(predict_input);
1539 CvMat predict_input_part;
1540 CvArr* sample = &predict_input_part;
1541 CvMat probs_part;
1542 CvMat* probs1 = probs ? &probs_part : 0;
1543
1544 if( !CV_IS_STAT_MODEL(stat_model) )
1545 CV_ERROR( !stat_model ? CV_StsNullPtr : CV_StsBadArg, "Invalid statistical model" );
1546
1547 if( !stat_model->predict )
1548 CV_ERROR( CV_StsNotImplemented, "There is no \"predict\" method" );
1549
1550 if( !predict_input || !predict_output )
1551 CV_ERROR( CV_StsNullPtr, "NULL input or output matrices" );
1552
1553 if( !is_sparse && !CV_IS_MAT(predict_input) )
1554 CV_ERROR( CV_StsBadArg, "predict_input should be a matrix or a sparse matrix" );
1555
1556 if( !CV_IS_MAT(predict_output) )
1557 CV_ERROR( CV_StsBadArg, "predict_output should be a matrix" );
1558
1559 type = cvGetElemType( predict_input );
1560 if( type != CV_32FC1 ||
1561 (CV_MAT_TYPE(predict_output->type) != CV_32FC1 &&
1562 CV_MAT_TYPE(predict_output->type) != CV_32SC1 ))
1563 CV_ERROR( CV_StsUnsupportedFormat, "The input or output matrix has unsupported format" );
1564
1565 CV_CALL( d = cvGetDims( predict_input, sizes ));
1566 if( d > 2 )
1567 CV_ERROR( CV_StsBadSize, "The input matrix should be 1- or 2-dimensional" );
1568
1569 if( !tflag )
1570 {
1571 samples_all = samples_selected = sizes[0];
1572 dims_all = sizes[1];
1573 }
1574 else
1575 {
1576 samples_all = samples_selected = sizes[1];
1577 dims_all = sizes[0];
1578 }
1579
1580 if( sample_idx )
1581 {
1582 if( !CV_IS_MAT(sample_idx) )
1583 CV_ERROR( CV_StsBadArg, "Invalid sample_idx matrix" );
1584
1585 if( sample_idx->cols != 1 && sample_idx->rows != 1 )
1586 CV_ERROR( CV_StsBadSize, "sample_idx must be 1-dimensional matrix" );
1587
1588 samples_selected = sample_idx->rows + sample_idx->cols - 1;
1589
1590 if( CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )
1591 {
1592 if( samples_selected > samples_all )
1593 CV_ERROR( CV_StsBadSize, "sample_idx is too large vector" );
1594 }
1595 else if( samples_selected != samples_all )
1596 CV_ERROR( CV_StsUnmatchedSizes, "sample_idx has incorrect size" );
1597
1598 sample_idx_step = sample_idx->step ?
1599 sample_idx->step / CV_ELEM_SIZE(sample_idx->type) : 1;
1600 }
1601
1602 if( predict_output->rows != 1 && predict_output->cols != 1 )
1603 CV_ERROR( CV_StsBadSize, "predict_output should be a 1-dimensional matrix" );
1604
1605 if( predict_output->rows + predict_output->cols - 1 != samples_all )
1606 CV_ERROR( CV_StsUnmatchedSizes, "predict_output and predict_input have uncoordinated sizes" );
1607
1608 predict_output_step = predict_output->step ?
1609 predict_output->step / CV_ELEM_SIZE(predict_output->type) : 1;
1610
1611 if( probs )
1612 {
1613 if( !CV_IS_MAT(probs) )
1614 CV_ERROR( CV_StsBadArg, "Invalid matrix of probabilities" );
1615
1616 if( probs->rows != samples_all )
1617 CV_ERROR( CV_StsUnmatchedSizes,
1618 "matrix of probabilities must have as many rows as the total number of samples" );
1619
1620 if( CV_MAT_TYPE(probs->type) != CV_32FC1 )
1621 CV_ERROR( CV_StsUnsupportedFormat, "matrix of probabilities must have 32fC1 type" );
1622 }
1623
1624 if( is_sparse )
1625 {
1626 CvSparseNode* node;
1627 CvSparseMatIterator mat_iterator;
1628 CvSparseMat* sparse = (CvSparseMat*)predict_input;
1629
1630 if( sample_idx && CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )
1631 {
1632 CV_CALL( sample_idx_buffer = cvCreateMat( 1, samples_all, CV_8UC1 ));
1633 cvZero( sample_idx_buffer );
1634 for( i = 0; i < samples_selected; i++ )
1635 sample_idx_buffer->data.ptr[sample_idx->data.i[i*sample_idx_step]] = 1;
1636 samples_selected = samples_all;
1637 sample_idx = sample_idx_buffer;
1638 sample_idx_step = 1;
1639 }
1640
1641 CV_CALL( sparse_rows = (CvSparseMat**)cvAlloc( samples_selected*sizeof(sparse_rows[0])));
1642 for( i = 0; i < samples_selected; i++ )
1643 {
1644 if( sample_idx && sample_idx->data.ptr[i*sample_idx_step] == 0 )
1645 continue;
1646 CV_CALL( sparse_rows[i] = cvCreateSparseMat( 1, &dims_all, type ));
1647 if( !storage )
1648 storage = sparse_rows[i]->heap->storage;
1649 else
1650 {
1651 // hack: to decrease memory footprint, make all the sparse matrices
1652 // reside in the same storage
1653 int elem_size = sparse_rows[i]->heap->elem_size;
1654 cvReleaseMemStorage( &sparse_rows[i]->heap->storage );
1655 sparse_rows[i]->heap = cvCreateSet( 0, sizeof(CvSet), elem_size, storage );
1656 }
1657 }
1658
1659 // put each row (or column) of predict_input into separate sparse matrix.
1660 node = cvInitSparseMatIterator( sparse, &mat_iterator );
1661 for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
1662 {
1663 int* idx = CV_NODE_IDX( sparse, node );
1664 int idx0 = idx[tflag ^ 1];
1665 int idx1 = idx[tflag];
1666
1667 if( sample_idx && sample_idx->data.ptr[idx0*sample_idx_step] == 0 )
1668 continue;
1669
1670 assert( sparse_rows[idx0] != 0 );
1671 *(float*)cvPtrND( sparse, &idx1, 0, 1, 0 ) = *(float*)CV_NODE_VAL( sparse, node );
1672 }
1673 }
1674
1675 for( i = 0; i < samples_selected; i++ )
1676 {
1677 int idx = i;
1678 float response;
1679
1680 if( sample_idx )
1681 {
1682 if( CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )
1683 {
1684 idx = sample_idx->data.i[i*sample_idx_step];
1685 if( (unsigned)idx >= (unsigned)samples_all )
1686 CV_ERROR( CV_StsOutOfRange, "Some of sample_idx elements are out of range" );
1687 }
1688 else if( CV_MAT_TYPE(sample_idx->type) == CV_8UC1 &&
1689 sample_idx->data.ptr[i*sample_idx_step] == 0 )
1690 continue;
1691 }
1692
1693 if( !is_sparse )
1694 {
1695 if( !tflag )
1696 cvGetRow( predict_input, &predict_input_part, idx );
1697 else
1698 {
1699 cvGetCol( predict_input, &predict_input_part, idx );
1700 }
1701 }
1702 else
1703 sample = sparse_rows[idx];
1704
1705 if( probs )
1706 cvGetRow( probs, probs1, idx );
1707
1708 CV_CALL( response = stat_model->predict( stat_model, (CvMat*)sample, probs1 ));
1709
1710 if( CV_MAT_TYPE(predict_output->type) == CV_32FC1 )
1711 predict_output->data.fl[idx*predict_output_step] = response;
1712 else
1713 {
1714 CV_ASSERT( cvRound(response) == response );
1715 predict_output->data.i[idx*predict_output_step] = cvRound(response);
1716 }
1717 }
1718
1719 __END__;
1720
1721 if( sparse_rows )
1722 {
1723 int i;
1724 for( i = 0; i < samples_selected; i++ )
1725 if( sparse_rows[i] )
1726 {
1727 sparse_rows[i]->heap->storage = 0;
1728 cvReleaseSparseMat( &sparse_rows[i] );
1729 }
1730 cvFree( &sparse_rows );
1731 }
1732
1733 cvReleaseMat( &sample_idx_buffer );
1734 cvReleaseMemStorage( &storage );
1735 }
1736 #endif
1737
1738 // By P. Yarykin - begin -
1739
cvCombineResponseMaps(CvMat * _responses,const CvMat * old_response_map,CvMat * new_response_map,CvMat ** out_response_map)1740 void cvCombineResponseMaps (CvMat* _responses,
1741 const CvMat* old_response_map,
1742 CvMat* new_response_map,
1743 CvMat** out_response_map)
1744 {
1745 int** old_data = NULL;
1746 int** new_data = NULL;
1747
1748 CV_FUNCNAME ("cvCombineResponseMaps");
1749 __BEGIN__
1750
1751 int i,j;
1752 int old_n, new_n, out_n;
1753 int samples, free_response;
1754 int* first;
1755 int* responses;
1756 int* out_data;
1757
1758 if( out_response_map )
1759 *out_response_map = 0;
1760
1761 // Check input data.
1762 if ((!ICV_IS_MAT_OF_TYPE (_responses, CV_32SC1)) ||
1763 (!ICV_IS_MAT_OF_TYPE (old_response_map, CV_32SC1)) ||
1764 (!ICV_IS_MAT_OF_TYPE (new_response_map, CV_32SC1)))
1765 {
1766 CV_ERROR (CV_StsBadArg, "Some of input arguments is not the CvMat")
1767 }
1768
1769 // Prepare sorted responses.
1770 first = new_response_map->data.i;
1771 new_n = new_response_map->cols;
1772 CV_CALL (new_data = (int**)cvAlloc (new_n * sizeof (new_data[0])));
1773 for (i = 0; i < new_n; i++)
1774 new_data[i] = first + i;
1775 qsort (new_data, new_n, sizeof(int*), icvCmpIntegersPtr);
1776
1777 first = old_response_map->data.i;
1778 old_n = old_response_map->cols;
1779 CV_CALL (old_data = (int**)cvAlloc (old_n * sizeof (old_data[0])));
1780 for (i = 0; i < old_n; i++)
1781 old_data[i] = first + i;
1782 qsort (old_data, old_n, sizeof(int*), icvCmpIntegersPtr);
1783
1784 // Count the number of different responses.
1785 for (i = 0, j = 0, out_n = 0; i < old_n && j < new_n; out_n++)
1786 {
1787 if (*old_data[i] == *new_data[j])
1788 {
1789 i++;
1790 j++;
1791 }
1792 else if (*old_data[i] < *new_data[j])
1793 i++;
1794 else
1795 j++;
1796 }
1797 out_n += old_n - i + new_n - j;
1798
1799 // Create and fill the result response maps.
1800 CV_CALL (*out_response_map = cvCreateMat (1, out_n, CV_32SC1));
1801 out_data = (*out_response_map)->data.i;
1802 memcpy (out_data, first, old_n * sizeof (int));
1803
1804 free_response = old_n;
1805 for (i = 0, j = 0; i < old_n && j < new_n; )
1806 {
1807 if (*old_data[i] == *new_data[j])
1808 {
1809 *new_data[j] = (int)(old_data[i] - first);
1810 i++;
1811 j++;
1812 }
1813 else if (*old_data[i] < *new_data[j])
1814 i++;
1815 else
1816 {
1817 out_data[free_response] = *new_data[j];
1818 *new_data[j] = free_response++;
1819 j++;
1820 }
1821 }
1822 for (; j < new_n; j++)
1823 {
1824 out_data[free_response] = *new_data[j];
1825 *new_data[j] = free_response++;
1826 }
1827 CV_ASSERT (free_response == out_n);
1828
1829 // Change <responses> according to out response map.
1830 samples = _responses->cols + _responses->rows - 1;
1831 responses = _responses->data.i;
1832 first = new_response_map->data.i;
1833 for (i = 0; i < samples; i++)
1834 {
1835 responses[i] = first[responses[i]];
1836 }
1837
1838 __END__
1839
1840 cvFree(&old_data);
1841 cvFree(&new_data);
1842
1843 }
1844
1845
icvGetNumberOfCluster(double * prob_vector,int num_of_clusters,float r,float outlier_thresh,int normalize_probs)1846 int icvGetNumberOfCluster( double* prob_vector, int num_of_clusters, float r,
1847 float outlier_thresh, int normalize_probs )
1848 {
1849 int max_prob_loc = 0;
1850
1851 CV_FUNCNAME("icvGetNumberOfCluster");
1852 __BEGIN__;
1853
1854 double prob, maxprob, sum;
1855 int i;
1856
1857 CV_ASSERT(prob_vector);
1858 CV_ASSERT(num_of_clusters >= 0);
1859
1860 maxprob = prob_vector[0];
1861 max_prob_loc = 0;
1862 sum = maxprob;
1863 for( i = 1; i < num_of_clusters; i++ )
1864 {
1865 prob = prob_vector[i];
1866 sum += prob;
1867 if( prob > maxprob )
1868 {
1869 max_prob_loc = i;
1870 maxprob = prob;
1871 }
1872 }
1873 if( normalize_probs && fabs(sum - 1.) > FLT_EPSILON )
1874 {
1875 for( i = 0; i < num_of_clusters; i++ )
1876 prob_vector[i] /= sum;
1877 }
1878 if( fabs(r - 1.) > FLT_EPSILON && fabs(sum - 1.) < outlier_thresh )
1879 max_prob_loc = -1;
1880
1881 __END__;
1882
1883 return max_prob_loc;
1884
1885 } // End of icvGetNumberOfCluster
1886
1887
icvFindClusterLabels(const CvMat * probs,float outlier_thresh,float r,const CvMat * labels)1888 void icvFindClusterLabels( const CvMat* probs, float outlier_thresh, float r,
1889 const CvMat* labels )
1890 {
1891 CvMat* counts = 0;
1892
1893 CV_FUNCNAME("icvFindClusterLabels");
1894 __BEGIN__;
1895
1896 int nclusters, nsamples;
1897 int i, j;
1898 double* probs_data;
1899
1900 CV_ASSERT( ICV_IS_MAT_OF_TYPE(probs, CV_64FC1) );
1901 CV_ASSERT( ICV_IS_MAT_OF_TYPE(labels, CV_32SC1) );
1902
1903 nclusters = probs->cols;
1904 nsamples = probs->rows;
1905 CV_ASSERT( nsamples == labels->cols );
1906
1907 CV_CALL( counts = cvCreateMat( 1, nclusters + 1, CV_32SC1 ) );
1908 CV_CALL( cvSetZero( counts ));
1909 for( i = 0; i < nsamples; i++ )
1910 {
1911 labels->data.i[i] = icvGetNumberOfCluster( probs->data.db + i*probs->cols,
1912 nclusters, r, outlier_thresh, 1 );
1913 counts->data.i[labels->data.i[i] + 1]++;
1914 }
1915 CV_ASSERT((int)cvSum(counts).val[0] == nsamples);
1916 // Filling empty clusters with the vector, that has the maximal probability
1917 for( j = 0; j < nclusters; j++ ) // outliers are ignored
1918 {
1919 int maxprob_loc = -1;
1920 double maxprob = 0;
1921
1922 if( counts->data.i[j+1] ) // j-th class is not empty
1923 continue;
1924 // look for the presentative, which is not lonely in it's cluster
1925 // and that has a maximal probability among all these vectors
1926 probs_data = probs->data.db;
1927 for( i = 0; i < nsamples; i++, probs_data++ )
1928 {
1929 int label = labels->data.i[i];
1930 double prob;
1931 if( counts->data.i[label+1] == 0 ||
1932 (counts->data.i[label+1] <= 1 && label != -1) )
1933 continue;
1934 prob = *probs_data;
1935 if( prob >= maxprob )
1936 {
1937 maxprob = prob;
1938 maxprob_loc = i;
1939 }
1940 }
1941 // maxprob_loc == 0 <=> number of vectors less then number of clusters
1942 CV_ASSERT( maxprob_loc >= 0 );
1943 counts->data.i[labels->data.i[maxprob_loc] + 1]--;
1944 labels->data.i[maxprob_loc] = j;
1945 counts->data.i[j + 1]++;
1946 }
1947
1948 __END__;
1949
1950 cvReleaseMat( &counts );
1951 } // End of icvFindClusterLabels
1952
1953 /* End of file */
1954