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