Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/apps/traincascade/old_ml_inner_functions.cpp
16337 views
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 "old_ml_precomp.hpp"
42
43
44
CvStatModel::CvStatModel()
45
{
46
default_model_name = "my_stat_model";
47
}
48
49
50
CvStatModel::~CvStatModel()
51
{
52
clear();
53
}
54
55
56
void CvStatModel::clear()
57
{
58
}
59
60
61
void CvStatModel::save( const char* filename, const char* name ) const
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
81
void CvStatModel::load( const char* filename, const char* name )
82
{
83
CvFileStorage* fs = 0;
84
85
CV_FUNCNAME( "CvAlgorithm::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
112
void CvStatModel::write( CvFileStorage*, const char* ) const
113
{
114
OPENCV_ERROR( CV_StsNotImplemented, "CvStatModel::write", "" );
115
}
116
117
void CvStatModel::read( CvFileStorage*, CvFileNode* )
118
{
119
OPENCV_ERROR( CV_StsNotImplemented, "CvStatModel::read", "" );
120
}
121
122
CvMat* icvGenerateRandomClusterCenters ( int seed, const CvMat* data,
123
int num_of_clusters, CvMat* _centers )
124
{
125
CvMat* centers = _centers;
126
127
CV_FUNCNAME("icvGenerateRandomClusterCenters");
128
__BEGIN__;
129
130
CvRNG rng;
131
CvMat data_comp, centers_comp;
132
CvPoint minLoc, maxLoc; // Not used, just for function "cvMinMaxLoc"
133
double minVal, maxVal;
134
int i;
135
int dim = data ? data->cols : 0;
136
137
if( ICV_IS_MAT_OF_TYPE(data, CV_32FC1) )
138
{
139
if( _centers && !ICV_IS_MAT_OF_TYPE (_centers, CV_32FC1) )
140
{
141
CV_ERROR(CV_StsBadArg,"");
142
}
143
else if( !_centers )
144
CV_CALL(centers = cvCreateMat (num_of_clusters, dim, CV_32FC1));
145
}
146
else if( ICV_IS_MAT_OF_TYPE(data, CV_64FC1) )
147
{
148
if( _centers && !ICV_IS_MAT_OF_TYPE (_centers, CV_64FC1) )
149
{
150
CV_ERROR(CV_StsBadArg,"");
151
}
152
else if( !_centers )
153
CV_CALL(centers = cvCreateMat (num_of_clusters, dim, CV_64FC1));
154
}
155
else
156
CV_ERROR (CV_StsBadArg,"");
157
158
if( num_of_clusters < 1 )
159
CV_ERROR (CV_StsBadArg,"");
160
161
rng = cvRNG(seed);
162
for (i = 0; i < dim; i++)
163
{
164
CV_CALL(cvGetCol (data, &data_comp, i));
165
CV_CALL(cvMinMaxLoc (&data_comp, &minVal, &maxVal, &minLoc, &maxLoc));
166
CV_CALL(cvGetCol (centers, &centers_comp, i));
167
CV_CALL(cvRandArr (&rng, &centers_comp, CV_RAND_UNI, cvScalarAll(minVal), cvScalarAll(maxVal)));
168
}
169
170
__END__;
171
172
if( (cvGetErrStatus () < 0) || (centers != _centers) )
173
cvReleaseMat (&centers);
174
175
return _centers ? _centers : centers;
176
} // end of icvGenerateRandomClusterCenters
177
178
static int CV_CDECL
179
icvCmpIntegers( const void* a, const void* b )
180
{
181
return *(const int*)a - *(const int*)b;
182
}
183
184
185
static int CV_CDECL
186
icvCmpIntegersPtr( const void* _a, const void* _b )
187
{
188
int a = **(const int**)_a;
189
int b = **(const int**)_b;
190
return (a < b ? -1 : 0)|(a > b);
191
}
192
193
194
static int icvCmpSparseVecElems( const void* a, const void* b )
195
{
196
return ((CvSparseVecElem32f*)a)->idx - ((CvSparseVecElem32f*)b)->idx;
197
}
198
199
200
CvMat*
201
cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, bool check_for_duplicates )
202
{
203
CvMat* idx = 0;
204
205
CV_FUNCNAME( "cvPreprocessIndexArray" );
206
207
__BEGIN__;
208
209
int i, idx_total, idx_selected = 0, step, type, prev = INT_MIN, is_sorted = 1;
210
uchar* srcb = 0;
211
int* srci = 0;
212
int* dsti;
213
214
if( !CV_IS_MAT(idx_arr) )
215
CV_ERROR( CV_StsBadArg, "Invalid index array" );
216
217
if( idx_arr->rows != 1 && idx_arr->cols != 1 )
218
CV_ERROR( CV_StsBadSize, "the index array must be 1-dimensional" );
219
220
idx_total = idx_arr->rows + idx_arr->cols - 1;
221
srcb = idx_arr->data.ptr;
222
srci = idx_arr->data.i;
223
224
type = CV_MAT_TYPE(idx_arr->type);
225
step = CV_IS_MAT_CONT(idx_arr->type) ? 1 : idx_arr->step/CV_ELEM_SIZE(type);
226
227
switch( type )
228
{
229
case CV_8UC1:
230
case CV_8SC1:
231
// idx_arr is array of 1's and 0's -
232
// i.e. it is a mask of the selected components
233
if( idx_total != data_arr_size )
234
CV_ERROR( CV_StsUnmatchedSizes,
235
"Component mask should contain as many elements as the total number of input variables" );
236
237
for( i = 0; i < idx_total; i++ )
238
idx_selected += srcb[i*step] != 0;
239
240
if( idx_selected == 0 )
241
CV_ERROR( CV_StsOutOfRange, "No components/input_variables is selected!" );
242
243
break;
244
case CV_32SC1:
245
// idx_arr is array of integer indices of selected components
246
if( idx_total > data_arr_size )
247
CV_ERROR( CV_StsOutOfRange,
248
"index array may not contain more elements than the total number of input variables" );
249
idx_selected = idx_total;
250
// check if sorted already
251
for( i = 0; i < idx_total; i++ )
252
{
253
int val = srci[i*step];
254
if( val >= prev )
255
{
256
is_sorted = 0;
257
break;
258
}
259
prev = val;
260
}
261
break;
262
default:
263
CV_ERROR( CV_StsUnsupportedFormat, "Unsupported index array data type "
264
"(it should be 8uC1, 8sC1 or 32sC1)" );
265
}
266
267
CV_CALL( idx = cvCreateMat( 1, idx_selected, CV_32SC1 ));
268
dsti = idx->data.i;
269
270
if( type < CV_32SC1 )
271
{
272
for( i = 0; i < idx_total; i++ )
273
if( srcb[i*step] )
274
*dsti++ = i;
275
}
276
else
277
{
278
for( i = 0; i < idx_total; i++ )
279
dsti[i] = srci[i*step];
280
281
if( !is_sorted )
282
qsort( dsti, idx_total, sizeof(dsti[0]), icvCmpIntegers );
283
284
if( dsti[0] < 0 || dsti[idx_total-1] >= data_arr_size )
285
CV_ERROR( CV_StsOutOfRange, "the index array elements are out of range" );
286
287
if( check_for_duplicates )
288
{
289
for( i = 1; i < idx_total; i++ )
290
if( dsti[i] <= dsti[i-1] )
291
CV_ERROR( CV_StsBadArg, "There are duplicated index array elements" );
292
}
293
}
294
295
__END__;
296
297
if( cvGetErrStatus() < 0 )
298
cvReleaseMat( &idx );
299
300
return idx;
301
}
302
303
304
CvMat*
305
cvPreprocessVarType( const CvMat* var_type, const CvMat* var_idx,
306
int var_count, int* response_type )
307
{
308
CvMat* out_var_type = 0;
309
CV_FUNCNAME( "cvPreprocessVarType" );
310
311
if( response_type )
312
*response_type = -1;
313
314
__BEGIN__;
315
316
int i, tm_size, tm_step;
317
//int* map = 0;
318
const uchar* src;
319
uchar* dst;
320
321
if( !CV_IS_MAT(var_type) )
322
CV_ERROR( var_type ? CV_StsBadArg : CV_StsNullPtr, "Invalid or absent var_type array" );
323
324
if( var_type->rows != 1 && var_type->cols != 1 )
325
CV_ERROR( CV_StsBadSize, "var_type array must be 1-dimensional" );
326
327
if( !CV_IS_MASK_ARR(var_type))
328
CV_ERROR( CV_StsUnsupportedFormat, "type mask must be 8uC1 or 8sC1 array" );
329
330
tm_size = var_type->rows + var_type->cols - 1;
331
tm_step = var_type->rows == 1 ? 1 : var_type->step/CV_ELEM_SIZE(var_type->type);
332
333
if( /*tm_size != var_count &&*/ tm_size != var_count + 1 )
334
CV_ERROR( CV_StsBadArg,
335
"type mask must be of <input var count> + 1 size" );
336
337
if( response_type && tm_size > var_count )
338
*response_type = var_type->data.ptr[var_count*tm_step] != 0;
339
340
if( var_idx )
341
{
342
if( !CV_IS_MAT(var_idx) || CV_MAT_TYPE(var_idx->type) != CV_32SC1 ||
343
(var_idx->rows != 1 && var_idx->cols != 1) || !CV_IS_MAT_CONT(var_idx->type) )
344
CV_ERROR( CV_StsBadArg, "var index array should be continuous 1-dimensional integer vector" );
345
if( var_idx->rows + var_idx->cols - 1 > var_count )
346
CV_ERROR( CV_StsBadSize, "var index array is too large" );
347
//map = var_idx->data.i;
348
var_count = var_idx->rows + var_idx->cols - 1;
349
}
350
351
CV_CALL( out_var_type = cvCreateMat( 1, var_count, CV_8UC1 ));
352
src = var_type->data.ptr;
353
dst = out_var_type->data.ptr;
354
355
for( i = 0; i < var_count; i++ )
356
{
357
//int idx = map ? map[i] : i;
358
assert( (unsigned)/*idx*/i < (unsigned)tm_size );
359
dst[i] = (uchar)(src[/*idx*/i*tm_step] != 0);
360
}
361
362
__END__;
363
364
return out_var_type;
365
}
366
367
368
CvMat*
369
cvPreprocessOrderedResponses( const CvMat* responses, const CvMat* sample_idx, int sample_all )
370
{
371
CvMat* out_responses = 0;
372
373
CV_FUNCNAME( "cvPreprocessOrderedResponses" );
374
375
__BEGIN__;
376
377
int i, r_type, r_step;
378
const int* map = 0;
379
float* dst;
380
int sample_count = sample_all;
381
382
if( !CV_IS_MAT(responses) )
383
CV_ERROR( CV_StsBadArg, "Invalid response array" );
384
385
if( responses->rows != 1 && responses->cols != 1 )
386
CV_ERROR( CV_StsBadSize, "Response array must be 1-dimensional" );
387
388
if( responses->rows + responses->cols - 1 != sample_count )
389
CV_ERROR( CV_StsUnmatchedSizes,
390
"Response array must contain as many elements as the total number of samples" );
391
392
r_type = CV_MAT_TYPE(responses->type);
393
if( r_type != CV_32FC1 && r_type != CV_32SC1 )
394
CV_ERROR( CV_StsUnsupportedFormat, "Unsupported response type" );
395
396
r_step = responses->step ? responses->step / CV_ELEM_SIZE(responses->type) : 1;
397
398
if( r_type == CV_32FC1 && CV_IS_MAT_CONT(responses->type) && !sample_idx )
399
{
400
out_responses = cvCloneMat( responses );
401
EXIT;
402
}
403
404
if( sample_idx )
405
{
406
if( !CV_IS_MAT(sample_idx) || CV_MAT_TYPE(sample_idx->type) != CV_32SC1 ||
407
(sample_idx->rows != 1 && sample_idx->cols != 1) || !CV_IS_MAT_CONT(sample_idx->type) )
408
CV_ERROR( CV_StsBadArg, "sample index array should be continuous 1-dimensional integer vector" );
409
if( sample_idx->rows + sample_idx->cols - 1 > sample_count )
410
CV_ERROR( CV_StsBadSize, "sample index array is too large" );
411
map = sample_idx->data.i;
412
sample_count = sample_idx->rows + sample_idx->cols - 1;
413
}
414
415
CV_CALL( out_responses = cvCreateMat( 1, sample_count, CV_32FC1 ));
416
417
dst = out_responses->data.fl;
418
if( r_type == CV_32FC1 )
419
{
420
const float* src = responses->data.fl;
421
for( i = 0; i < sample_count; i++ )
422
{
423
int idx = map ? map[i] : i;
424
assert( (unsigned)idx < (unsigned)sample_all );
425
dst[i] = src[idx*r_step];
426
}
427
}
428
else
429
{
430
const int* src = responses->data.i;
431
for( i = 0; i < sample_count; i++ )
432
{
433
int idx = map ? map[i] : i;
434
assert( (unsigned)idx < (unsigned)sample_all );
435
dst[i] = (float)src[idx*r_step];
436
}
437
}
438
439
__END__;
440
441
return out_responses;
442
}
443
444
CvMat*
445
cvPreprocessCategoricalResponses( const CvMat* responses,
446
const CvMat* sample_idx, int sample_all,
447
CvMat** out_response_map, CvMat** class_counts )
448
{
449
CvMat* out_responses = 0;
450
int** response_ptr = 0;
451
452
CV_FUNCNAME( "cvPreprocessCategoricalResponses" );
453
454
if( out_response_map )
455
*out_response_map = 0;
456
457
if( class_counts )
458
*class_counts = 0;
459
460
__BEGIN__;
461
462
int i, r_type, r_step;
463
int cls_count = 1, prev_cls, prev_i;
464
const int* map = 0;
465
const int* srci;
466
const float* srcfl;
467
int* dst;
468
int* cls_map;
469
int* cls_counts = 0;
470
int sample_count = sample_all;
471
472
if( !CV_IS_MAT(responses) )
473
CV_ERROR( CV_StsBadArg, "Invalid response array" );
474
475
if( responses->rows != 1 && responses->cols != 1 )
476
CV_ERROR( CV_StsBadSize, "Response array must be 1-dimensional" );
477
478
if( responses->rows + responses->cols - 1 != sample_count )
479
CV_ERROR( CV_StsUnmatchedSizes,
480
"Response array must contain as many elements as the total number of samples" );
481
482
r_type = CV_MAT_TYPE(responses->type);
483
if( r_type != CV_32FC1 && r_type != CV_32SC1 )
484
CV_ERROR( CV_StsUnsupportedFormat, "Unsupported response type" );
485
486
r_step = responses->rows == 1 ? 1 : responses->step / CV_ELEM_SIZE(responses->type);
487
488
if( sample_idx )
489
{
490
if( !CV_IS_MAT(sample_idx) || CV_MAT_TYPE(sample_idx->type) != CV_32SC1 ||
491
(sample_idx->rows != 1 && sample_idx->cols != 1) || !CV_IS_MAT_CONT(sample_idx->type) )
492
CV_ERROR( CV_StsBadArg, "sample index array should be continuous 1-dimensional integer vector" );
493
if( sample_idx->rows + sample_idx->cols - 1 > sample_count )
494
CV_ERROR( CV_StsBadSize, "sample index array is too large" );
495
map = sample_idx->data.i;
496
sample_count = sample_idx->rows + sample_idx->cols - 1;
497
}
498
499
CV_CALL( out_responses = cvCreateMat( 1, sample_count, CV_32SC1 ));
500
501
if( !out_response_map )
502
CV_ERROR( CV_StsNullPtr, "out_response_map pointer is NULL" );
503
504
CV_CALL( response_ptr = (int**)cvAlloc( sample_count*sizeof(response_ptr[0])));
505
506
srci = responses->data.i;
507
srcfl = responses->data.fl;
508
dst = out_responses->data.i;
509
510
for( i = 0; i < sample_count; i++ )
511
{
512
int idx = map ? map[i] : i;
513
assert( (unsigned)idx < (unsigned)sample_all );
514
if( r_type == CV_32SC1 )
515
dst[i] = srci[idx*r_step];
516
else
517
{
518
float rf = srcfl[idx*r_step];
519
int ri = cvRound(rf);
520
if( ri != rf )
521
{
522
char buf[100];
523
sprintf( buf, "response #%d is not integral", idx );
524
CV_ERROR( CV_StsBadArg, buf );
525
}
526
dst[i] = ri;
527
}
528
response_ptr[i] = dst + i;
529
}
530
531
qsort( response_ptr, sample_count, sizeof(int*), icvCmpIntegersPtr );
532
533
// count the classes
534
for( i = 1; i < sample_count; i++ )
535
cls_count += *response_ptr[i] != *response_ptr[i-1];
536
537
if( cls_count < 2 )
538
CV_ERROR( CV_StsBadArg, "There is only a single class" );
539
540
CV_CALL( *out_response_map = cvCreateMat( 1, cls_count, CV_32SC1 ));
541
542
if( class_counts )
543
{
544
CV_CALL( *class_counts = cvCreateMat( 1, cls_count, CV_32SC1 ));
545
cls_counts = (*class_counts)->data.i;
546
}
547
548
// compact the class indices and build the map
549
prev_cls = ~*response_ptr[0];
550
cls_count = -1;
551
cls_map = (*out_response_map)->data.i;
552
553
for( i = 0, prev_i = -1; i < sample_count; i++ )
554
{
555
int cur_cls = *response_ptr[i];
556
if( cur_cls != prev_cls )
557
{
558
if( cls_counts && cls_count >= 0 )
559
cls_counts[cls_count] = i - prev_i;
560
cls_map[++cls_count] = prev_cls = cur_cls;
561
prev_i = i;
562
}
563
*response_ptr[i] = cls_count;
564
}
565
566
if( cls_counts )
567
cls_counts[cls_count] = i - prev_i;
568
569
__END__;
570
571
cvFree( &response_ptr );
572
573
return out_responses;
574
}
575
576
577
const float**
578
cvGetTrainSamples( const CvMat* train_data, int tflag,
579
const CvMat* var_idx, const CvMat* sample_idx,
580
int* _var_count, int* _sample_count,
581
bool always_copy_data )
582
{
583
float** samples = 0;
584
585
CV_FUNCNAME( "cvGetTrainSamples" );
586
587
__BEGIN__;
588
589
int i, j, var_count, sample_count, s_step, v_step;
590
bool copy_data;
591
const float* data;
592
const int *s_idx, *v_idx;
593
594
if( !CV_IS_MAT(train_data) )
595
CV_ERROR( CV_StsBadArg, "Invalid or NULL training data matrix" );
596
597
var_count = var_idx ? var_idx->cols + var_idx->rows - 1 :
598
tflag == CV_ROW_SAMPLE ? train_data->cols : train_data->rows;
599
sample_count = sample_idx ? sample_idx->cols + sample_idx->rows - 1 :
600
tflag == CV_ROW_SAMPLE ? train_data->rows : train_data->cols;
601
602
if( _var_count )
603
*_var_count = var_count;
604
605
if( _sample_count )
606
*_sample_count = sample_count;
607
608
copy_data = tflag != CV_ROW_SAMPLE || var_idx || always_copy_data;
609
610
CV_CALL( samples = (float**)cvAlloc(sample_count*sizeof(samples[0]) +
611
(copy_data ? 1 : 0)*var_count*sample_count*sizeof(samples[0][0])) );
612
data = train_data->data.fl;
613
s_step = train_data->step / sizeof(samples[0][0]);
614
v_step = 1;
615
s_idx = sample_idx ? sample_idx->data.i : 0;
616
v_idx = var_idx ? var_idx->data.i : 0;
617
618
if( !copy_data )
619
{
620
for( i = 0; i < sample_count; i++ )
621
samples[i] = (float*)(data + (s_idx ? s_idx[i] : i)*s_step);
622
}
623
else
624
{
625
samples[0] = (float*)(samples + sample_count);
626
if( tflag != CV_ROW_SAMPLE )
627
CV_SWAP( s_step, v_step, i );
628
629
for( i = 0; i < sample_count; i++ )
630
{
631
float* dst = samples[i] = samples[0] + i*var_count;
632
const float* src = data + (s_idx ? s_idx[i] : i)*s_step;
633
634
if( !v_idx )
635
for( j = 0; j < var_count; j++ )
636
dst[j] = src[j*v_step];
637
else
638
for( j = 0; j < var_count; j++ )
639
dst[j] = src[v_idx[j]*v_step];
640
}
641
}
642
643
__END__;
644
645
return (const float**)samples;
646
}
647
648
649
void
650
cvCheckTrainData( const CvMat* train_data, int tflag,
651
const CvMat* missing_mask,
652
int* var_all, int* sample_all )
653
{
654
CV_FUNCNAME( "cvCheckTrainData" );
655
656
if( var_all )
657
*var_all = 0;
658
659
if( sample_all )
660
*sample_all = 0;
661
662
__BEGIN__;
663
664
// check parameter types and sizes
665
if( !CV_IS_MAT(train_data) || CV_MAT_TYPE(train_data->type) != CV_32FC1 )
666
CV_ERROR( CV_StsBadArg, "train data must be floating-point matrix" );
667
668
if( missing_mask )
669
{
670
if( !CV_IS_MAT(missing_mask) || !CV_IS_MASK_ARR(missing_mask) ||
671
!CV_ARE_SIZES_EQ(train_data, missing_mask) )
672
CV_ERROR( CV_StsBadArg,
673
"missing value mask must be 8-bit matrix of the same size as training data" );
674
}
675
676
if( tflag != CV_ROW_SAMPLE && tflag != CV_COL_SAMPLE )
677
CV_ERROR( CV_StsBadArg,
678
"Unknown training data layout (must be CV_ROW_SAMPLE or CV_COL_SAMPLE)" );
679
680
if( var_all )
681
*var_all = tflag == CV_ROW_SAMPLE ? train_data->cols : train_data->rows;
682
683
if( sample_all )
684
*sample_all = tflag == CV_ROW_SAMPLE ? train_data->rows : train_data->cols;
685
686
__END__;
687
}
688
689
690
int
691
cvPrepareTrainData( const char* /*funcname*/,
692
const CvMat* train_data, int tflag,
693
const CvMat* responses, int response_type,
694
const CvMat* var_idx,
695
const CvMat* sample_idx,
696
bool always_copy_data,
697
const float*** out_train_samples,
698
int* _sample_count,
699
int* _var_count,
700
int* _var_all,
701
CvMat** out_responses,
702
CvMat** out_response_map,
703
CvMat** out_var_idx,
704
CvMat** out_sample_idx )
705
{
706
int ok = 0;
707
CvMat* _var_idx = 0;
708
CvMat* _sample_idx = 0;
709
CvMat* _responses = 0;
710
int sample_all = 0, sample_count = 0, var_all = 0, var_count = 0;
711
712
CV_FUNCNAME( "cvPrepareTrainData" );
713
714
// step 0. clear all the output pointers to ensure we do not try
715
// to call free() with uninitialized pointers
716
if( out_responses )
717
*out_responses = 0;
718
719
if( out_response_map )
720
*out_response_map = 0;
721
722
if( out_var_idx )
723
*out_var_idx = 0;
724
725
if( out_sample_idx )
726
*out_sample_idx = 0;
727
728
if( out_train_samples )
729
*out_train_samples = 0;
730
731
if( _sample_count )
732
*_sample_count = 0;
733
734
if( _var_count )
735
*_var_count = 0;
736
737
if( _var_all )
738
*_var_all = 0;
739
740
__BEGIN__;
741
742
if( !out_train_samples )
743
CV_ERROR( CV_StsBadArg, "output pointer to train samples is NULL" );
744
745
CV_CALL( cvCheckTrainData( train_data, tflag, 0, &var_all, &sample_all ));
746
747
if( sample_idx )
748
CV_CALL( _sample_idx = cvPreprocessIndexArray( sample_idx, sample_all ));
749
if( var_idx )
750
CV_CALL( _var_idx = cvPreprocessIndexArray( var_idx, var_all ));
751
752
if( responses )
753
{
754
if( !out_responses )
755
CV_ERROR( CV_StsNullPtr, "output response pointer is NULL" );
756
757
if( response_type == CV_VAR_NUMERICAL )
758
{
759
CV_CALL( _responses = cvPreprocessOrderedResponses( responses,
760
_sample_idx, sample_all ));
761
}
762
else
763
{
764
CV_CALL( _responses = cvPreprocessCategoricalResponses( responses,
765
_sample_idx, sample_all, out_response_map, 0 ));
766
}
767
}
768
769
CV_CALL( *out_train_samples =
770
cvGetTrainSamples( train_data, tflag, _var_idx, _sample_idx,
771
&var_count, &sample_count, always_copy_data ));
772
773
ok = 1;
774
775
__END__;
776
777
if( ok )
778
{
779
if( out_responses )
780
*out_responses = _responses, _responses = 0;
781
782
if( out_var_idx )
783
*out_var_idx = _var_idx, _var_idx = 0;
784
785
if( out_sample_idx )
786
*out_sample_idx = _sample_idx, _sample_idx = 0;
787
788
if( _sample_count )
789
*_sample_count = sample_count;
790
791
if( _var_count )
792
*_var_count = var_count;
793
794
if( _var_all )
795
*_var_all = var_all;
796
}
797
else
798
{
799
if( out_response_map )
800
cvReleaseMat( out_response_map );
801
cvFree( out_train_samples );
802
}
803
804
if( _responses != responses )
805
cvReleaseMat( &_responses );
806
cvReleaseMat( &_var_idx );
807
cvReleaseMat( &_sample_idx );
808
809
return ok;
810
}
811
812
813
typedef struct CvSampleResponsePair
814
{
815
const float* sample;
816
const uchar* mask;
817
int response;
818
int index;
819
}
820
CvSampleResponsePair;
821
822
823
static int
824
CV_CDECL icvCmpSampleResponsePairs( const void* a, const void* b )
825
{
826
int ra = ((const CvSampleResponsePair*)a)->response;
827
int rb = ((const CvSampleResponsePair*)b)->response;
828
int ia = ((const CvSampleResponsePair*)a)->index;
829
int ib = ((const CvSampleResponsePair*)b)->index;
830
831
return ra < rb ? -1 : ra > rb ? 1 : ia - ib;
832
//return (ra > rb ? -1 : 0)|(ra < rb);
833
}
834
835
836
void
837
cvSortSamplesByClasses( const float** samples, const CvMat* classes,
838
int* class_ranges, const uchar** mask )
839
{
840
CvSampleResponsePair* pairs = 0;
841
CV_FUNCNAME( "cvSortSamplesByClasses" );
842
843
__BEGIN__;
844
845
int i, k = 0, sample_count;
846
847
if( !samples || !classes || !class_ranges )
848
CV_ERROR( CV_StsNullPtr, "INTERNAL ERROR: some of the args are NULL pointers" );
849
850
if( classes->rows != 1 || CV_MAT_TYPE(classes->type) != CV_32SC1 )
851
CV_ERROR( CV_StsBadArg, "classes array must be a single row of integers" );
852
853
sample_count = classes->cols;
854
CV_CALL( pairs = (CvSampleResponsePair*)cvAlloc( (sample_count+1)*sizeof(pairs[0])));
855
856
for( i = 0; i < sample_count; i++ )
857
{
858
pairs[i].sample = samples[i];
859
pairs[i].mask = (mask) ? (mask[i]) : 0;
860
pairs[i].response = classes->data.i[i];
861
pairs[i].index = i;
862
assert( classes->data.i[i] >= 0 );
863
}
864
865
qsort( pairs, sample_count, sizeof(pairs[0]), icvCmpSampleResponsePairs );
866
pairs[sample_count].response = -1;
867
class_ranges[0] = 0;
868
869
for( i = 0; i < sample_count; i++ )
870
{
871
samples[i] = pairs[i].sample;
872
if (mask)
873
mask[i] = pairs[i].mask;
874
classes->data.i[i] = pairs[i].response;
875
876
if( pairs[i].response != pairs[i+1].response )
877
class_ranges[++k] = i+1;
878
}
879
880
__END__;
881
882
cvFree( &pairs );
883
}
884
885
886
void
887
cvPreparePredictData( const CvArr* _sample, int dims_all,
888
const CvMat* comp_idx, int class_count,
889
const CvMat* prob, float** _row_sample,
890
int as_sparse )
891
{
892
float* row_sample = 0;
893
int* inverse_comp_idx = 0;
894
895
CV_FUNCNAME( "cvPreparePredictData" );
896
897
__BEGIN__;
898
899
const CvMat* sample = (const CvMat*)_sample;
900
float* sample_data;
901
int sample_step;
902
int is_sparse = CV_IS_SPARSE_MAT(sample);
903
int d, sizes[CV_MAX_DIM];
904
int i, dims_selected;
905
int vec_size;
906
907
if( !is_sparse && !CV_IS_MAT(sample) )
908
CV_ERROR( !sample ? CV_StsNullPtr : CV_StsBadArg, "The sample is not a valid vector" );
909
910
if( cvGetElemType( sample ) != CV_32FC1 )
911
CV_ERROR( CV_StsUnsupportedFormat, "Input sample must have 32fC1 type" );
912
913
CV_CALL( d = cvGetDims( sample, sizes ));
914
915
if( !((is_sparse && d == 1) || (!is_sparse && d == 2 && (sample->rows == 1 || sample->cols == 1))) )
916
CV_ERROR( CV_StsBadSize, "Input sample must be 1-dimensional vector" );
917
918
if( d == 1 )
919
sizes[1] = 1;
920
921
if( sizes[0] + sizes[1] - 1 != dims_all )
922
CV_ERROR( CV_StsUnmatchedSizes,
923
"The sample size is different from what has been used for training" );
924
925
if( !_row_sample )
926
CV_ERROR( CV_StsNullPtr, "INTERNAL ERROR: The row_sample pointer is NULL" );
927
928
if( comp_idx && (!CV_IS_MAT(comp_idx) || comp_idx->rows != 1 ||
929
CV_MAT_TYPE(comp_idx->type) != CV_32SC1) )
930
CV_ERROR( CV_StsBadArg, "INTERNAL ERROR: invalid comp_idx" );
931
932
dims_selected = comp_idx ? comp_idx->cols : dims_all;
933
934
if( prob )
935
{
936
if( !CV_IS_MAT(prob) )
937
CV_ERROR( CV_StsBadArg, "The output matrix of probabilities is invalid" );
938
939
if( (prob->rows != 1 && prob->cols != 1) ||
940
(CV_MAT_TYPE(prob->type) != CV_32FC1 &&
941
CV_MAT_TYPE(prob->type) != CV_64FC1) )
942
CV_ERROR( CV_StsBadSize,
943
"The matrix of probabilities must be 1-dimensional vector of 32fC1 type" );
944
945
if( prob->rows + prob->cols - 1 != class_count )
946
CV_ERROR( CV_StsUnmatchedSizes,
947
"The vector of probabilities must contain as many elements as "
948
"the number of classes in the training set" );
949
}
950
951
vec_size = !as_sparse ? dims_selected*sizeof(row_sample[0]) :
952
(dims_selected + 1)*sizeof(CvSparseVecElem32f);
953
954
if( CV_IS_MAT(sample) )
955
{
956
sample_data = sample->data.fl;
957
sample_step = CV_IS_MAT_CONT(sample->type) ? 1 : sample->step/sizeof(row_sample[0]);
958
959
if( !comp_idx && CV_IS_MAT_CONT(sample->type) && !as_sparse )
960
*_row_sample = sample_data;
961
else
962
{
963
CV_CALL( row_sample = (float*)cvAlloc( vec_size ));
964
965
if( !comp_idx )
966
for( i = 0; i < dims_selected; i++ )
967
row_sample[i] = sample_data[sample_step*i];
968
else
969
{
970
int* comp = comp_idx->data.i;
971
for( i = 0; i < dims_selected; i++ )
972
row_sample[i] = sample_data[sample_step*comp[i]];
973
}
974
975
*_row_sample = row_sample;
976
}
977
978
if( as_sparse )
979
{
980
const float* src = (const float*)row_sample;
981
CvSparseVecElem32f* dst = (CvSparseVecElem32f*)row_sample;
982
983
dst[dims_selected].idx = -1;
984
for( i = dims_selected - 1; i >= 0; i-- )
985
{
986
dst[i].idx = i;
987
dst[i].val = src[i];
988
}
989
}
990
}
991
else
992
{
993
CvSparseNode* node;
994
CvSparseMatIterator mat_iterator;
995
const CvSparseMat* sparse = (const CvSparseMat*)sample;
996
assert( is_sparse );
997
998
node = cvInitSparseMatIterator( sparse, &mat_iterator );
999
CV_CALL( row_sample = (float*)cvAlloc( vec_size ));
1000
1001
if( comp_idx )
1002
{
1003
CV_CALL( inverse_comp_idx = (int*)cvAlloc( dims_all*sizeof(int) ));
1004
memset( inverse_comp_idx, -1, dims_all*sizeof(int) );
1005
for( i = 0; i < dims_selected; i++ )
1006
inverse_comp_idx[comp_idx->data.i[i]] = i;
1007
}
1008
1009
if( !as_sparse )
1010
{
1011
memset( row_sample, 0, vec_size );
1012
1013
for( ; node != 0; node = cvGetNextSparseNode(&mat_iterator) )
1014
{
1015
int idx = *CV_NODE_IDX( sparse, node );
1016
if( inverse_comp_idx )
1017
{
1018
idx = inverse_comp_idx[idx];
1019
if( idx < 0 )
1020
continue;
1021
}
1022
row_sample[idx] = *(float*)CV_NODE_VAL( sparse, node );
1023
}
1024
}
1025
else
1026
{
1027
CvSparseVecElem32f* ptr = (CvSparseVecElem32f*)row_sample;
1028
1029
for( ; node != 0; node = cvGetNextSparseNode(&mat_iterator) )
1030
{
1031
int idx = *CV_NODE_IDX( sparse, node );
1032
if( inverse_comp_idx )
1033
{
1034
idx = inverse_comp_idx[idx];
1035
if( idx < 0 )
1036
continue;
1037
}
1038
ptr->idx = idx;
1039
ptr->val = *(float*)CV_NODE_VAL( sparse, node );
1040
ptr++;
1041
}
1042
1043
qsort( row_sample, ptr - (CvSparseVecElem32f*)row_sample,
1044
sizeof(ptr[0]), icvCmpSparseVecElems );
1045
ptr->idx = -1;
1046
}
1047
1048
*_row_sample = row_sample;
1049
}
1050
1051
__END__;
1052
1053
if( inverse_comp_idx )
1054
cvFree( &inverse_comp_idx );
1055
1056
if( cvGetErrStatus() < 0 && _row_sample )
1057
{
1058
cvFree( &row_sample );
1059
*_row_sample = 0;
1060
}
1061
}
1062
1063
1064
static void
1065
icvConvertDataToSparse( const uchar* src, int src_step, int src_type,
1066
uchar* dst, int dst_step, int dst_type,
1067
CvSize size, int* idx )
1068
{
1069
CV_FUNCNAME( "icvConvertDataToSparse" );
1070
1071
__BEGIN__;
1072
1073
int i, j;
1074
src_type = CV_MAT_TYPE(src_type);
1075
dst_type = CV_MAT_TYPE(dst_type);
1076
1077
if( CV_MAT_CN(src_type) != 1 || CV_MAT_CN(dst_type) != 1 )
1078
CV_ERROR( CV_StsUnsupportedFormat, "The function supports only single-channel arrays" );
1079
1080
if( src_step == 0 )
1081
src_step = CV_ELEM_SIZE(src_type);
1082
1083
if( dst_step == 0 )
1084
dst_step = CV_ELEM_SIZE(dst_type);
1085
1086
// if there is no "idx" and if both arrays are continuous,
1087
// do the whole processing (copying or conversion) in a single loop
1088
if( !idx && CV_ELEM_SIZE(src_type)*size.width == src_step &&
1089
CV_ELEM_SIZE(dst_type)*size.width == dst_step )
1090
{
1091
size.width *= size.height;
1092
size.height = 1;
1093
}
1094
1095
if( src_type == dst_type )
1096
{
1097
int full_width = CV_ELEM_SIZE(dst_type)*size.width;
1098
1099
if( full_width == sizeof(int) ) // another common case: copy int's or float's
1100
for( i = 0; i < size.height; i++, src += src_step )
1101
*(int*)(dst + dst_step*(idx ? idx[i] : i)) = *(int*)src;
1102
else
1103
for( i = 0; i < size.height; i++, src += src_step )
1104
memcpy( dst + dst_step*(idx ? idx[i] : i), src, full_width );
1105
}
1106
else if( src_type == CV_32SC1 && (dst_type == CV_32FC1 || dst_type == CV_64FC1) )
1107
for( i = 0; i < size.height; i++, src += src_step )
1108
{
1109
uchar* _dst = dst + dst_step*(idx ? idx[i] : i);
1110
if( dst_type == CV_32FC1 )
1111
for( j = 0; j < size.width; j++ )
1112
((float*)_dst)[j] = (float)((int*)src)[j];
1113
else
1114
for( j = 0; j < size.width; j++ )
1115
((double*)_dst)[j] = ((int*)src)[j];
1116
}
1117
else if( (src_type == CV_32FC1 || src_type == CV_64FC1) && dst_type == CV_32SC1 )
1118
for( i = 0; i < size.height; i++, src += src_step )
1119
{
1120
uchar* _dst = dst + dst_step*(idx ? idx[i] : i);
1121
if( src_type == CV_32FC1 )
1122
for( j = 0; j < size.width; j++ )
1123
((int*)_dst)[j] = cvRound(((float*)src)[j]);
1124
else
1125
for( j = 0; j < size.width; j++ )
1126
((int*)_dst)[j] = cvRound(((double*)src)[j]);
1127
}
1128
else if( (src_type == CV_32FC1 && dst_type == CV_64FC1) ||
1129
(src_type == CV_64FC1 && dst_type == CV_32FC1) )
1130
for( i = 0; i < size.height; i++, src += src_step )
1131
{
1132
uchar* _dst = dst + dst_step*(idx ? idx[i] : i);
1133
if( src_type == CV_32FC1 )
1134
for( j = 0; j < size.width; j++ )
1135
((double*)_dst)[j] = ((float*)src)[j];
1136
else
1137
for( j = 0; j < size.width; j++ )
1138
((float*)_dst)[j] = (float)((double*)src)[j];
1139
}
1140
else
1141
CV_ERROR( CV_StsUnsupportedFormat, "Unsupported combination of input and output vectors" );
1142
1143
__END__;
1144
}
1145
1146
1147
void
1148
cvWritebackLabels( const CvMat* labels, CvMat* dst_labels,
1149
const CvMat* centers, CvMat* dst_centers,
1150
const CvMat* probs, CvMat* dst_probs,
1151
const CvMat* sample_idx, int samples_all,
1152
const CvMat* comp_idx, int dims_all )
1153
{
1154
CV_FUNCNAME( "cvWritebackLabels" );
1155
1156
__BEGIN__;
1157
1158
int samples_selected = samples_all, dims_selected = dims_all;
1159
1160
if( dst_labels && !CV_IS_MAT(dst_labels) )
1161
CV_ERROR( CV_StsBadArg, "Array of output labels is not a valid matrix" );
1162
1163
if( dst_centers )
1164
if( !ICV_IS_MAT_OF_TYPE(dst_centers, CV_32FC1) &&
1165
!ICV_IS_MAT_OF_TYPE(dst_centers, CV_64FC1) )
1166
CV_ERROR( CV_StsBadArg, "Array of cluster centers is not a valid matrix" );
1167
1168
if( dst_probs && !CV_IS_MAT(dst_probs) )
1169
CV_ERROR( CV_StsBadArg, "Probability matrix is not valid" );
1170
1171
if( sample_idx )
1172
{
1173
CV_ASSERT( sample_idx->rows == 1 && CV_MAT_TYPE(sample_idx->type) == CV_32SC1 );
1174
samples_selected = sample_idx->cols;
1175
}
1176
1177
if( comp_idx )
1178
{
1179
CV_ASSERT( comp_idx->rows == 1 && CV_MAT_TYPE(comp_idx->type) == CV_32SC1 );
1180
dims_selected = comp_idx->cols;
1181
}
1182
1183
if( dst_labels && (!labels || labels->data.ptr != dst_labels->data.ptr) )
1184
{
1185
if( !labels )
1186
CV_ERROR( CV_StsNullPtr, "NULL labels" );
1187
1188
CV_ASSERT( labels->rows == 1 );
1189
1190
if( dst_labels->rows != 1 && dst_labels->cols != 1 )
1191
CV_ERROR( CV_StsBadSize, "Array of output labels should be 1d vector" );
1192
1193
if( dst_labels->rows + dst_labels->cols - 1 != samples_all )
1194
CV_ERROR( CV_StsUnmatchedSizes,
1195
"Size of vector of output labels is not equal to the total number of input samples" );
1196
1197
CV_ASSERT( labels->cols == samples_selected );
1198
1199
CV_CALL( icvConvertDataToSparse( labels->data.ptr, labels->step, labels->type,
1200
dst_labels->data.ptr, dst_labels->step, dst_labels->type,
1201
cvSize( 1, samples_selected ), sample_idx ? sample_idx->data.i : 0 ));
1202
}
1203
1204
if( dst_centers && (!centers || centers->data.ptr != dst_centers->data.ptr) )
1205
{
1206
int i;
1207
1208
if( !centers )
1209
CV_ERROR( CV_StsNullPtr, "NULL centers" );
1210
1211
if( centers->rows != dst_centers->rows )
1212
CV_ERROR( CV_StsUnmatchedSizes, "Invalid number of rows in matrix of output centers" );
1213
1214
if( dst_centers->cols != dims_all )
1215
CV_ERROR( CV_StsUnmatchedSizes,
1216
"Number of columns in matrix of output centers is "
1217
"not equal to the total number of components in the input samples" );
1218
1219
CV_ASSERT( centers->cols == dims_selected );
1220
1221
for( i = 0; i < centers->rows; i++ )
1222
CV_CALL( icvConvertDataToSparse( centers->data.ptr + i*centers->step, 0, centers->type,
1223
dst_centers->data.ptr + i*dst_centers->step, 0, dst_centers->type,
1224
cvSize( 1, dims_selected ), comp_idx ? comp_idx->data.i : 0 ));
1225
}
1226
1227
if( dst_probs && (!probs || probs->data.ptr != dst_probs->data.ptr) )
1228
{
1229
if( !probs )
1230
CV_ERROR( CV_StsNullPtr, "NULL probs" );
1231
1232
if( probs->cols != dst_probs->cols )
1233
CV_ERROR( CV_StsUnmatchedSizes, "Invalid number of columns in output probability matrix" );
1234
1235
if( dst_probs->rows != samples_all )
1236
CV_ERROR( CV_StsUnmatchedSizes,
1237
"Number of rows in output probability matrix is "
1238
"not equal to the total number of input samples" );
1239
1240
CV_ASSERT( probs->rows == samples_selected );
1241
1242
CV_CALL( icvConvertDataToSparse( probs->data.ptr, probs->step, probs->type,
1243
dst_probs->data.ptr, dst_probs->step, dst_probs->type,
1244
cvSize( probs->cols, samples_selected ),
1245
sample_idx ? sample_idx->data.i : 0 ));
1246
}
1247
1248
__END__;
1249
}
1250
1251
#if 0
1252
CV_IMPL void
1253
cvStatModelMultiPredict( const CvStatModel* stat_model,
1254
const CvArr* predict_input,
1255
int flags, CvMat* predict_output,
1256
CvMat* probs, const CvMat* sample_idx )
1257
{
1258
CvMemStorage* storage = 0;
1259
CvMat* sample_idx_buffer = 0;
1260
CvSparseMat** sparse_rows = 0;
1261
int samples_selected = 0;
1262
1263
CV_FUNCNAME( "cvStatModelMultiPredict" );
1264
1265
__BEGIN__;
1266
1267
int i;
1268
int predict_output_step = 1, sample_idx_step = 1;
1269
int type;
1270
int d, sizes[CV_MAX_DIM];
1271
int tflag = flags == CV_COL_SAMPLE;
1272
int samples_all, dims_all;
1273
int is_sparse = CV_IS_SPARSE_MAT(predict_input);
1274
CvMat predict_input_part;
1275
CvArr* sample = &predict_input_part;
1276
CvMat probs_part;
1277
CvMat* probs1 = probs ? &probs_part : 0;
1278
1279
if( !CV_IS_STAT_MODEL(stat_model) )
1280
CV_ERROR( !stat_model ? CV_StsNullPtr : CV_StsBadArg, "Invalid statistical model" );
1281
1282
if( !stat_model->predict )
1283
CV_ERROR( CV_StsNotImplemented, "There is no \"predict\" method" );
1284
1285
if( !predict_input || !predict_output )
1286
CV_ERROR( CV_StsNullPtr, "NULL input or output matrices" );
1287
1288
if( !is_sparse && !CV_IS_MAT(predict_input) )
1289
CV_ERROR( CV_StsBadArg, "predict_input should be a matrix or a sparse matrix" );
1290
1291
if( !CV_IS_MAT(predict_output) )
1292
CV_ERROR( CV_StsBadArg, "predict_output should be a matrix" );
1293
1294
type = cvGetElemType( predict_input );
1295
if( type != CV_32FC1 ||
1296
(CV_MAT_TYPE(predict_output->type) != CV_32FC1 &&
1297
CV_MAT_TYPE(predict_output->type) != CV_32SC1 ))
1298
CV_ERROR( CV_StsUnsupportedFormat, "The input or output matrix has unsupported format" );
1299
1300
CV_CALL( d = cvGetDims( predict_input, sizes ));
1301
if( d > 2 )
1302
CV_ERROR( CV_StsBadSize, "The input matrix should be 1- or 2-dimensional" );
1303
1304
if( !tflag )
1305
{
1306
samples_all = samples_selected = sizes[0];
1307
dims_all = sizes[1];
1308
}
1309
else
1310
{
1311
samples_all = samples_selected = sizes[1];
1312
dims_all = sizes[0];
1313
}
1314
1315
if( sample_idx )
1316
{
1317
if( !CV_IS_MAT(sample_idx) )
1318
CV_ERROR( CV_StsBadArg, "Invalid sample_idx matrix" );
1319
1320
if( sample_idx->cols != 1 && sample_idx->rows != 1 )
1321
CV_ERROR( CV_StsBadSize, "sample_idx must be 1-dimensional matrix" );
1322
1323
samples_selected = sample_idx->rows + sample_idx->cols - 1;
1324
1325
if( CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )
1326
{
1327
if( samples_selected > samples_all )
1328
CV_ERROR( CV_StsBadSize, "sample_idx is too large vector" );
1329
}
1330
else if( samples_selected != samples_all )
1331
CV_ERROR( CV_StsUnmatchedSizes, "sample_idx has incorrect size" );
1332
1333
sample_idx_step = sample_idx->step ?
1334
sample_idx->step / CV_ELEM_SIZE(sample_idx->type) : 1;
1335
}
1336
1337
if( predict_output->rows != 1 && predict_output->cols != 1 )
1338
CV_ERROR( CV_StsBadSize, "predict_output should be a 1-dimensional matrix" );
1339
1340
if( predict_output->rows + predict_output->cols - 1 != samples_all )
1341
CV_ERROR( CV_StsUnmatchedSizes, "predict_output and predict_input have uncoordinated sizes" );
1342
1343
predict_output_step = predict_output->step ?
1344
predict_output->step / CV_ELEM_SIZE(predict_output->type) : 1;
1345
1346
if( probs )
1347
{
1348
if( !CV_IS_MAT(probs) )
1349
CV_ERROR( CV_StsBadArg, "Invalid matrix of probabilities" );
1350
1351
if( probs->rows != samples_all )
1352
CV_ERROR( CV_StsUnmatchedSizes,
1353
"matrix of probabilities must have as many rows as the total number of samples" );
1354
1355
if( CV_MAT_TYPE(probs->type) != CV_32FC1 )
1356
CV_ERROR( CV_StsUnsupportedFormat, "matrix of probabilities must have 32fC1 type" );
1357
}
1358
1359
if( is_sparse )
1360
{
1361
CvSparseNode* node;
1362
CvSparseMatIterator mat_iterator;
1363
CvSparseMat* sparse = (CvSparseMat*)predict_input;
1364
1365
if( sample_idx && CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )
1366
{
1367
CV_CALL( sample_idx_buffer = cvCreateMat( 1, samples_all, CV_8UC1 ));
1368
cvZero( sample_idx_buffer );
1369
for( i = 0; i < samples_selected; i++ )
1370
sample_idx_buffer->data.ptr[sample_idx->data.i[i*sample_idx_step]] = 1;
1371
samples_selected = samples_all;
1372
sample_idx = sample_idx_buffer;
1373
sample_idx_step = 1;
1374
}
1375
1376
CV_CALL( sparse_rows = (CvSparseMat**)cvAlloc( samples_selected*sizeof(sparse_rows[0])));
1377
for( i = 0; i < samples_selected; i++ )
1378
{
1379
if( sample_idx && sample_idx->data.ptr[i*sample_idx_step] == 0 )
1380
continue;
1381
CV_CALL( sparse_rows[i] = cvCreateSparseMat( 1, &dims_all, type ));
1382
if( !storage )
1383
storage = sparse_rows[i]->heap->storage;
1384
else
1385
{
1386
// hack: to decrease memory footprint, make all the sparse matrices
1387
// reside in the same storage
1388
int elem_size = sparse_rows[i]->heap->elem_size;
1389
cvReleaseMemStorage( &sparse_rows[i]->heap->storage );
1390
sparse_rows[i]->heap = cvCreateSet( 0, sizeof(CvSet), elem_size, storage );
1391
}
1392
}
1393
1394
// put each row (or column) of predict_input into separate sparse matrix.
1395
node = cvInitSparseMatIterator( sparse, &mat_iterator );
1396
for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
1397
{
1398
int* idx = CV_NODE_IDX( sparse, node );
1399
int idx0 = idx[tflag ^ 1];
1400
int idx1 = idx[tflag];
1401
1402
if( sample_idx && sample_idx->data.ptr[idx0*sample_idx_step] == 0 )
1403
continue;
1404
1405
assert( sparse_rows[idx0] != 0 );
1406
*(float*)cvPtrND( sparse, &idx1, 0, 1, 0 ) = *(float*)CV_NODE_VAL( sparse, node );
1407
}
1408
}
1409
1410
for( i = 0; i < samples_selected; i++ )
1411
{
1412
int idx = i;
1413
float response;
1414
1415
if( sample_idx )
1416
{
1417
if( CV_MAT_TYPE(sample_idx->type) == CV_32SC1 )
1418
{
1419
idx = sample_idx->data.i[i*sample_idx_step];
1420
if( (unsigned)idx >= (unsigned)samples_all )
1421
CV_ERROR( CV_StsOutOfRange, "Some of sample_idx elements are out of range" );
1422
}
1423
else if( CV_MAT_TYPE(sample_idx->type) == CV_8UC1 &&
1424
sample_idx->data.ptr[i*sample_idx_step] == 0 )
1425
continue;
1426
}
1427
1428
if( !is_sparse )
1429
{
1430
if( !tflag )
1431
cvGetRow( predict_input, &predict_input_part, idx );
1432
else
1433
{
1434
cvGetCol( predict_input, &predict_input_part, idx );
1435
}
1436
}
1437
else
1438
sample = sparse_rows[idx];
1439
1440
if( probs )
1441
cvGetRow( probs, probs1, idx );
1442
1443
CV_CALL( response = stat_model->predict( stat_model, (CvMat*)sample, probs1 ));
1444
1445
if( CV_MAT_TYPE(predict_output->type) == CV_32FC1 )
1446
predict_output->data.fl[idx*predict_output_step] = response;
1447
else
1448
{
1449
CV_ASSERT( cvRound(response) == response );
1450
predict_output->data.i[idx*predict_output_step] = cvRound(response);
1451
}
1452
}
1453
1454
__END__;
1455
1456
if( sparse_rows )
1457
{
1458
int i;
1459
for( i = 0; i < samples_selected; i++ )
1460
if( sparse_rows[i] )
1461
{
1462
sparse_rows[i]->heap->storage = 0;
1463
cvReleaseSparseMat( &sparse_rows[i] );
1464
}
1465
cvFree( &sparse_rows );
1466
}
1467
1468
cvReleaseMat( &sample_idx_buffer );
1469
cvReleaseMemStorage( &storage );
1470
}
1471
#endif
1472
1473
// By P. Yarykin - begin -
1474
1475
void cvCombineResponseMaps (CvMat* _responses,
1476
const CvMat* old_response_map,
1477
CvMat* new_response_map,
1478
CvMat** out_response_map)
1479
{
1480
int** old_data = NULL;
1481
int** new_data = NULL;
1482
1483
CV_FUNCNAME ("cvCombineResponseMaps");
1484
__BEGIN__
1485
1486
int i,j;
1487
int old_n, new_n, out_n;
1488
int samples, free_response;
1489
int* first;
1490
int* responses;
1491
int* out_data;
1492
1493
if( out_response_map )
1494
*out_response_map = 0;
1495
1496
// Check input data.
1497
if ((!ICV_IS_MAT_OF_TYPE (_responses, CV_32SC1)) ||
1498
(!ICV_IS_MAT_OF_TYPE (old_response_map, CV_32SC1)) ||
1499
(!ICV_IS_MAT_OF_TYPE (new_response_map, CV_32SC1)))
1500
{
1501
CV_ERROR (CV_StsBadArg, "Some of input arguments is not the CvMat")
1502
}
1503
1504
// Prepare sorted responses.
1505
first = new_response_map->data.i;
1506
new_n = new_response_map->cols;
1507
CV_CALL (new_data = (int**)cvAlloc (new_n * sizeof (new_data[0])));
1508
for (i = 0; i < new_n; i++)
1509
new_data[i] = first + i;
1510
qsort (new_data, new_n, sizeof(int*), icvCmpIntegersPtr);
1511
1512
first = old_response_map->data.i;
1513
old_n = old_response_map->cols;
1514
CV_CALL (old_data = (int**)cvAlloc (old_n * sizeof (old_data[0])));
1515
for (i = 0; i < old_n; i++)
1516
old_data[i] = first + i;
1517
qsort (old_data, old_n, sizeof(int*), icvCmpIntegersPtr);
1518
1519
// Count the number of different responses.
1520
for (i = 0, j = 0, out_n = 0; i < old_n && j < new_n; out_n++)
1521
{
1522
if (*old_data[i] == *new_data[j])
1523
{
1524
i++;
1525
j++;
1526
}
1527
else if (*old_data[i] < *new_data[j])
1528
i++;
1529
else
1530
j++;
1531
}
1532
out_n += old_n - i + new_n - j;
1533
1534
// Create and fill the result response maps.
1535
CV_CALL (*out_response_map = cvCreateMat (1, out_n, CV_32SC1));
1536
out_data = (*out_response_map)->data.i;
1537
memcpy (out_data, first, old_n * sizeof (int));
1538
1539
free_response = old_n;
1540
for (i = 0, j = 0; i < old_n && j < new_n; )
1541
{
1542
if (*old_data[i] == *new_data[j])
1543
{
1544
*new_data[j] = (int)(old_data[i] - first);
1545
i++;
1546
j++;
1547
}
1548
else if (*old_data[i] < *new_data[j])
1549
i++;
1550
else
1551
{
1552
out_data[free_response] = *new_data[j];
1553
*new_data[j] = free_response++;
1554
j++;
1555
}
1556
}
1557
for (; j < new_n; j++)
1558
{
1559
out_data[free_response] = *new_data[j];
1560
*new_data[j] = free_response++;
1561
}
1562
CV_ASSERT (free_response == out_n);
1563
1564
// Change <responses> according to out response map.
1565
samples = _responses->cols + _responses->rows - 1;
1566
responses = _responses->data.i;
1567
first = new_response_map->data.i;
1568
for (i = 0; i < samples; i++)
1569
{
1570
responses[i] = first[responses[i]];
1571
}
1572
1573
__END__
1574
1575
cvFree(&old_data);
1576
cvFree(&new_data);
1577
1578
}
1579
1580
1581
static int icvGetNumberOfCluster( double* prob_vector, int num_of_clusters, float r,
1582
float outlier_thresh, int normalize_probs )
1583
{
1584
int max_prob_loc = 0;
1585
1586
CV_FUNCNAME("icvGetNumberOfCluster");
1587
__BEGIN__;
1588
1589
double prob, maxprob, sum;
1590
int i;
1591
1592
CV_ASSERT(prob_vector);
1593
CV_ASSERT(num_of_clusters >= 0);
1594
1595
maxprob = prob_vector[0];
1596
max_prob_loc = 0;
1597
sum = maxprob;
1598
for( i = 1; i < num_of_clusters; i++ )
1599
{
1600
prob = prob_vector[i];
1601
sum += prob;
1602
if( prob > maxprob )
1603
{
1604
max_prob_loc = i;
1605
maxprob = prob;
1606
}
1607
}
1608
if( normalize_probs && fabs(sum - 1.) > FLT_EPSILON )
1609
{
1610
for( i = 0; i < num_of_clusters; i++ )
1611
prob_vector[i] /= sum;
1612
}
1613
if( fabs(r - 1.) > FLT_EPSILON && fabs(sum - 1.) < outlier_thresh )
1614
max_prob_loc = -1;
1615
1616
__END__;
1617
1618
return max_prob_loc;
1619
1620
} // End of icvGetNumberOfCluster
1621
1622
1623
void icvFindClusterLabels( const CvMat* probs, float outlier_thresh, float r,
1624
const CvMat* labels )
1625
{
1626
CvMat* counts = 0;
1627
1628
CV_FUNCNAME("icvFindClusterLabels");
1629
__BEGIN__;
1630
1631
int nclusters, nsamples;
1632
int i, j;
1633
double* probs_data;
1634
1635
CV_ASSERT( ICV_IS_MAT_OF_TYPE(probs, CV_64FC1) );
1636
CV_ASSERT( ICV_IS_MAT_OF_TYPE(labels, CV_32SC1) );
1637
1638
nclusters = probs->cols;
1639
nsamples = probs->rows;
1640
CV_ASSERT( nsamples == labels->cols );
1641
1642
CV_CALL( counts = cvCreateMat( 1, nclusters + 1, CV_32SC1 ) );
1643
CV_CALL( cvSetZero( counts ));
1644
for( i = 0; i < nsamples; i++ )
1645
{
1646
labels->data.i[i] = icvGetNumberOfCluster( probs->data.db + i*probs->cols,
1647
nclusters, r, outlier_thresh, 1 );
1648
counts->data.i[labels->data.i[i] + 1]++;
1649
}
1650
CV_ASSERT((int)cvSum(counts).val[0] == nsamples);
1651
// Filling empty clusters with the vector, that has the maximal probability
1652
for( j = 0; j < nclusters; j++ ) // outliers are ignored
1653
{
1654
int maxprob_loc = -1;
1655
double maxprob = 0;
1656
1657
if( counts->data.i[j+1] ) // j-th class is not empty
1658
continue;
1659
// look for the presentative, which is not lonely in it's cluster
1660
// and that has a maximal probability among all these vectors
1661
probs_data = probs->data.db;
1662
for( i = 0; i < nsamples; i++, probs_data++ )
1663
{
1664
int label = labels->data.i[i];
1665
double prob;
1666
if( counts->data.i[label+1] == 0 ||
1667
(counts->data.i[label+1] <= 1 && label != -1) )
1668
continue;
1669
prob = *probs_data;
1670
if( prob >= maxprob )
1671
{
1672
maxprob = prob;
1673
maxprob_loc = i;
1674
}
1675
}
1676
// maxprob_loc == 0 <=> number of vectors less then number of clusters
1677
CV_ASSERT( maxprob_loc >= 0 );
1678
counts->data.i[labels->data.i[maxprob_loc] + 1]--;
1679
labels->data.i[maxprob_loc] = j;
1680
counts->data.i[j + 1]++;
1681
}
1682
1683
__END__;
1684
1685
cvReleaseMat( &counts );
1686
} // End of icvFindClusterLabels
1687
1688
/* End of file */
1689
1690