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 #if 0
     44 
     45 ML_IMPL int
     46 icvCmpIntegers (const void* a, const void* b) {return *(const int*)a - *(const int*)b;}
     47 
     48 /****************************************************************************************\
     49 *                    Cross-validation algorithms realizations                            *
     50 \****************************************************************************************/
     51 
     52 // Return pointer to trainIdx. Function DOES NOT FILL this matrix!
     53 ML_IMPL
     54 const CvMat* cvCrossValGetTrainIdxMatrix (const CvStatModel* estimateModel)
     55 {
     56     CvMat* result = NULL;
     57 
     58         CV_FUNCNAME ("cvCrossValGetTrainIdxMatrix");
     59         __BEGIN__
     60 
     61     if (!CV_IS_CROSSVAL(estimateModel))
     62     {
     63         CV_ERROR (CV_StsBadArg, "Pointer point to not CvCrossValidationModel");
     64     }
     65 
     66     result = ((CvCrossValidationModel*)estimateModel)->sampleIdxTrain;
     67 
     68         __END__
     69 
     70     return result;
     71 } // End of cvCrossValGetTrainIdxMatrix
     72 
     73 /****************************************************************************************/
     74 // Return pointer to checkIdx. Function DOES NOT FILL this matrix!
     75 ML_IMPL
     76 const CvMat* cvCrossValGetCheckIdxMatrix (const CvStatModel* estimateModel)
     77 {
     78     CvMat* result = NULL;
     79 
     80         CV_FUNCNAME ("cvCrossValGetCheckIdxMatrix");
     81         __BEGIN__
     82 
     83     if (!CV_IS_CROSSVAL (estimateModel))
     84     {
     85         CV_ERROR (CV_StsBadArg, "Pointer point to not CvCrossValidationModel");
     86     }
     87 
     88     result = ((CvCrossValidationModel*)estimateModel)->sampleIdxEval;
     89 
     90         __END__
     91 
     92     return result;
     93 } // End of cvCrossValGetCheckIdxMatrix
     94 
     95 /****************************************************************************************/
     96 // Create new Idx-matrix for next classifiers training and return code of result.
     97 //   Result is 0 if function can't make next step (error input or folds are finished),
     98 //   it is 1 if all was correct, and it is 2 if current fold wasn't' checked.
     99 ML_IMPL
    100 int cvCrossValNextStep (CvStatModel* estimateModel)
    101 {
    102     int result = 0;
    103 
    104         CV_FUNCNAME ("cvCrossValGetNextTrainIdx");
    105         __BEGIN__
    106 
    107     CvCrossValidationModel* crVal = (CvCrossValidationModel*) estimateModel;
    108     int k, fold;
    109 
    110     if (!CV_IS_CROSSVAL (estimateModel))
    111     {
    112         CV_ERROR (CV_StsBadArg, "Pointer point to not CvCrossValidationModel");
    113     }
    114 
    115     fold = ++crVal->current_fold;
    116 
    117     if (fold >= crVal->folds_all)
    118     {
    119         if (fold == crVal->folds_all)
    120             EXIT;
    121         else
    122         {
    123             CV_ERROR (CV_StsInternal, "All iterations has end long ago");
    124         }
    125     }
    126 
    127     k = crVal->folds[fold + 1] - crVal->folds[fold];
    128     crVal->sampleIdxTrain->data.i = crVal->sampleIdxAll + crVal->folds[fold + 1];
    129     crVal->sampleIdxTrain->cols = crVal->samples_all - k;
    130     crVal->sampleIdxEval->data.i = crVal->sampleIdxAll + crVal->folds[fold];
    131     crVal->sampleIdxEval->cols = k;
    132 
    133     if (crVal->is_checked)
    134     {
    135         crVal->is_checked = 0;
    136         result = 1;
    137     }
    138     else
    139     {
    140         result = 2;
    141     }
    142 
    143         __END__
    144 
    145     return result;
    146 }
    147 
    148 /****************************************************************************************/
    149 // Do checking part of loop  of cross-validations metod.
    150 ML_IMPL
    151 void cvCrossValCheckClassifier (CvStatModel*  estimateModel,
    152                           const CvStatModel*  model,
    153                           const CvMat*        trainData,
    154                                 int           sample_t_flag,
    155                           const CvMat*        trainClasses)
    156 {
    157         CV_FUNCNAME ("cvCrossValCheckClassifier ");
    158         __BEGIN__
    159 
    160     CvCrossValidationModel* crVal = (CvCrossValidationModel*) estimateModel;
    161     int  i, j, k;
    162     int* data;
    163     float* responses_fl;
    164     int    step;
    165     float* responses_result;
    166     int* responses_i;
    167     double te, te1;
    168     double sum_c, sum_p, sum_pp, sum_cp, sum_cc, sq_err;
    169 
    170 // Check input data to correct values.
    171     if (!CV_IS_CROSSVAL (estimateModel))
    172     {
    173         CV_ERROR (CV_StsBadArg,"First parameter point to not CvCrossValidationModel");
    174     }
    175     if (!CV_IS_STAT_MODEL (model))
    176     {
    177         CV_ERROR (CV_StsBadArg, "Second parameter point to not CvStatModel");
    178     }
    179     if (!CV_IS_MAT (trainData))
    180     {
    181         CV_ERROR (CV_StsBadArg, "Third parameter point to not CvMat");
    182     }
    183     if (!CV_IS_MAT (trainClasses))
    184     {
    185         CV_ERROR (CV_StsBadArg, "Fifth parameter point to not CvMat");
    186     }
    187     if (crVal->is_checked)
    188     {
    189         CV_ERROR (CV_StsInternal, "This iterations already was checked");
    190     }
    191 
    192 // Initialize.
    193     k = crVal->sampleIdxEval->cols;
    194     data = crVal->sampleIdxEval->data.i;
    195 
    196 // Eval tested feature vectors.
    197     CV_CALL (cvStatModelMultiPredict (model, trainData, sample_t_flag,
    198                                          crVal->predict_results, NULL, crVal->sampleIdxEval));
    199 // Count number if correct results.
    200     responses_result = crVal->predict_results->data.fl;
    201     if (crVal->is_regression)
    202     {
    203         sum_c = sum_p = sum_pp = sum_cp = sum_cc = sq_err = 0;
    204         if (CV_MAT_TYPE (trainClasses->type) == CV_32FC1)
    205         {
    206             responses_fl = trainClasses->data.fl;
    207             step = trainClasses->rows == 1 ? 1 : trainClasses->step / sizeof(float);
    208             for (i = 0; i < k; i++)
    209             {
    210                 te = responses_result[*data];
    211                 te1 = responses_fl[*data * step];
    212                 sum_c += te1;
    213                 sum_p += te;
    214                 sum_cc += te1 * te1;
    215                 sum_pp += te * te;
    216                 sum_cp += te1 * te;
    217                 te -= te1;
    218                 sq_err += te  * te;
    219 
    220                 data++;
    221             }
    222         }
    223         else
    224         {
    225             responses_i = trainClasses->data.i;
    226             step = trainClasses->rows == 1 ? 1 : trainClasses->step / sizeof(int);
    227             for (i = 0; i < k; i++)
    228             {
    229                 te = responses_result[*data];
    230                 te1 = responses_i[*data * step];
    231                 sum_c += te1;
    232                 sum_p += te;
    233                 sum_cc += te1 * te1;
    234                 sum_pp += te * te;
    235                 sum_cp += te1 * te;
    236                 te -= te1;
    237                 sq_err += te  * te;
    238 
    239                 data++;
    240             }
    241         }
    242     // Fixing new internal values of accuracy.
    243         crVal->sum_correct += sum_c;
    244         crVal->sum_predict += sum_p;
    245         crVal->sum_cc += sum_cc;
    246         crVal->sum_pp += sum_pp;
    247         crVal->sum_cp += sum_cp;
    248         crVal->sq_error += sq_err;
    249     }
    250     else
    251     {
    252         if (CV_MAT_TYPE (trainClasses->type) == CV_32FC1)
    253         {
    254             responses_fl = trainClasses->data.fl;
    255             step = trainClasses->rows == 1 ? 1 : trainClasses->step / sizeof(float);
    256             for (i = 0, j = 0; i < k; i++)
    257             {
    258                 if (cvRound (responses_result[*data]) == cvRound (responses_fl[*data * step]))
    259                     j++;
    260                 data++;
    261             }
    262         }
    263         else
    264         {
    265             responses_i = trainClasses->data.i;
    266             step = trainClasses->rows == 1 ? 1 : trainClasses->step / sizeof(int);
    267             for (i = 0, j = 0; i < k; i++)
    268             {
    269                 if (cvRound (responses_result[*data]) == responses_i[*data * step])
    270                     j++;
    271                 data++;
    272             }
    273         }
    274     // Fixing new internal values of accuracy.
    275         crVal->correct_results += j;
    276     }
    277 // Fixing that this fold already checked.
    278     crVal->all_results += k;
    279     crVal->is_checked = 1;
    280 
    281         __END__
    282 } // End of cvCrossValCheckClassifier
    283 
    284 /****************************************************************************************/
    285 // Return current accuracy.
    286 ML_IMPL
    287 float cvCrossValGetResult (const CvStatModel* estimateModel,
    288                                  float*       correlation)
    289 {
    290     float result = 0;
    291 
    292         CV_FUNCNAME ("cvCrossValGetResult");
    293         __BEGIN__
    294 
    295     double te, te1;
    296     CvCrossValidationModel* crVal = (CvCrossValidationModel*)estimateModel;
    297 
    298     if (!CV_IS_CROSSVAL (estimateModel))
    299     {
    300         CV_ERROR (CV_StsBadArg, "Pointer point to not CvCrossValidationModel");
    301     }
    302 
    303     if (crVal->all_results)
    304     {
    305         if (crVal->is_regression)
    306         {
    307             result = ((float)crVal->sq_error) / crVal->all_results;
    308             if (correlation)
    309             {
    310                 te = crVal->all_results * crVal->sum_cp -
    311                                              crVal->sum_correct * crVal->sum_predict;
    312                 te *= te;
    313                 te1 = (crVal->all_results * crVal->sum_cc -
    314                                     crVal->sum_correct * crVal->sum_correct) *
    315                            (crVal->all_results * crVal->sum_pp -
    316                                     crVal->sum_predict * crVal->sum_predict);
    317                 *correlation = (float)(te / te1);
    318 
    319             }
    320         }
    321         else
    322         {
    323             result = ((float)crVal->correct_results) / crVal->all_results;
    324         }
    325     }
    326 
    327         __END__
    328 
    329     return result;
    330 }
    331 
    332 /****************************************************************************************/
    333 // Reset cross-validation EstimateModel to state the same as it was immidiatly after
    334 //   its creating.
    335 ML_IMPL
    336 void cvCrossValReset (CvStatModel* estimateModel)
    337 {
    338         CV_FUNCNAME ("cvCrossValReset");
    339         __BEGIN__
    340 
    341     CvCrossValidationModel* crVal = (CvCrossValidationModel*)estimateModel;
    342 
    343     if (!CV_IS_CROSSVAL (estimateModel))
    344     {
    345         CV_ERROR (CV_StsBadArg, "Pointer point to not CvCrossValidationModel");
    346     }
    347 
    348     crVal->current_fold = -1;
    349     crVal->is_checked = 1;
    350     crVal->all_results = 0;
    351     crVal->correct_results = 0;
    352     crVal->sq_error = 0;
    353     crVal->sum_correct = 0;
    354     crVal->sum_predict = 0;
    355     crVal->sum_cc = 0;
    356     crVal->sum_pp = 0;
    357     crVal->sum_cp = 0;
    358 
    359         __END__
    360 }
    361 
    362 /****************************************************************************************/
    363 // This function is standart CvStatModel field to release cross-validation EstimateModel.
    364 ML_IMPL
    365 void cvReleaseCrossValidationModel (CvStatModel** model)
    366 {
    367     CvCrossValidationModel* pModel;
    368 
    369         CV_FUNCNAME ("cvReleaseCrossValidationModel");
    370         __BEGIN__
    371 
    372     if (!model)
    373     {
    374         CV_ERROR (CV_StsNullPtr, "");
    375     }
    376 
    377     pModel = (CvCrossValidationModel*)*model;
    378     if (!pModel)
    379     {
    380         return;
    381     }
    382     if (!CV_IS_CROSSVAL (pModel))
    383     {
    384         CV_ERROR (CV_StsBadArg, "");
    385     }
    386 
    387     cvFree (&pModel->sampleIdxAll);
    388     cvFree (&pModel->folds);
    389     cvReleaseMat (&pModel->sampleIdxEval);
    390     cvReleaseMat (&pModel->sampleIdxTrain);
    391     cvReleaseMat (&pModel->predict_results);
    392 
    393     cvFree (model);
    394 
    395         __END__
    396 } // End of cvReleaseCrossValidationModel.
    397 
    398 /****************************************************************************************/
    399 // This function create cross-validation EstimateModel.
    400 ML_IMPL CvStatModel*
    401 cvCreateCrossValidationEstimateModel(
    402              int                samples_all,
    403        const CvStatModelParams* estimateParams,
    404        const CvMat*             sampleIdx)
    405 {
    406     CvStatModel*            model   = NULL;
    407     CvCrossValidationModel* crVal   = NULL;
    408 
    409         CV_FUNCNAME ("cvCreateCrossValidationEstimateModel");
    410         __BEGIN__
    411 
    412     int  k_fold = 10;
    413 
    414     int  i, j, k, s_len;
    415     int  samples_selected;
    416     CvRNG rng;
    417     CvRNG* prng;
    418     int* res_s_data;
    419     int* te_s_data;
    420     int* folds;
    421 
    422     rng = cvRNG(cvGetTickCount());
    423     cvRandInt (&rng); cvRandInt (&rng); cvRandInt (&rng); cvRandInt (&rng);
    424 // Check input parameters.
    425     if (estimateParams)
    426         k_fold = ((CvCrossValidationParams*)estimateParams)->k_fold;
    427     if (!k_fold)
    428     {
    429         CV_ERROR (CV_StsBadArg, "Error in parameters of cross-validation (k_fold == 0)!");
    430     }
    431     if (samples_all <= 0)
    432     {
    433         CV_ERROR (CV_StsBadArg, "<samples_all> should be positive!");
    434     }
    435 
    436 // Alloc memory and fill standart StatModel's fields.
    437     CV_CALL (crVal = (CvCrossValidationModel*)cvCreateStatModel (
    438                             CV_STAT_MODEL_MAGIC_VAL | CV_CROSSVAL_MAGIC_VAL,
    439                             sizeof(CvCrossValidationModel),
    440                             cvReleaseCrossValidationModel,
    441                             NULL, NULL));
    442     crVal->current_fold    = -1;
    443     crVal->folds_all       = k_fold;
    444     if (estimateParams && ((CvCrossValidationParams*)estimateParams)->is_regression)
    445         crVal->is_regression = 1;
    446     else
    447         crVal->is_regression = 0;
    448     if (estimateParams && ((CvCrossValidationParams*)estimateParams)->rng)
    449         prng = ((CvCrossValidationParams*)estimateParams)->rng;
    450     else
    451         prng = &rng;
    452 
    453     // Check and preprocess sample indices.
    454     if (sampleIdx)
    455     {
    456         int s_step;
    457         int s_type = 0;
    458 
    459         if (!CV_IS_MAT (sampleIdx))
    460             CV_ERROR (CV_StsBadArg, "Invalid sampleIdx array");
    461 
    462         if (sampleIdx->rows != 1 && sampleIdx->cols != 1)
    463             CV_ERROR (CV_StsBadSize, "sampleIdx array must be 1-dimensional");
    464 
    465         s_len = sampleIdx->rows + sampleIdx->cols - 1;
    466         s_step = sampleIdx->rows == 1 ?
    467                                      1 : sampleIdx->step / CV_ELEM_SIZE(sampleIdx->type);
    468 
    469         s_type = CV_MAT_TYPE (sampleIdx->type);
    470 
    471         switch (s_type)
    472         {
    473         case CV_8UC1:
    474         case CV_8SC1:
    475             {
    476             uchar* s_data = sampleIdx->data.ptr;
    477 
    478             // sampleIdx is array of 1's and 0's -
    479             // i.e. it is a mask of the selected samples
    480             if( s_len != samples_all )
    481                 CV_ERROR (CV_StsUnmatchedSizes,
    482        "Sample mask should contain as many elements as the total number of samples");
    483 
    484             samples_selected = 0;
    485             for (i = 0; i < s_len; i++)
    486                 samples_selected += s_data[i * s_step] != 0;
    487 
    488             if (samples_selected == 0)
    489                 CV_ERROR (CV_StsOutOfRange, "No samples is selected!");
    490             }
    491             s_len = samples_selected;
    492             break;
    493         case CV_32SC1:
    494             if (s_len > samples_all)
    495                 CV_ERROR (CV_StsOutOfRange,
    496         "sampleIdx array may not contain more elements than the total number of samples");
    497             samples_selected = s_len;
    498             break;
    499         default:
    500             CV_ERROR (CV_StsUnsupportedFormat, "Unsupported sampleIdx array data type "
    501                                                "(it should be 8uC1, 8sC1 or 32sC1)");
    502         }
    503 
    504         // Alloc additional memory for internal Idx and fill it.
    505 /*!!*/  CV_CALL (res_s_data = crVal->sampleIdxAll =
    506                                                  (int*)cvAlloc (2 * s_len * sizeof(int)));
    507 
    508         if (s_type < CV_32SC1)
    509         {
    510             uchar* s_data = sampleIdx->data.ptr;
    511             for (i = 0; i < s_len; i++)
    512                 if (s_data[i * s_step])
    513                 {
    514                     *res_s_data++ = i;
    515                 }
    516             res_s_data = crVal->sampleIdxAll;
    517         }
    518         else
    519         {
    520             int* s_data = sampleIdx->data.i;
    521             int out_of_order = 0;
    522 
    523             for (i = 0; i < s_len; i++)
    524             {
    525                 res_s_data[i] = s_data[i * s_step];
    526                 if (i > 0 && res_s_data[i] < res_s_data[i - 1])
    527                     out_of_order = 1;
    528             }
    529 
    530             if (out_of_order)
    531                 qsort (res_s_data, s_len, sizeof(res_s_data[0]), icvCmpIntegers);
    532 
    533             if (res_s_data[0] < 0 ||
    534                 res_s_data[s_len - 1] >= samples_all)
    535                     CV_ERROR (CV_StsBadArg, "There are out-of-range sample indices");
    536             for (i = 1; i < s_len; i++)
    537                 if (res_s_data[i] <= res_s_data[i - 1])
    538                     CV_ERROR (CV_StsBadArg, "There are duplicated");
    539         }
    540     }
    541     else // if (sampleIdx)
    542     {
    543         // Alloc additional memory for internal Idx and fill it.
    544         s_len = samples_all;
    545         CV_CALL (res_s_data = crVal->sampleIdxAll = (int*)cvAlloc (2 * s_len * sizeof(int)));
    546         for (i = 0; i < s_len; i++)
    547         {
    548             *res_s_data++ = i;
    549         }
    550         res_s_data = crVal->sampleIdxAll;
    551     } // if (sampleIdx) ... else
    552 
    553 // Resort internal Idx.
    554     te_s_data = res_s_data + s_len;
    555     for (i = s_len; i > 1; i--)
    556     {
    557         j = cvRandInt (prng) % i;
    558         k = *(--te_s_data);
    559         *te_s_data = res_s_data[j];
    560         res_s_data[j] = k;
    561     }
    562 
    563 // Duplicate resorted internal Idx.
    564 // It will be used to simplify operation of getting trainIdx.
    565     te_s_data = res_s_data + s_len;
    566     for (i = 0; i < s_len; i++)
    567     {
    568         *te_s_data++ = *res_s_data++;
    569     }
    570 
    571 // Cut sampleIdxAll to parts.
    572     if (k_fold > 0)
    573     {
    574         if (k_fold > s_len)
    575         {
    576             CV_ERROR (CV_StsBadArg,
    577                         "Error in parameters of cross-validation ('k_fold' > #samples)!");
    578         }
    579         folds = crVal->folds = (int*) cvAlloc ((k_fold + 1) * sizeof (int));
    580         *folds++ = 0;
    581         for (i = 1; i < k_fold; i++)
    582         {
    583             *folds++ = cvRound (i * s_len * 1. / k_fold);
    584         }
    585         *folds = s_len;
    586         folds = crVal->folds;
    587 
    588         crVal->max_fold_size = (s_len - 1) / k_fold + 1;
    589     }
    590     else
    591     {
    592         k = -k_fold;
    593         crVal->max_fold_size = k;
    594         if (k >= s_len)
    595         {
    596             CV_ERROR (CV_StsBadArg,
    597                       "Error in parameters of cross-validation (-'k_fold' > #samples)!");
    598         }
    599         crVal->folds_all = k = (s_len - 1) / k + 1;
    600 
    601         folds = crVal->folds = (int*) cvAlloc ((k + 1) * sizeof (int));
    602         for (i = 0; i < k; i++)
    603         {
    604             *folds++ = -i * k_fold;
    605         }
    606         *folds = s_len;
    607         folds = crVal->folds;
    608     }
    609 
    610 // Prepare other internal fields to working.
    611     CV_CALL (crVal->predict_results = cvCreateMat (1, samples_all, CV_32FC1));
    612     CV_CALL (crVal->sampleIdxEval = cvCreateMatHeader (1, 1, CV_32SC1));
    613     CV_CALL (crVal->sampleIdxTrain = cvCreateMatHeader (1, 1, CV_32SC1));
    614     crVal->sampleIdxEval->cols = 0;
    615     crVal->sampleIdxTrain->cols = 0;
    616     crVal->samples_all = s_len;
    617     crVal->is_checked = 1;
    618 
    619     crVal->getTrainIdxMat = cvCrossValGetTrainIdxMatrix;
    620     crVal->getCheckIdxMat = cvCrossValGetCheckIdxMatrix;
    621     crVal->nextStep = cvCrossValNextStep;
    622     crVal->check = cvCrossValCheckClassifier;
    623     crVal->getResult = cvCrossValGetResult;
    624     crVal->reset = cvCrossValReset;
    625 
    626     model = (CvStatModel*)crVal;
    627 
    628         __END__
    629 
    630     if (!model)
    631     {
    632         cvReleaseCrossValidationModel ((CvStatModel**)&crVal);
    633     }
    634 
    635     return model;
    636 } // End of cvCreateCrossValidationEstimateModel
    637 
    638 
    639 /****************************************************************************************\
    640 *                Extended interface with backcalls for models                            *
    641 \****************************************************************************************/
    642 ML_IMPL float
    643 cvCrossValidation (const CvMat*            trueData,
    644                          int               tflag,
    645                    const CvMat*            trueClasses,
    646                          CvStatModel*     (*createClassifier) (const CvMat*,
    647                                                                      int,
    648                                                                const CvMat*,
    649                                                                const CvClassifierTrainParams*,
    650                                                                const CvMat*,
    651                                                                const CvMat*,
    652                                                                const CvMat*,
    653                                                                const CvMat*),
    654                    const CvClassifierTrainParams*    estimateParams,
    655                    const CvClassifierTrainParams*    trainParams,
    656                    const CvMat*            compIdx,
    657                    const CvMat*            sampleIdx,
    658                          CvStatModel**     pCrValModel,
    659                    const CvMat*            typeMask,
    660                    const CvMat*            missedMeasurementMask)
    661 {
    662     CvCrossValidationModel* crVal = NULL;
    663     float  result = 0;
    664     CvStatModel* pClassifier = NULL;
    665 
    666         CV_FUNCNAME ("cvCrossValidation");
    667         __BEGIN__
    668 
    669     const CvMat* trainDataIdx;
    670     int    samples_all;
    671 
    672 // checking input data
    673     if ((createClassifier) == NULL)
    674     {
    675         CV_ERROR (CV_StsNullPtr, "Null pointer to functiion which create classifier");
    676     }
    677     if (pCrValModel && *pCrValModel && !CV_IS_CROSSVAL(*pCrValModel))
    678     {
    679         CV_ERROR (CV_StsBadArg,
    680            "<pCrValModel> point to not cross-validation model");
    681     }
    682 
    683 // initialization
    684     if (pCrValModel && *pCrValModel)
    685     {
    686         crVal = (CvCrossValidationModel*)*pCrValModel;
    687         crVal->reset ((CvStatModel*)crVal);
    688     }
    689     else
    690     {
    691         samples_all = ((tflag) ? trueData->rows : trueData->cols);
    692         CV_CALL (crVal = (CvCrossValidationModel*)
    693            cvCreateCrossValidationEstimateModel (samples_all, estimateParams, sampleIdx));
    694     }
    695 
    696     CV_CALL (trainDataIdx = crVal->getTrainIdxMat ((CvStatModel*)crVal));
    697 
    698 // operation loop
    699     for (; crVal->nextStep((CvStatModel*)crVal) != 0; )
    700     {
    701         CV_CALL (pClassifier = createClassifier (trueData, tflag, trueClasses,
    702                     trainParams, compIdx, trainDataIdx, typeMask, missedMeasurementMask));
    703         CV_CALL (crVal->check ((CvStatModel*)crVal, pClassifier,
    704                                                            trueData, tflag, trueClasses));
    705 
    706         pClassifier->release (&pClassifier);
    707     }
    708 
    709 // Get result and fill output field.
    710     CV_CALL (result = crVal->getResult ((CvStatModel*)crVal, 0));
    711 
    712     if (pCrValModel && !*pCrValModel)
    713         *pCrValModel = (CvStatModel*)crVal;
    714 
    715         __END__
    716 
    717 // Free all memory that should be freed.
    718     if (pClassifier)
    719         pClassifier->release (&pClassifier);
    720     if (crVal && (!pCrValModel || !*pCrValModel))
    721         crVal->release ((CvStatModel**)&crVal);
    722 
    723     return result;
    724 } // End of cvCrossValidation
    725 
    726 #endif
    727 
    728 /* End of file */
    729