Home | History | Annotate | Download | only in traincascade
      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 #include <ctype.h>
     43 
     44 #define MISS_VAL    FLT_MAX
     45 #define CV_VAR_MISS    0
     46 
     47 CvTrainTestSplit::CvTrainTestSplit()
     48 {
     49     train_sample_part_mode = CV_COUNT;
     50     train_sample_part.count = -1;
     51     mix = false;
     52 }
     53 
     54 CvTrainTestSplit::CvTrainTestSplit( int _train_sample_count, bool _mix )
     55 {
     56     train_sample_part_mode = CV_COUNT;
     57     train_sample_part.count = _train_sample_count;
     58     mix = _mix;
     59 }
     60 
     61 CvTrainTestSplit::CvTrainTestSplit( float _train_sample_portion, bool _mix )
     62 {
     63     train_sample_part_mode = CV_PORTION;
     64     train_sample_part.portion = _train_sample_portion;
     65     mix = _mix;
     66 }
     67 
     68 ////////////////
     69 
     70 CvMLData::CvMLData()
     71 {
     72     values = missing = var_types = var_idx_mask = response_out = var_idx_out = var_types_out = 0;
     73     train_sample_idx = test_sample_idx = 0;
     74     header_lines_number = 0;
     75     sample_idx = 0;
     76     response_idx = -1;
     77 
     78     train_sample_count = -1;
     79 
     80     delimiter = ',';
     81     miss_ch = '?';
     82     //flt_separator = '.';
     83 
     84     rng = &cv::theRNG();
     85 }
     86 
     87 CvMLData::~CvMLData()
     88 {
     89     clear();
     90 }
     91 
     92 void CvMLData::free_train_test_idx()
     93 {
     94     cvReleaseMat( &train_sample_idx );
     95     cvReleaseMat( &test_sample_idx );
     96     sample_idx = 0;
     97 }
     98 
     99 void CvMLData::clear()
    100 {
    101     class_map.clear();
    102 
    103     cvReleaseMat( &values );
    104     cvReleaseMat( &missing );
    105     cvReleaseMat( &var_types );
    106     cvReleaseMat( &var_idx_mask );
    107 
    108     cvReleaseMat( &response_out );
    109     cvReleaseMat( &var_idx_out );
    110     cvReleaseMat( &var_types_out );
    111 
    112     free_train_test_idx();
    113 
    114     total_class_count = 0;
    115 
    116     response_idx = -1;
    117 
    118     train_sample_count = -1;
    119 }
    120 
    121 
    122 void CvMLData::set_header_lines_number( int idx )
    123 {
    124     header_lines_number = std::max(0, idx);
    125 }
    126 
    127 int CvMLData::get_header_lines_number() const
    128 {
    129     return header_lines_number;
    130 }
    131 
    132 static char *fgets_chomp(char *str, int n, FILE *stream)
    133 {
    134     char *head = fgets(str, n, stream);
    135     if( head )
    136     {
    137         for(char *tail = head + strlen(head) - 1; tail >= head; --tail)
    138         {
    139             if( *tail != '\r'  && *tail != '\n' )
    140                 break;
    141             *tail = '\0';
    142         }
    143     }
    144     return head;
    145 }
    146 
    147 
    148 int CvMLData::read_csv(const char* filename)
    149 {
    150     const int M = 1000000;
    151     const char str_delimiter[3] = { ' ', delimiter, '\0' };
    152     FILE* file = 0;
    153     CvMemStorage* storage;
    154     CvSeq* seq;
    155     char *ptr;
    156     float* el_ptr;
    157     CvSeqReader reader;
    158     int cols_count = 0;
    159     uchar *var_types_ptr = 0;
    160 
    161     clear();
    162 
    163     file = fopen( filename, "rt" );
    164 
    165     if( !file )
    166         return -1;
    167 
    168     std::vector<char> _buf(M);
    169     char* buf = &_buf[0];
    170 
    171     // skip header lines
    172     for( int i = 0; i < header_lines_number; i++ )
    173     {
    174         if( fgets( buf, M, file ) == 0 )
    175         {
    176             fclose(file);
    177             return -1;
    178         }
    179     }
    180 
    181     // read the first data line and determine the number of variables
    182     if( !fgets_chomp( buf, M, file ))
    183     {
    184         fclose(file);
    185         return -1;
    186     }
    187 
    188     ptr = buf;
    189     while( *ptr == ' ' )
    190         ptr++;
    191     for( ; *ptr != '\0'; )
    192     {
    193         if(*ptr == delimiter || *ptr == ' ')
    194         {
    195             cols_count++;
    196             ptr++;
    197             while( *ptr == ' ' ) ptr++;
    198         }
    199         else
    200             ptr++;
    201     }
    202 
    203     cols_count++;
    204 
    205     if ( cols_count == 0)
    206     {
    207         fclose(file);
    208         return -1;
    209     }
    210 
    211     // create temporary memory storage to store the whole database
    212     el_ptr = new float[cols_count];
    213     storage = cvCreateMemStorage();
    214     seq = cvCreateSeq( 0, sizeof(*seq), cols_count*sizeof(float), storage );
    215 
    216     var_types = cvCreateMat( 1, cols_count, CV_8U );
    217     cvZero( var_types );
    218     var_types_ptr = var_types->data.ptr;
    219 
    220     for(;;)
    221     {
    222         char *token = NULL;
    223         int type;
    224         token = strtok(buf, str_delimiter);
    225         if (!token)
    226             break;
    227         for (int i = 0; i < cols_count-1; i++)
    228         {
    229             str_to_flt_elem( token, el_ptr[i], type);
    230             var_types_ptr[i] |= type;
    231             token = strtok(NULL, str_delimiter);
    232             if (!token)
    233             {
    234                 fclose(file);
    235                 delete [] el_ptr;
    236                 return -1;
    237             }
    238         }
    239         str_to_flt_elem( token, el_ptr[cols_count-1], type);
    240         var_types_ptr[cols_count-1] |= type;
    241         cvSeqPush( seq, el_ptr );
    242         if( !fgets_chomp( buf, M, file ) )
    243             break;
    244     }
    245     fclose(file);
    246 
    247     values = cvCreateMat( seq->total, cols_count, CV_32FC1 );
    248     missing = cvCreateMat( seq->total, cols_count, CV_8U );
    249     var_idx_mask = cvCreateMat( 1, values->cols, CV_8UC1 );
    250     cvSet( var_idx_mask, cvRealScalar(1) );
    251     train_sample_count = seq->total;
    252 
    253     cvStartReadSeq( seq, &reader );
    254     for(int i = 0; i < seq->total; i++ )
    255     {
    256         const float* sdata = (float*)reader.ptr;
    257         float* ddata = values->data.fl + cols_count*i;
    258         uchar* dm = missing->data.ptr + cols_count*i;
    259 
    260         for( int j = 0; j < cols_count; j++ )
    261         {
    262             ddata[j] = sdata[j];
    263             dm[j] = ( fabs( MISS_VAL - sdata[j] ) <= FLT_EPSILON );
    264         }
    265         CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
    266     }
    267 
    268     if ( cvNorm( missing, 0, CV_L1 ) <= FLT_EPSILON )
    269         cvReleaseMat( &missing );
    270 
    271     cvReleaseMemStorage( &storage );
    272     delete []el_ptr;
    273     return 0;
    274 }
    275 
    276 const CvMat* CvMLData::get_values() const
    277 {
    278     return values;
    279 }
    280 
    281 const CvMat* CvMLData::get_missing() const
    282 {
    283     CV_FUNCNAME( "CvMLData::get_missing" );
    284     __BEGIN__;
    285 
    286     if ( !values )
    287         CV_ERROR( CV_StsInternal, "data is empty" );
    288 
    289     __END__;
    290 
    291     return missing;
    292 }
    293 
    294 const std::map<cv::String, int>& CvMLData::get_class_labels_map() const
    295 {
    296     return class_map;
    297 }
    298 
    299 void CvMLData::str_to_flt_elem( const char* token, float& flt_elem, int& type)
    300 {
    301 
    302     char* stopstring = NULL;
    303     flt_elem = (float)strtod( token, &stopstring );
    304     assert( stopstring );
    305     type = CV_VAR_ORDERED;
    306     if ( *stopstring == miss_ch && strlen(stopstring) == 1 ) // missed value
    307     {
    308         flt_elem = MISS_VAL;
    309         type = CV_VAR_MISS;
    310     }
    311     else
    312     {
    313         if ( (*stopstring != 0) && (*stopstring != '\n') && (strcmp(stopstring, "\r\n") != 0) ) // class label
    314         {
    315             int idx = class_map[token];
    316             if ( idx == 0)
    317             {
    318                 total_class_count++;
    319                 idx = total_class_count;
    320                 class_map[token] = idx;
    321             }
    322             flt_elem = (float)idx;
    323             type = CV_VAR_CATEGORICAL;
    324         }
    325     }
    326 }
    327 
    328 void CvMLData::set_delimiter(char ch)
    329 {
    330     CV_FUNCNAME( "CvMLData::set_delimited" );
    331     __BEGIN__;
    332 
    333     if (ch == miss_ch /*|| ch == flt_separator*/)
    334         CV_ERROR(CV_StsBadArg, "delimited, miss_character and flt_separator must be different");
    335 
    336     delimiter = ch;
    337 
    338     __END__;
    339 }
    340 
    341 char CvMLData::get_delimiter() const
    342 {
    343     return delimiter;
    344 }
    345 
    346 void CvMLData::set_miss_ch(char ch)
    347 {
    348     CV_FUNCNAME( "CvMLData::set_miss_ch" );
    349     __BEGIN__;
    350 
    351     if (ch == delimiter/* || ch == flt_separator*/)
    352         CV_ERROR(CV_StsBadArg, "delimited, miss_character and flt_separator must be different");
    353 
    354     miss_ch = ch;
    355 
    356     __END__;
    357 }
    358 
    359 char CvMLData::get_miss_ch() const
    360 {
    361     return miss_ch;
    362 }
    363 
    364 void CvMLData::set_response_idx( int idx )
    365 {
    366     CV_FUNCNAME( "CvMLData::set_response_idx" );
    367     __BEGIN__;
    368 
    369     if ( !values )
    370         CV_ERROR( CV_StsInternal, "data is empty" );
    371 
    372     if ( idx >= values->cols)
    373         CV_ERROR( CV_StsBadArg, "idx value is not correct" );
    374 
    375     if ( response_idx >= 0 )
    376         chahge_var_idx( response_idx, true );
    377     if ( idx >= 0 )
    378         chahge_var_idx( idx, false );
    379     response_idx = idx;
    380 
    381     __END__;
    382 }
    383 
    384 int CvMLData::get_response_idx() const
    385 {
    386     CV_FUNCNAME( "CvMLData::get_response_idx" );
    387     __BEGIN__;
    388 
    389     if ( !values )
    390         CV_ERROR( CV_StsInternal, "data is empty" );
    391      __END__;
    392     return response_idx;
    393 }
    394 
    395 void CvMLData::change_var_type( int var_idx, int type )
    396 {
    397     CV_FUNCNAME( "CvMLData::change_var_type" );
    398     __BEGIN__;
    399 
    400     int var_count = 0;
    401 
    402     if ( !values )
    403         CV_ERROR( CV_StsInternal, "data is empty" );
    404 
    405      var_count = values->cols;
    406 
    407     if ( var_idx < 0 || var_idx >= var_count)
    408         CV_ERROR( CV_StsBadArg, "var_idx is not correct" );
    409 
    410     if ( type != CV_VAR_ORDERED && type != CV_VAR_CATEGORICAL)
    411          CV_ERROR( CV_StsBadArg, "type is not correct" );
    412 
    413     assert( var_types );
    414     if ( var_types->data.ptr[var_idx] == CV_VAR_CATEGORICAL && type == CV_VAR_ORDERED)
    415         CV_ERROR( CV_StsBadArg, "it`s impossible to assign CV_VAR_ORDERED type to categorical variable" );
    416     var_types->data.ptr[var_idx] = (uchar)type;
    417 
    418     __END__;
    419 
    420     return;
    421 }
    422 
    423 void CvMLData::set_var_types( const char* str )
    424 {
    425     CV_FUNCNAME( "CvMLData::set_var_types" );
    426     __BEGIN__;
    427 
    428     const char* ord = 0, *cat = 0;
    429     int var_count = 0, set_var_type_count = 0;
    430     if ( !values )
    431         CV_ERROR( CV_StsInternal, "data is empty" );
    432 
    433     var_count = values->cols;
    434 
    435     assert( var_types );
    436 
    437     ord = strstr( str, "ord" );
    438     cat = strstr( str, "cat" );
    439     if ( !ord && !cat )
    440         CV_ERROR( CV_StsBadArg, "types string is not correct" );
    441 
    442     if ( !ord && strlen(cat) == 3 ) // str == "cat"
    443     {
    444         cvSet( var_types, cvScalarAll(CV_VAR_CATEGORICAL) );
    445         return;
    446     }
    447 
    448     if ( !cat && strlen(ord) == 3 ) // str == "ord"
    449     {
    450         cvSet( var_types, cvScalarAll(CV_VAR_ORDERED) );
    451         return;
    452     }
    453 
    454     if ( ord ) // parse ord str
    455     {
    456         char* stopstring = NULL;
    457         if ( ord[3] != '[')
    458             CV_ERROR( CV_StsBadArg, "types string is not correct" );
    459 
    460         ord += 4; // pass "ord["
    461         do
    462         {
    463             int b1 = (int)strtod( ord, &stopstring );
    464             if ( *stopstring == 0 || (*stopstring != ',' && *stopstring != ']' && *stopstring != '-') )
    465                 CV_ERROR( CV_StsBadArg, "types string is not correct" );
    466             ord = stopstring + 1;
    467             if ( (stopstring[0] == ',') || (stopstring[0] == ']'))
    468             {
    469                 if ( var_types->data.ptr[b1] == CV_VAR_CATEGORICAL)
    470                     CV_ERROR( CV_StsBadArg, "it`s impossible to assign CV_VAR_ORDERED type to categorical variable" );
    471                 var_types->data.ptr[b1] = CV_VAR_ORDERED;
    472                 set_var_type_count++;
    473             }
    474             else
    475             {
    476                 if ( stopstring[0] == '-')
    477                 {
    478                     int b2 = (int)strtod( ord, &stopstring);
    479                     if ( (*stopstring == 0) || (*stopstring != ',' && *stopstring != ']') )
    480                         CV_ERROR( CV_StsBadArg, "types string is not correct" );
    481                     ord = stopstring + 1;
    482                     for (int i = b1; i <= b2; i++)
    483                     {
    484                         if ( var_types->data.ptr[i] == CV_VAR_CATEGORICAL)
    485                             CV_ERROR( CV_StsBadArg, "it`s impossible to assign CV_VAR_ORDERED type to categorical variable" );
    486                         var_types->data.ptr[i] = CV_VAR_ORDERED;
    487                     }
    488                     set_var_type_count += b2 - b1 + 1;
    489                 }
    490                 else
    491                     CV_ERROR( CV_StsBadArg, "types string is not correct" );
    492 
    493             }
    494         }
    495         while (*stopstring != ']');
    496 
    497         if ( stopstring[1] != '\0' && stopstring[1] != ',')
    498             CV_ERROR( CV_StsBadArg, "types string is not correct" );
    499     }
    500 
    501     if ( cat ) // parse cat str
    502     {
    503         char* stopstring = NULL;
    504         if ( cat[3] != '[')
    505             CV_ERROR( CV_StsBadArg, "types string is not correct" );
    506 
    507         cat += 4; // pass "cat["
    508         do
    509         {
    510             int b1 = (int)strtod( cat, &stopstring );
    511             if ( *stopstring == 0 || (*stopstring != ',' && *stopstring != ']' && *stopstring != '-') )
    512                 CV_ERROR( CV_StsBadArg, "types string is not correct" );
    513             cat = stopstring + 1;
    514             if ( (stopstring[0] == ',') || (stopstring[0] == ']'))
    515             {
    516                 var_types->data.ptr[b1] = CV_VAR_CATEGORICAL;
    517                 set_var_type_count++;
    518             }
    519             else
    520             {
    521                 if ( stopstring[0] == '-')
    522                 {
    523                     int b2 = (int)strtod( cat, &stopstring);
    524                     if ( (*stopstring == 0) || (*stopstring != ',' && *stopstring != ']') )
    525                         CV_ERROR( CV_StsBadArg, "types string is not correct" );
    526                     cat = stopstring + 1;
    527                     for (int i = b1; i <= b2; i++)
    528                         var_types->data.ptr[i] = CV_VAR_CATEGORICAL;
    529                     set_var_type_count += b2 - b1 + 1;
    530                 }
    531                 else
    532                     CV_ERROR( CV_StsBadArg, "types string is not correct" );
    533 
    534             }
    535         }
    536         while (*stopstring != ']');
    537 
    538         if ( stopstring[1] != '\0' && stopstring[1] != ',')
    539             CV_ERROR( CV_StsBadArg, "types string is not correct" );
    540     }
    541 
    542     if (set_var_type_count != var_count)
    543         CV_ERROR( CV_StsBadArg, "types string is not correct" );
    544 
    545      __END__;
    546 }
    547 
    548 const CvMat* CvMLData::get_var_types()
    549 {
    550     CV_FUNCNAME( "CvMLData::get_var_types" );
    551     __BEGIN__;
    552 
    553     uchar *var_types_out_ptr = 0;
    554     int avcount, vt_size;
    555     if ( !values )
    556         CV_ERROR( CV_StsInternal, "data is empty" );
    557 
    558     assert( var_idx_mask );
    559 
    560     avcount = cvFloor( cvNorm( var_idx_mask, 0, CV_L1 ) );
    561     vt_size = avcount + (response_idx >= 0);
    562 
    563     if ( avcount == values->cols || (avcount == values->cols-1 && response_idx == values->cols-1) )
    564         return var_types;
    565 
    566     if ( !var_types_out || ( var_types_out && var_types_out->cols != vt_size ) )
    567     {
    568         cvReleaseMat( &var_types_out );
    569         var_types_out = cvCreateMat( 1, vt_size, CV_8UC1 );
    570     }
    571 
    572     var_types_out_ptr = var_types_out->data.ptr;
    573     for( int i = 0; i < var_types->cols; i++)
    574     {
    575         if (i == response_idx || !var_idx_mask->data.ptr[i]) continue;
    576         *var_types_out_ptr = var_types->data.ptr[i];
    577         var_types_out_ptr++;
    578     }
    579     if ( response_idx >= 0 )
    580         *var_types_out_ptr = var_types->data.ptr[response_idx];
    581 
    582     __END__;
    583 
    584     return var_types_out;
    585 }
    586 
    587 int CvMLData::get_var_type( int var_idx ) const
    588 {
    589     return var_types->data.ptr[var_idx];
    590 }
    591 
    592 const CvMat* CvMLData::get_responses()
    593 {
    594     CV_FUNCNAME( "CvMLData::get_responses_ptr" );
    595     __BEGIN__;
    596 
    597     int var_count = 0;
    598 
    599     if ( !values )
    600         CV_ERROR( CV_StsInternal, "data is empty" );
    601     var_count = values->cols;
    602 
    603     if ( response_idx < 0 || response_idx >= var_count )
    604        return 0;
    605     if ( !response_out )
    606         response_out = cvCreateMatHeader( values->rows, 1, CV_32FC1 );
    607     else
    608         cvInitMatHeader( response_out, values->rows, 1, CV_32FC1);
    609     cvGetCol( values, response_out, response_idx );
    610 
    611     __END__;
    612 
    613     return response_out;
    614 }
    615 
    616 void CvMLData::set_train_test_split( const CvTrainTestSplit * spl)
    617 {
    618     CV_FUNCNAME( "CvMLData::set_division" );
    619     __BEGIN__;
    620 
    621     int sample_count = 0;
    622 
    623     if ( !values )
    624         CV_ERROR( CV_StsInternal, "data is empty" );
    625 
    626     sample_count = values->rows;
    627 
    628     float train_sample_portion;
    629 
    630     if (spl->train_sample_part_mode == CV_COUNT)
    631     {
    632         train_sample_count = spl->train_sample_part.count;
    633         if (train_sample_count > sample_count)
    634             CV_ERROR( CV_StsBadArg, "train samples count is not correct" );
    635         train_sample_count = train_sample_count<=0 ? sample_count : train_sample_count;
    636     }
    637     else // dtype.train_sample_part_mode == CV_PORTION
    638     {
    639         train_sample_portion = spl->train_sample_part.portion;
    640         if ( train_sample_portion > 1)
    641             CV_ERROR( CV_StsBadArg, "train samples count is not correct" );
    642         train_sample_portion = train_sample_portion <= FLT_EPSILON ||
    643             1 - train_sample_portion <= FLT_EPSILON ? 1 : train_sample_portion;
    644         train_sample_count = std::max(1, cvFloor( train_sample_portion * sample_count ));
    645     }
    646 
    647     if ( train_sample_count == sample_count )
    648     {
    649         free_train_test_idx();
    650         return;
    651     }
    652 
    653     if ( train_sample_idx && train_sample_idx->cols != train_sample_count )
    654         free_train_test_idx();
    655 
    656     if ( !sample_idx)
    657     {
    658         int test_sample_count = sample_count- train_sample_count;
    659         sample_idx = (int*)cvAlloc( sample_count * sizeof(sample_idx[0]) );
    660         for (int i = 0; i < sample_count; i++ )
    661             sample_idx[i] = i;
    662         train_sample_idx = cvCreateMatHeader( 1, train_sample_count, CV_32SC1 );
    663         *train_sample_idx = cvMat( 1, train_sample_count, CV_32SC1, &sample_idx[0] );
    664 
    665         CV_Assert(test_sample_count > 0);
    666         test_sample_idx = cvCreateMatHeader( 1, test_sample_count, CV_32SC1 );
    667         *test_sample_idx = cvMat( 1, test_sample_count, CV_32SC1, &sample_idx[train_sample_count] );
    668     }
    669 
    670     mix = spl->mix;
    671     if ( mix )
    672         mix_train_and_test_idx();
    673 
    674     __END__;
    675 }
    676 
    677 const CvMat* CvMLData::get_train_sample_idx() const
    678 {
    679     CV_FUNCNAME( "CvMLData::get_train_sample_idx" );
    680     __BEGIN__;
    681 
    682     if ( !values )
    683         CV_ERROR( CV_StsInternal, "data is empty" );
    684     __END__;
    685 
    686     return train_sample_idx;
    687 }
    688 
    689 const CvMat* CvMLData::get_test_sample_idx() const
    690 {
    691     CV_FUNCNAME( "CvMLData::get_test_sample_idx" );
    692     __BEGIN__;
    693 
    694     if ( !values )
    695         CV_ERROR( CV_StsInternal, "data is empty" );
    696     __END__;
    697 
    698     return test_sample_idx;
    699 }
    700 
    701 void CvMLData::mix_train_and_test_idx()
    702 {
    703     CV_FUNCNAME( "CvMLData::mix_train_and_test_idx" );
    704     __BEGIN__;
    705 
    706     if ( !values )
    707         CV_ERROR( CV_StsInternal, "data is empty" );
    708     __END__;
    709 
    710     if ( !sample_idx)
    711         return;
    712 
    713     if ( train_sample_count > 0 && train_sample_count < values->rows )
    714     {
    715         int n = values->rows;
    716         for (int i = 0; i < n; i++)
    717         {
    718             int a = (*rng)(n);
    719             int b = (*rng)(n);
    720             int t;
    721             CV_SWAP( sample_idx[a], sample_idx[b], t );
    722         }
    723     }
    724 }
    725 
    726 const CvMat* CvMLData::get_var_idx()
    727 {
    728      CV_FUNCNAME( "CvMLData::get_var_idx" );
    729     __BEGIN__;
    730 
    731     int avcount = 0;
    732 
    733     if ( !values )
    734         CV_ERROR( CV_StsInternal, "data is empty" );
    735 
    736     assert( var_idx_mask );
    737 
    738     avcount = cvFloor( cvNorm( var_idx_mask, 0, CV_L1 ) );
    739     int* vidx;
    740 
    741     if ( avcount == values->cols )
    742         return 0;
    743 
    744     if ( !var_idx_out || ( var_idx_out && var_idx_out->cols != avcount ) )
    745     {
    746         cvReleaseMat( &var_idx_out );
    747         var_idx_out = cvCreateMat( 1, avcount, CV_32SC1);
    748         if ( response_idx >=0 )
    749             var_idx_mask->data.ptr[response_idx] = 0;
    750     }
    751 
    752     vidx = var_idx_out->data.i;
    753 
    754     for(int i = 0; i < var_idx_mask->cols; i++)
    755         if ( var_idx_mask->data.ptr[i] )
    756         {
    757             *vidx = i;
    758             vidx++;
    759         }
    760 
    761     __END__;
    762 
    763     return var_idx_out;
    764 }
    765 
    766 void CvMLData::chahge_var_idx( int vi, bool state )
    767 {
    768     change_var_idx( vi, state );
    769 }
    770 
    771 void CvMLData::change_var_idx( int vi, bool state )
    772 {
    773      CV_FUNCNAME( "CvMLData::change_var_idx" );
    774     __BEGIN__;
    775 
    776     int var_count = 0;
    777 
    778     if ( !values )
    779         CV_ERROR( CV_StsInternal, "data is empty" );
    780 
    781     var_count = values->cols;
    782 
    783     if ( vi < 0 || vi >= var_count)
    784         CV_ERROR( CV_StsBadArg, "variable index is not correct" );
    785 
    786     assert( var_idx_mask );
    787     var_idx_mask->data.ptr[vi] = state;
    788 
    789     __END__;
    790 }
    791 
    792 /* End of file. */
    793