Home | History | Annotate | Download | only in src
      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 
     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 )
     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( "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 
    112 void CvStatModel::write( CvFileStorage*, const char* )
    113 {
    114     OPENCV_ERROR( CV_StsNotImplemented, "CvStatModel::write", "" );
    115 }
    116 
    117 
    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 */
    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 */
    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. */
    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 */
    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 
    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, &centers_comp, i));
    309         CV_CALL(cvRandArr (&rng, &centers_comp, CV_RAND_UNI, cvScalarAll(minVal), cvScalarAll(maxVal)));
    310     }
    311 
    312     __END__;
    313 
    314     if( (cvGetErrStatus () < 0) || (centers != _centers) )
    315         cvReleaseMat (&centers);
    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 
    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 */
    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
    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
    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 
    452 static int icvCmpSparseVecElems( const void* a, const void* b )
    453 {
    454     return ((CvSparseVecElem32f*)a)->idx - ((CvSparseVecElem32f*)b)->idx;
    455 }
    456 
    457 
    458 CvMat*
    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*
    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*
    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*
    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**
    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
    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
    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
   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
   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
   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
   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
   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 
   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 
   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 
   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