1 ////////////////////////////////////////////////////////////////////////////////////////// 2 /////////////////// tests for matrix operations and math functions /////////////////////// 3 ////////////////////////////////////////////////////////////////////////////////////////// 4 5 #include "test_precomp.hpp" 6 #include <float.h> 7 #include <math.h> 8 9 using namespace cv; 10 using namespace std; 11 12 /// !!! NOTE !!! These tests happily avoid overflow cases & out-of-range arguments 13 /// so that output arrays contain neigher Inf's nor Nan's. 14 /// Handling such cases would require special modification of check function 15 /// (validate_test_results) => TBD. 16 /// Also, need some logarithmic-scale generation of input data. Right now it is done (in some tests) 17 /// by generating min/max boundaries for random data in logarimithic scale, but 18 /// within the same test case all the input array elements are of the same order. 19 20 class Core_MathTest : public cvtest::ArrayTest 21 { 22 public: 23 typedef cvtest::ArrayTest Base; 24 Core_MathTest(); 25 protected: 26 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, 27 vector<vector<int> >& types); 28 double get_success_error_level( int /*test_case_idx*/, int i, int j ); 29 bool test_nd; 30 }; 31 32 33 Core_MathTest::Core_MathTest() 34 { 35 optional_mask = false; 36 37 test_array[INPUT].push_back(NULL); 38 test_array[OUTPUT].push_back(NULL); 39 test_array[REF_OUTPUT].push_back(NULL); 40 41 test_nd = false; 42 } 43 44 45 double Core_MathTest::get_success_error_level( int /*test_case_idx*/, int i, int j ) 46 { 47 return test_mat[i][j].depth() == CV_32F ? FLT_EPSILON*128 : DBL_EPSILON*1024; 48 } 49 50 51 void Core_MathTest::get_test_array_types_and_sizes( int test_case_idx, 52 vector<vector<Size> >& sizes, 53 vector<vector<int> >& types) 54 { 55 RNG& rng = ts->get_rng(); 56 int depth = cvtest::randInt(rng)%2 + CV_32F; 57 int cn = cvtest::randInt(rng) % 4 + 1, type = CV_MAKETYPE(depth, cn); 58 size_t i, j; 59 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 60 61 for( i = 0; i < test_array.size(); i++ ) 62 { 63 size_t count = test_array[i].size(); 64 for( j = 0; j < count; j++ ) 65 types[i][j] = type; 66 } 67 test_nd = cvtest::randInt(rng)%3 == 0; 68 } 69 70 71 ////////// pow ///////////// 72 73 class Core_PowTest : public Core_MathTest 74 { 75 public: 76 typedef Core_MathTest Base; 77 Core_PowTest(); 78 protected: 79 void get_test_array_types_and_sizes( int test_case_idx, 80 vector<vector<Size> >& sizes, 81 vector<vector<int> >& types ); 82 void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high ); 83 void run_func(); 84 void prepare_to_validation( int test_case_idx ); 85 double get_success_error_level( int test_case_idx, int i, int j ); 86 double power; 87 }; 88 89 90 Core_PowTest::Core_PowTest() 91 { 92 power = 0; 93 } 94 95 96 void Core_PowTest::get_test_array_types_and_sizes( int test_case_idx, 97 vector<vector<Size> >& sizes, 98 vector<vector<int> >& types ) 99 { 100 RNG& rng = ts->get_rng(); 101 int depth = cvtest::randInt(rng) % (CV_64F+1); 102 int cn = cvtest::randInt(rng) % 4 + 1; 103 size_t i, j; 104 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 105 depth += depth == CV_8S; 106 107 if( depth < CV_32F || cvtest::randInt(rng)%8 == 0 ) 108 // integer power 109 power = (int)(cvtest::randInt(rng)%21 - 10); 110 else 111 { 112 i = cvtest::randInt(rng)%17; 113 power = i == 16 ? 1./3 : i == 15 ? 0.5 : i == 14 ? -0.5 : cvtest::randReal(rng)*10 - 5; 114 } 115 116 for( i = 0; i < test_array.size(); i++ ) 117 { 118 size_t count = test_array[i].size(); 119 int type = CV_MAKETYPE(depth, cn); 120 for( j = 0; j < count; j++ ) 121 types[i][j] = type; 122 } 123 test_nd = cvtest::randInt(rng)%3 == 0; 124 } 125 126 127 double Core_PowTest::get_success_error_level( int test_case_idx, int i, int j ) 128 { 129 int depth = test_mat[i][j].depth(); 130 if( depth < CV_32F ) 131 return power == cvRound(power) && power >= 0 ? 0 : 1; 132 else 133 return Base::get_success_error_level( test_case_idx, i, j ); 134 } 135 136 137 void Core_PowTest::get_minmax_bounds( int /*i*/, int /*j*/, int type, Scalar& low, Scalar& high ) 138 { 139 double l, u = cvtest::randInt(ts->get_rng())%1000 + 1; 140 if( power > 0 ) 141 { 142 double mval = cvtest::getMaxVal(type); 143 double u1 = pow(mval,1./power)*2; 144 u = MIN(u,u1); 145 } 146 147 l = power == cvRound(power) ? -u : FLT_EPSILON; 148 low = Scalar::all(l); 149 high = Scalar::all(u); 150 } 151 152 153 void Core_PowTest::run_func() 154 { 155 if(!test_nd) 156 { 157 if( fabs(power-1./3) <= DBL_EPSILON && test_mat[INPUT][0].depth() == CV_32F ) 158 { 159 Mat a = test_mat[INPUT][0], b = test_mat[OUTPUT][0]; 160 161 a = a.reshape(1); 162 b = b.reshape(1); 163 for( int i = 0; i < a.rows; i++ ) 164 { 165 b.at<float>(i,0) = (float)fabs(cvCbrt(a.at<float>(i,0))); 166 for( int j = 1; j < a.cols; j++ ) 167 b.at<float>(i,j) = (float)fabs(cv::cubeRoot(a.at<float>(i,j))); 168 } 169 } 170 else 171 cvPow( test_array[INPUT][0], test_array[OUTPUT][0], power ); 172 } 173 else 174 { 175 Mat& a = test_mat[INPUT][0]; 176 Mat& b = test_mat[OUTPUT][0]; 177 if(power == 0.5) 178 cv::sqrt(a, b); 179 else 180 cv::pow(a, power, b); 181 } 182 } 183 184 185 inline static int ipow( int a, int power ) 186 { 187 int b = 1; 188 while( power > 0 ) 189 { 190 if( power&1 ) 191 b *= a, power--; 192 else 193 a *= a, power >>= 1; 194 } 195 return b; 196 } 197 198 199 inline static double ipow( double a, int power ) 200 { 201 double b = 1.; 202 while( power > 0 ) 203 { 204 if( power&1 ) 205 b *= a, power--; 206 else 207 a *= a, power >>= 1; 208 } 209 return b; 210 } 211 212 213 void Core_PowTest::prepare_to_validation( int /*test_case_idx*/ ) 214 { 215 const Mat& a = test_mat[INPUT][0]; 216 Mat& b = test_mat[REF_OUTPUT][0]; 217 218 int depth = a.depth(); 219 int ncols = a.cols*a.channels(); 220 int ipower = cvRound(power), apower = abs(ipower); 221 int i, j; 222 223 for( i = 0; i < a.rows; i++ ) 224 { 225 const uchar* a_data = a.ptr(i); 226 uchar* b_data = b.ptr(i); 227 228 switch( depth ) 229 { 230 case CV_8U: 231 if( ipower < 0 ) 232 for( j = 0; j < ncols; j++ ) 233 { 234 int val = ((uchar*)a_data)[j]; 235 ((uchar*)b_data)[j] = (uchar)(val == 0 ? 255 : val == 1 ? 1 : 236 val == 2 && ipower == -1 ? 1 : 0); 237 } 238 else 239 for( j = 0; j < ncols; j++ ) 240 { 241 int val = ((uchar*)a_data)[j]; 242 val = ipow( val, ipower ); 243 ((uchar*)b_data)[j] = saturate_cast<uchar>(val); 244 } 245 break; 246 case CV_8S: 247 if( ipower < 0 ) 248 for( j = 0; j < ncols; j++ ) 249 { 250 int val = ((schar*)a_data)[j]; 251 ((schar*)b_data)[j] = (schar)(val == 0 ? 127 : val == 1 ? 1 : 252 val ==-1 ? 1-2*(ipower&1) : 253 val == 2 && ipower == -1 ? 1 : 0); 254 } 255 else 256 for( j = 0; j < ncols; j++ ) 257 { 258 int val = ((schar*)a_data)[j]; 259 val = ipow( val, ipower ); 260 ((schar*)b_data)[j] = saturate_cast<schar>(val); 261 } 262 break; 263 case CV_16U: 264 if( ipower < 0 ) 265 for( j = 0; j < ncols; j++ ) 266 { 267 int val = ((ushort*)a_data)[j]; 268 ((ushort*)b_data)[j] = (ushort)(val == 0 ? 65535 : val == 1 ? 1 : 269 val ==-1 ? 1-2*(ipower&1) : 270 val == 2 && ipower == -1 ? 1 : 0); 271 } 272 else 273 for( j = 0; j < ncols; j++ ) 274 { 275 int val = ((ushort*)a_data)[j]; 276 val = ipow( val, ipower ); 277 ((ushort*)b_data)[j] = saturate_cast<ushort>(val); 278 } 279 break; 280 case CV_16S: 281 if( ipower < 0 ) 282 for( j = 0; j < ncols; j++ ) 283 { 284 int val = ((short*)a_data)[j]; 285 ((short*)b_data)[j] = (short)(val == 0 ? 32767 : val == 1 ? 1 : 286 val ==-1 ? 1-2*(ipower&1) : 287 val == 2 && ipower == -1 ? 1 : 0); 288 } 289 else 290 for( j = 0; j < ncols; j++ ) 291 { 292 int val = ((short*)a_data)[j]; 293 val = ipow( val, ipower ); 294 ((short*)b_data)[j] = saturate_cast<short>(val); 295 } 296 break; 297 case CV_32S: 298 if( ipower < 0 ) 299 for( j = 0; j < ncols; j++ ) 300 { 301 int val = ((int*)a_data)[j]; 302 ((int*)b_data)[j] = val == 0 ? INT_MAX : val == 1 ? 1 : 303 val ==-1 ? 1-2*(ipower&1) : 304 val == 2 && ipower == -1 ? 1 : 0; 305 } 306 else 307 for( j = 0; j < ncols; j++ ) 308 { 309 int val = ((int*)a_data)[j]; 310 val = ipow( val, ipower ); 311 ((int*)b_data)[j] = val; 312 } 313 break; 314 case CV_32F: 315 if( power != ipower ) 316 for( j = 0; j < ncols; j++ ) 317 { 318 double val = ((float*)a_data)[j]; 319 val = pow( fabs(val), power ); 320 ((float*)b_data)[j] = (float)val; 321 } 322 else 323 for( j = 0; j < ncols; j++ ) 324 { 325 double val = ((float*)a_data)[j]; 326 if( ipower < 0 ) 327 val = 1./val; 328 val = ipow( val, apower ); 329 ((float*)b_data)[j] = (float)val; 330 } 331 break; 332 case CV_64F: 333 if( power != ipower ) 334 for( j = 0; j < ncols; j++ ) 335 { 336 double val = ((double*)a_data)[j]; 337 val = pow( fabs(val), power ); 338 ((double*)b_data)[j] = (double)val; 339 } 340 else 341 for( j = 0; j < ncols; j++ ) 342 { 343 double val = ((double*)a_data)[j]; 344 if( ipower < 0 ) 345 val = 1./val; 346 val = ipow( val, apower ); 347 ((double*)b_data)[j] = (double)val; 348 } 349 break; 350 } 351 } 352 } 353 354 ///////////////////////////////////////// matrix tests //////////////////////////////////////////// 355 356 class Core_MatrixTest : public cvtest::ArrayTest 357 { 358 public: 359 typedef cvtest::ArrayTest Base; 360 Core_MatrixTest( int in_count, int out_count, 361 bool allow_int, bool scalar_output, int max_cn ); 362 protected: 363 void get_test_array_types_and_sizes( int test_case_idx, 364 vector<vector<Size> >& sizes, 365 vector<vector<int> >& types ); 366 double get_success_error_level( int test_case_idx, int i, int j ); 367 bool allow_int; 368 bool scalar_output; 369 int max_cn; 370 }; 371 372 373 Core_MatrixTest::Core_MatrixTest( int in_count, int out_count, 374 bool _allow_int, bool _scalar_output, int _max_cn ) 375 : allow_int(_allow_int), scalar_output(_scalar_output), max_cn(_max_cn) 376 { 377 int i; 378 for( i = 0; i < in_count; i++ ) 379 test_array[INPUT].push_back(NULL); 380 381 for( i = 0; i < out_count; i++ ) 382 { 383 test_array[OUTPUT].push_back(NULL); 384 test_array[REF_OUTPUT].push_back(NULL); 385 } 386 387 element_wise_relative_error = false; 388 } 389 390 391 void Core_MatrixTest::get_test_array_types_and_sizes( int test_case_idx, 392 vector<vector<Size> >& sizes, 393 vector<vector<int> >& types ) 394 { 395 RNG& rng = ts->get_rng(); 396 int depth = cvtest::randInt(rng) % (allow_int ? CV_64F+1 : 2); 397 int cn = cvtest::randInt(rng) % max_cn + 1; 398 size_t i, j; 399 400 if( allow_int ) 401 depth += depth == CV_8S; 402 else 403 depth += CV_32F; 404 405 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 406 407 for( i = 0; i < test_array.size(); i++ ) 408 { 409 size_t count = test_array[i].size(); 410 int flag = (i == OUTPUT || i == REF_OUTPUT) && scalar_output; 411 int type = !flag ? CV_MAKETYPE(depth, cn) : CV_64FC1; 412 413 for( j = 0; j < count; j++ ) 414 { 415 types[i][j] = type; 416 if( flag ) 417 sizes[i][j] = Size( 4, 1 ); 418 } 419 } 420 } 421 422 423 double Core_MatrixTest::get_success_error_level( int test_case_idx, int i, int j ) 424 { 425 int input_depth = test_mat[INPUT][0].depth(); 426 double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ? 5e-5 : 5e-10; 427 double output_precision = Base::get_success_error_level( test_case_idx, i, j ); 428 return MAX(input_precision, output_precision); 429 } 430 431 432 ///////////////// Trace ///////////////////// 433 434 class Core_TraceTest : public Core_MatrixTest 435 { 436 public: 437 Core_TraceTest(); 438 protected: 439 void run_func(); 440 void prepare_to_validation( int test_case_idx ); 441 }; 442 443 444 Core_TraceTest::Core_TraceTest() : Core_MatrixTest( 1, 1, true, true, 4 ) 445 { 446 } 447 448 449 void Core_TraceTest::run_func() 450 { 451 test_mat[OUTPUT][0].at<Scalar>(0,0) = cvTrace(test_array[INPUT][0]); 452 } 453 454 455 void Core_TraceTest::prepare_to_validation( int ) 456 { 457 Mat& mat = test_mat[INPUT][0]; 458 int count = MIN( mat.rows, mat.cols ); 459 Mat diag(count, 1, mat.type(), mat.ptr(), mat.step + mat.elemSize()); 460 Scalar r = cvtest::mean(diag); 461 r *= (double)count; 462 463 test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = r; 464 } 465 466 467 ///////// dotproduct ////////// 468 469 class Core_DotProductTest : public Core_MatrixTest 470 { 471 public: 472 Core_DotProductTest(); 473 protected: 474 void run_func(); 475 void prepare_to_validation( int test_case_idx ); 476 }; 477 478 479 Core_DotProductTest::Core_DotProductTest() : Core_MatrixTest( 2, 1, true, true, 4 ) 480 { 481 } 482 483 484 void Core_DotProductTest::run_func() 485 { 486 test_mat[OUTPUT][0].at<Scalar>(0,0) = Scalar(cvDotProduct( test_array[INPUT][0], test_array[INPUT][1] )); 487 } 488 489 490 void Core_DotProductTest::prepare_to_validation( int ) 491 { 492 test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = Scalar(cvtest::crossCorr( test_mat[INPUT][0], test_mat[INPUT][1] )); 493 } 494 495 496 ///////// crossproduct ////////// 497 498 class Core_CrossProductTest : public Core_MatrixTest 499 { 500 public: 501 Core_CrossProductTest(); 502 protected: 503 void get_test_array_types_and_sizes( int test_case_idx, 504 vector<vector<Size> >& sizes, 505 vector<vector<int> >& types ); 506 void run_func(); 507 void prepare_to_validation( int test_case_idx ); 508 }; 509 510 511 Core_CrossProductTest::Core_CrossProductTest() : Core_MatrixTest( 2, 1, false, false, 1 ) 512 { 513 } 514 515 516 void Core_CrossProductTest::get_test_array_types_and_sizes( int, 517 vector<vector<Size> >& sizes, 518 vector<vector<int> >& types ) 519 { 520 RNG& rng = ts->get_rng(); 521 int depth = cvtest::randInt(rng) % 2 + CV_32F; 522 int cn = cvtest::randInt(rng) & 1 ? 3 : 1, type = CV_MAKETYPE(depth, cn); 523 CvSize sz; 524 525 types[INPUT][0] = types[INPUT][1] = types[OUTPUT][0] = types[REF_OUTPUT][0] = type; 526 527 if( cn == 3 ) 528 sz = Size(1,1); 529 else if( cvtest::randInt(rng) & 1 ) 530 sz = Size(3,1); 531 else 532 sz = Size(1,3); 533 534 sizes[INPUT][0] = sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz; 535 } 536 537 538 void Core_CrossProductTest::run_func() 539 { 540 cvCrossProduct( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] ); 541 } 542 543 544 void Core_CrossProductTest::prepare_to_validation( int ) 545 { 546 CvScalar a(0), b(0), c(0); 547 548 if( test_mat[INPUT][0].rows > 1 ) 549 { 550 a.val[0] = cvGetReal2D( test_array[INPUT][0], 0, 0 ); 551 a.val[1] = cvGetReal2D( test_array[INPUT][0], 1, 0 ); 552 a.val[2] = cvGetReal2D( test_array[INPUT][0], 2, 0 ); 553 554 b.val[0] = cvGetReal2D( test_array[INPUT][1], 0, 0 ); 555 b.val[1] = cvGetReal2D( test_array[INPUT][1], 1, 0 ); 556 b.val[2] = cvGetReal2D( test_array[INPUT][1], 2, 0 ); 557 } 558 else if( test_mat[INPUT][0].cols > 1 ) 559 { 560 a.val[0] = cvGetReal1D( test_array[INPUT][0], 0 ); 561 a.val[1] = cvGetReal1D( test_array[INPUT][0], 1 ); 562 a.val[2] = cvGetReal1D( test_array[INPUT][0], 2 ); 563 564 b.val[0] = cvGetReal1D( test_array[INPUT][1], 0 ); 565 b.val[1] = cvGetReal1D( test_array[INPUT][1], 1 ); 566 b.val[2] = cvGetReal1D( test_array[INPUT][1], 2 ); 567 } 568 else 569 { 570 a = cvGet1D( test_array[INPUT][0], 0 ); 571 b = cvGet1D( test_array[INPUT][1], 0 ); 572 } 573 574 c.val[2] = a.val[0]*b.val[1] - a.val[1]*b.val[0]; 575 c.val[1] = -a.val[0]*b.val[2] + a.val[2]*b.val[0]; 576 c.val[0] = a.val[1]*b.val[2] - a.val[2]*b.val[1]; 577 578 if( test_mat[REF_OUTPUT][0].rows > 1 ) 579 { 580 cvSetReal2D( test_array[REF_OUTPUT][0], 0, 0, c.val[0] ); 581 cvSetReal2D( test_array[REF_OUTPUT][0], 1, 0, c.val[1] ); 582 cvSetReal2D( test_array[REF_OUTPUT][0], 2, 0, c.val[2] ); 583 } 584 else if( test_mat[REF_OUTPUT][0].cols > 1 ) 585 { 586 cvSetReal1D( test_array[REF_OUTPUT][0], 0, c.val[0] ); 587 cvSetReal1D( test_array[REF_OUTPUT][0], 1, c.val[1] ); 588 cvSetReal1D( test_array[REF_OUTPUT][0], 2, c.val[2] ); 589 } 590 else 591 { 592 cvSet1D( test_array[REF_OUTPUT][0], 0, c ); 593 } 594 } 595 596 597 ///////////////// gemm ///////////////////// 598 599 class Core_GEMMTest : public Core_MatrixTest 600 { 601 public: 602 typedef Core_MatrixTest Base; 603 Core_GEMMTest(); 604 protected: 605 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 606 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ); 607 int prepare_test_case( int test_case_idx ); 608 void run_func(); 609 void prepare_to_validation( int test_case_idx ); 610 int tabc_flag; 611 double alpha, beta; 612 }; 613 614 Core_GEMMTest::Core_GEMMTest() : Core_MatrixTest( 5, 1, false, false, 2 ) 615 { 616 test_case_count = 100; 617 max_log_array_size = 10; 618 tabc_flag = 0; 619 alpha = beta = 0; 620 } 621 622 623 void Core_GEMMTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 624 { 625 RNG& rng = ts->get_rng(); 626 Size sizeA; 627 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 628 sizeA = sizes[INPUT][0]; 629 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 630 sizes[INPUT][0] = sizeA; 631 sizes[INPUT][2] = sizes[INPUT][3] = Size(1,1); 632 types[INPUT][2] = types[INPUT][3] &= ~CV_MAT_CN_MASK; 633 634 tabc_flag = cvtest::randInt(rng) & 7; 635 636 switch( tabc_flag & (CV_GEMM_A_T|CV_GEMM_B_T) ) 637 { 638 case 0: 639 sizes[INPUT][1].height = sizes[INPUT][0].width; 640 sizes[OUTPUT][0].height = sizes[INPUT][0].height; 641 sizes[OUTPUT][0].width = sizes[INPUT][1].width; 642 break; 643 case CV_GEMM_B_T: 644 sizes[INPUT][1].width = sizes[INPUT][0].width; 645 sizes[OUTPUT][0].height = sizes[INPUT][0].height; 646 sizes[OUTPUT][0].width = sizes[INPUT][1].height; 647 break; 648 case CV_GEMM_A_T: 649 sizes[INPUT][1].height = sizes[INPUT][0].height; 650 sizes[OUTPUT][0].height = sizes[INPUT][0].width; 651 sizes[OUTPUT][0].width = sizes[INPUT][1].width; 652 break; 653 case CV_GEMM_A_T | CV_GEMM_B_T: 654 sizes[INPUT][1].width = sizes[INPUT][0].height; 655 sizes[OUTPUT][0].height = sizes[INPUT][0].width; 656 sizes[OUTPUT][0].width = sizes[INPUT][1].height; 657 break; 658 } 659 660 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0]; 661 662 if( cvtest::randInt(rng) & 1 ) 663 sizes[INPUT][4] = Size(0,0); 664 else if( !(tabc_flag & CV_GEMM_C_T) ) 665 sizes[INPUT][4] = sizes[OUTPUT][0]; 666 else 667 { 668 sizes[INPUT][4].width = sizes[OUTPUT][0].height; 669 sizes[INPUT][4].height = sizes[OUTPUT][0].width; 670 } 671 } 672 673 674 int Core_GEMMTest::prepare_test_case( int test_case_idx ) 675 { 676 int code = Base::prepare_test_case( test_case_idx ); 677 if( code > 0 ) 678 { 679 alpha = cvGetReal2D( test_array[INPUT][2], 0, 0 ); 680 beta = cvGetReal2D( test_array[INPUT][3], 0, 0 ); 681 } 682 return code; 683 } 684 685 686 void Core_GEMMTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ) 687 { 688 low = Scalar::all(-10.); 689 high = Scalar::all(10.); 690 } 691 692 693 void Core_GEMMTest::run_func() 694 { 695 cvGEMM( test_array[INPUT][0], test_array[INPUT][1], alpha, 696 test_array[INPUT][4], beta, test_array[OUTPUT][0], tabc_flag ); 697 } 698 699 700 void Core_GEMMTest::prepare_to_validation( int ) 701 { 702 cvtest::gemm( test_mat[INPUT][0], test_mat[INPUT][1], alpha, 703 test_array[INPUT][4] ? test_mat[INPUT][4] : Mat(), 704 beta, test_mat[REF_OUTPUT][0], tabc_flag ); 705 } 706 707 708 ///////////////// multransposed ///////////////////// 709 710 class Core_MulTransposedTest : public Core_MatrixTest 711 { 712 public: 713 Core_MulTransposedTest(); 714 protected: 715 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 716 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ); 717 void run_func(); 718 void prepare_to_validation( int test_case_idx ); 719 int order; 720 }; 721 722 723 Core_MulTransposedTest::Core_MulTransposedTest() : Core_MatrixTest( 2, 1, false, false, 1 ) 724 { 725 test_case_count = 100; 726 order = 0; 727 test_array[TEMP].push_back(NULL); 728 } 729 730 731 void Core_MulTransposedTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 732 { 733 RNG& rng = ts->get_rng(); 734 int bits = cvtest::randInt(rng); 735 int src_type = cvtest::randInt(rng) % 5; 736 int dst_type = cvtest::randInt(rng) % 2; 737 738 src_type = src_type == 0 ? CV_8U : src_type == 1 ? CV_16U : src_type == 2 ? CV_16S : 739 src_type == 3 ? CV_32F : CV_64F; 740 dst_type = dst_type == 0 ? CV_32F : CV_64F; 741 dst_type = MAX( dst_type, src_type ); 742 743 Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 744 745 if( bits & 1 ) 746 sizes[INPUT][1] = Size(0,0); 747 else 748 { 749 sizes[INPUT][1] = sizes[INPUT][0]; 750 if( bits & 2 ) 751 sizes[INPUT][1].height = 1; 752 if( bits & 4 ) 753 sizes[INPUT][1].width = 1; 754 } 755 756 sizes[TEMP][0] = sizes[INPUT][0]; 757 types[INPUT][0] = src_type; 758 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][1] = types[TEMP][0] = dst_type; 759 760 order = (bits & 8) != 0; 761 sizes[OUTPUT][0].width = sizes[OUTPUT][0].height = order == 0 ? 762 sizes[INPUT][0].height : sizes[INPUT][0].width; 763 sizes[REF_OUTPUT][0] = sizes[OUTPUT][0]; 764 } 765 766 767 void Core_MulTransposedTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ) 768 { 769 low = cvScalarAll(-10.); 770 high = cvScalarAll(10.); 771 } 772 773 774 void Core_MulTransposedTest::run_func() 775 { 776 cvMulTransposed( test_array[INPUT][0], test_array[OUTPUT][0], 777 order, test_array[INPUT][1] ); 778 } 779 780 781 void Core_MulTransposedTest::prepare_to_validation( int ) 782 { 783 const Mat& src = test_mat[INPUT][0]; 784 Mat delta = test_mat[INPUT][1]; 785 Mat& temp = test_mat[TEMP][0]; 786 if( !delta.empty() ) 787 { 788 if( delta.rows < src.rows || delta.cols < src.cols ) 789 { 790 cv::repeat( delta, src.rows/delta.rows, src.cols/delta.cols, temp); 791 delta = temp; 792 } 793 cvtest::add( src, 1, delta, -1, Scalar::all(0), temp, temp.type()); 794 } 795 else 796 src.convertTo(temp, temp.type()); 797 798 cvtest::gemm( temp, temp, 1., Mat(), 0, test_mat[REF_OUTPUT][0], order == 0 ? GEMM_2_T : GEMM_1_T ); 799 } 800 801 802 ///////////////// Transform ///////////////////// 803 804 class Core_TransformTest : public Core_MatrixTest 805 { 806 public: 807 typedef Core_MatrixTest Base; 808 Core_TransformTest(); 809 protected: 810 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 811 double get_success_error_level( int test_case_idx, int i, int j ); 812 int prepare_test_case( int test_case_idx ); 813 void run_func(); 814 void prepare_to_validation( int test_case_idx ); 815 816 double scale; 817 bool diagMtx; 818 }; 819 820 821 Core_TransformTest::Core_TransformTest() : Core_MatrixTest( 3, 1, true, false, 4 ) 822 { 823 scale = 1; 824 diagMtx = false; 825 } 826 827 828 void Core_TransformTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 829 { 830 RNG& rng = ts->get_rng(); 831 int bits = cvtest::randInt(rng); 832 int depth, dst_cn, mat_cols, mattype; 833 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 834 835 mat_cols = CV_MAT_CN(types[INPUT][0]); 836 depth = CV_MAT_DEPTH(types[INPUT][0]); 837 dst_cn = cvtest::randInt(rng) % 4 + 1; 838 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, dst_cn); 839 840 mattype = depth < CV_32S ? CV_32F : depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F; 841 types[INPUT][1] = mattype; 842 types[INPUT][2] = CV_MAKETYPE(mattype, dst_cn); 843 844 scale = 1./((cvtest::randInt(rng)%4)*50+1); 845 846 if( bits & 2 ) 847 { 848 sizes[INPUT][2] = Size(0,0); 849 mat_cols += (bits & 4) != 0; 850 } 851 else if( bits & 4 ) 852 sizes[INPUT][2] = Size(1,1); 853 else 854 { 855 if( bits & 8 ) 856 sizes[INPUT][2] = Size(dst_cn,1); 857 else 858 sizes[INPUT][2] = Size(1,dst_cn); 859 types[INPUT][2] &= ~CV_MAT_CN_MASK; 860 } 861 diagMtx = (bits & 16) != 0; 862 863 sizes[INPUT][1] = Size(mat_cols,dst_cn); 864 } 865 866 867 int Core_TransformTest::prepare_test_case( int test_case_idx ) 868 { 869 int code = Base::prepare_test_case( test_case_idx ); 870 if( code > 0 ) 871 { 872 Mat& m = test_mat[INPUT][1]; 873 cvtest::add(m, scale, m, 0, Scalar::all(0), m, m.type() ); 874 if(diagMtx) 875 { 876 Mat mask = Mat::eye(m.rows, m.cols, CV_8U)*255; 877 mask = ~mask; 878 m.setTo(Scalar::all(0), mask); 879 } 880 } 881 return code; 882 } 883 884 885 double Core_TransformTest::get_success_error_level( int test_case_idx, int i, int j ) 886 { 887 int depth = test_mat[INPUT][0].depth(); 888 return depth <= CV_8S ? 1 : depth <= CV_32S ? 9 : Base::get_success_error_level( test_case_idx, i, j ); 889 } 890 891 void Core_TransformTest::run_func() 892 { 893 CvMat _m = test_mat[INPUT][1], _shift = test_mat[INPUT][2]; 894 cvTransform( test_array[INPUT][0], test_array[OUTPUT][0], &_m, _shift.data.ptr ? &_shift : 0); 895 } 896 897 898 void Core_TransformTest::prepare_to_validation( int ) 899 { 900 Mat transmat = test_mat[INPUT][1]; 901 Mat shift = test_mat[INPUT][2]; 902 903 cvtest::transform( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], transmat, shift ); 904 } 905 906 907 ///////////////// PerspectiveTransform ///////////////////// 908 909 class Core_PerspectiveTransformTest : public Core_MatrixTest 910 { 911 public: 912 Core_PerspectiveTransformTest(); 913 protected: 914 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 915 double get_success_error_level( int test_case_idx, int i, int j ); 916 void run_func(); 917 void prepare_to_validation( int test_case_idx ); 918 }; 919 920 921 Core_PerspectiveTransformTest::Core_PerspectiveTransformTest() : Core_MatrixTest( 2, 1, false, false, 2 ) 922 { 923 } 924 925 926 void Core_PerspectiveTransformTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 927 { 928 RNG& rng = ts->get_rng(); 929 int bits = cvtest::randInt(rng); 930 int depth, cn, mattype; 931 Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 932 933 cn = CV_MAT_CN(types[INPUT][0]) + 1; 934 depth = CV_MAT_DEPTH(types[INPUT][0]); 935 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn); 936 937 mattype = depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F; 938 types[INPUT][1] = mattype; 939 sizes[INPUT][1] = Size(cn + 1, cn + 1); 940 } 941 942 943 double Core_PerspectiveTransformTest::get_success_error_level( int test_case_idx, int i, int j ) 944 { 945 int depth = test_mat[INPUT][0].depth(); 946 return depth == CV_32F ? 1e-4 : depth == CV_64F ? 1e-8 : 947 Core_MatrixTest::get_success_error_level(test_case_idx, i, j); 948 } 949 950 951 void Core_PerspectiveTransformTest::run_func() 952 { 953 CvMat _m = test_mat[INPUT][1]; 954 cvPerspectiveTransform( test_array[INPUT][0], test_array[OUTPUT][0], &_m ); 955 } 956 957 958 static void cvTsPerspectiveTransform( const CvArr* _src, CvArr* _dst, const CvMat* transmat ) 959 { 960 int i, j, cols; 961 int cn, depth, mat_depth; 962 CvMat astub, bstub, *a, *b; 963 double mat[16]; 964 965 a = cvGetMat( _src, &astub, 0, 0 ); 966 b = cvGetMat( _dst, &bstub, 0, 0 ); 967 968 cn = CV_MAT_CN(a->type); 969 depth = CV_MAT_DEPTH(a->type); 970 mat_depth = CV_MAT_DEPTH(transmat->type); 971 cols = transmat->cols; 972 973 // prepare cn x (cn + 1) transform matrix 974 if( mat_depth == CV_32F ) 975 { 976 for( i = 0; i < transmat->rows; i++ ) 977 for( j = 0; j < cols; j++ ) 978 mat[i*cols + j] = ((float*)(transmat->data.ptr + transmat->step*i))[j]; 979 } 980 else 981 { 982 assert( mat_depth == CV_64F ); 983 for( i = 0; i < transmat->rows; i++ ) 984 for( j = 0; j < cols; j++ ) 985 mat[i*cols + j] = ((double*)(transmat->data.ptr + transmat->step*i))[j]; 986 } 987 988 // transform data 989 cols = a->cols * cn; 990 vector<double> buf(cols); 991 992 for( i = 0; i < a->rows; i++ ) 993 { 994 uchar* src = a->data.ptr + i*a->step; 995 uchar* dst = b->data.ptr + i*b->step; 996 997 switch( depth ) 998 { 999 case CV_32F: 1000 for( j = 0; j < cols; j++ ) 1001 buf[j] = ((float*)src)[j]; 1002 break; 1003 case CV_64F: 1004 for( j = 0; j < cols; j++ ) 1005 buf[j] = ((double*)src)[j]; 1006 break; 1007 default: 1008 assert(0); 1009 } 1010 1011 switch( cn ) 1012 { 1013 case 2: 1014 for( j = 0; j < cols; j += 2 ) 1015 { 1016 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + mat[2]; 1017 double t1 = buf[j]*mat[3] + buf[j+1]*mat[4] + mat[5]; 1018 double w = buf[j]*mat[6] + buf[j+1]*mat[7] + mat[8]; 1019 w = w ? 1./w : 0; 1020 buf[j] = t0*w; 1021 buf[j+1] = t1*w; 1022 } 1023 break; 1024 case 3: 1025 for( j = 0; j < cols; j += 3 ) 1026 { 1027 double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + buf[j+2]*mat[2] + mat[3]; 1028 double t1 = buf[j]*mat[4] + buf[j+1]*mat[5] + buf[j+2]*mat[6] + mat[7]; 1029 double t2 = buf[j]*mat[8] + buf[j+1]*mat[9] + buf[j+2]*mat[10] + mat[11]; 1030 double w = buf[j]*mat[12] + buf[j+1]*mat[13] + buf[j+2]*mat[14] + mat[15]; 1031 w = w ? 1./w : 0; 1032 buf[j] = t0*w; 1033 buf[j+1] = t1*w; 1034 buf[j+2] = t2*w; 1035 } 1036 break; 1037 default: 1038 assert(0); 1039 } 1040 1041 switch( depth ) 1042 { 1043 case CV_32F: 1044 for( j = 0; j < cols; j++ ) 1045 ((float*)dst)[j] = (float)buf[j]; 1046 break; 1047 case CV_64F: 1048 for( j = 0; j < cols; j++ ) 1049 ((double*)dst)[j] = buf[j]; 1050 break; 1051 default: 1052 assert(0); 1053 } 1054 } 1055 } 1056 1057 1058 void Core_PerspectiveTransformTest::prepare_to_validation( int ) 1059 { 1060 CvMat transmat = test_mat[INPUT][1]; 1061 cvTsPerspectiveTransform( test_array[INPUT][0], test_array[REF_OUTPUT][0], &transmat ); 1062 } 1063 1064 ///////////////// Mahalanobis ///////////////////// 1065 1066 class Core_MahalanobisTest : public Core_MatrixTest 1067 { 1068 public: 1069 typedef Core_MatrixTest Base; 1070 Core_MahalanobisTest(); 1071 protected: 1072 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 1073 int prepare_test_case( int test_case_idx ); 1074 void run_func(); 1075 void prepare_to_validation( int test_case_idx ); 1076 }; 1077 1078 1079 Core_MahalanobisTest::Core_MahalanobisTest() : Core_MatrixTest( 3, 1, false, true, 1 ) 1080 { 1081 test_case_count = 100; 1082 test_array[TEMP].push_back(NULL); 1083 test_array[TEMP].push_back(NULL); 1084 test_array[TEMP].push_back(NULL); 1085 } 1086 1087 1088 void Core_MahalanobisTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 1089 { 1090 RNG& rng = ts->get_rng(); 1091 Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1092 1093 if( cvtest::randInt(rng) & 1 ) 1094 sizes[INPUT][0].width = sizes[INPUT][1].width = 1; 1095 else 1096 sizes[INPUT][0].height = sizes[INPUT][1].height = 1; 1097 1098 sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT][0]; 1099 sizes[INPUT][2].width = sizes[INPUT][2].height = sizes[INPUT][0].width + sizes[INPUT][0].height - 1; 1100 sizes[TEMP][2] = sizes[INPUT][2]; 1101 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0]; 1102 } 1103 1104 int Core_MahalanobisTest::prepare_test_case( int test_case_idx ) 1105 { 1106 int code = Base::prepare_test_case( test_case_idx ); 1107 if( code > 0 ) 1108 { 1109 // make sure that the inverted "covariation" matrix is symmetrix and positively defined. 1110 cvtest::gemm( test_mat[INPUT][2], test_mat[INPUT][2], 1., Mat(), 0., test_mat[TEMP][2], GEMM_2_T ); 1111 cvtest::copy( test_mat[TEMP][2], test_mat[INPUT][2] ); 1112 } 1113 1114 return code; 1115 } 1116 1117 1118 void Core_MahalanobisTest::run_func() 1119 { 1120 test_mat[OUTPUT][0].at<Scalar>(0,0) = 1121 cvRealScalar(cvMahalanobis(test_array[INPUT][0], test_array[INPUT][1], test_array[INPUT][2])); 1122 } 1123 1124 void Core_MahalanobisTest::prepare_to_validation( int ) 1125 { 1126 cvtest::add( test_mat[INPUT][0], 1., test_mat[INPUT][1], -1., 1127 Scalar::all(0), test_mat[TEMP][0], test_mat[TEMP][0].type() ); 1128 if( test_mat[INPUT][0].rows == 1 ) 1129 cvtest::gemm( test_mat[TEMP][0], test_mat[INPUT][2], 1., 1130 Mat(), 0., test_mat[TEMP][1], 0 ); 1131 else 1132 cvtest::gemm( test_mat[INPUT][2], test_mat[TEMP][0], 1., 1133 Mat(), 0., test_mat[TEMP][1], 0 ); 1134 1135 test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = cvRealScalar(sqrt(cvtest::crossCorr(test_mat[TEMP][0], test_mat[TEMP][1]))); 1136 } 1137 1138 1139 ///////////////// covarmatrix ///////////////////// 1140 1141 class Core_CovarMatrixTest : public Core_MatrixTest 1142 { 1143 public: 1144 Core_CovarMatrixTest(); 1145 protected: 1146 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 1147 int prepare_test_case( int test_case_idx ); 1148 void run_func(); 1149 void prepare_to_validation( int test_case_idx ); 1150 vector<void*> temp_hdrs; 1151 vector<uchar> hdr_data; 1152 int flags, t_flag, len, count; 1153 bool are_images; 1154 }; 1155 1156 1157 Core_CovarMatrixTest::Core_CovarMatrixTest() : Core_MatrixTest( 1, 1, true, false, 1 ), 1158 flags(0), t_flag(0), len(0), count(0), are_images(false) 1159 { 1160 test_case_count = 100; 1161 test_array[INPUT_OUTPUT].push_back(NULL); 1162 test_array[REF_INPUT_OUTPUT].push_back(NULL); 1163 test_array[TEMP].push_back(NULL); 1164 test_array[TEMP].push_back(NULL); 1165 } 1166 1167 1168 void Core_CovarMatrixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 1169 { 1170 RNG& rng = ts->get_rng(); 1171 int bits = cvtest::randInt(rng); 1172 int i, single_matrix; 1173 Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1174 1175 flags = bits & (CV_COVAR_NORMAL | CV_COVAR_USE_AVG | CV_COVAR_SCALE | CV_COVAR_ROWS ); 1176 single_matrix = flags & CV_COVAR_ROWS; 1177 t_flag = (bits & 256) != 0; 1178 1179 const int min_count = 2; 1180 1181 if( !t_flag ) 1182 { 1183 len = sizes[INPUT][0].width; 1184 count = sizes[INPUT][0].height; 1185 count = MAX(count, min_count); 1186 sizes[INPUT][0] = Size(len, count); 1187 } 1188 else 1189 { 1190 len = sizes[INPUT][0].height; 1191 count = sizes[INPUT][0].width; 1192 count = MAX(count, min_count); 1193 sizes[INPUT][0] = Size(count, len); 1194 } 1195 1196 if( single_matrix && t_flag ) 1197 flags = (flags & ~CV_COVAR_ROWS) | CV_COVAR_COLS; 1198 1199 if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32S ) 1200 types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK) | CV_32F; 1201 1202 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = flags & CV_COVAR_NORMAL ? Size(len,len) : Size(count,count); 1203 sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = !t_flag ? Size(len,1) : Size(1,len); 1204 sizes[TEMP][0] = sizes[INPUT][0]; 1205 1206 types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = 1207 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0] = 1208 CV_MAT_DEPTH(types[INPUT][0]) == CV_64F || (bits & 512) ? CV_64F : CV_32F; 1209 1210 are_images = (bits & 1024) != 0; 1211 for( i = 0; i < (single_matrix ? 1 : count); i++ ) 1212 temp_hdrs.push_back(NULL); 1213 } 1214 1215 1216 int Core_CovarMatrixTest::prepare_test_case( int test_case_idx ) 1217 { 1218 int code = Core_MatrixTest::prepare_test_case( test_case_idx ); 1219 if( code > 0 ) 1220 { 1221 int i; 1222 int single_matrix = flags & (CV_COVAR_ROWS|CV_COVAR_COLS); 1223 int hdr_size = are_images ? sizeof(IplImage) : sizeof(CvMat); 1224 1225 hdr_data.resize(count*hdr_size); 1226 uchar* _hdr_data = &hdr_data[0]; 1227 if( single_matrix ) 1228 { 1229 if( !are_images ) 1230 *((CvMat*)_hdr_data) = test_mat[INPUT][0]; 1231 else 1232 *((IplImage*)_hdr_data) = test_mat[INPUT][0]; 1233 temp_hdrs[0] = _hdr_data; 1234 } 1235 else 1236 for( i = 0; i < count; i++ ) 1237 { 1238 Mat part; 1239 void* ptr = _hdr_data + i*hdr_size; 1240 1241 if( !t_flag ) 1242 part = test_mat[INPUT][0].row(i); 1243 else 1244 part = test_mat[INPUT][0].col(i); 1245 1246 if( !are_images ) 1247 *((CvMat*)ptr) = part; 1248 else 1249 *((IplImage*)ptr) = part; 1250 1251 temp_hdrs[i] = ptr; 1252 } 1253 } 1254 1255 return code; 1256 } 1257 1258 1259 void Core_CovarMatrixTest::run_func() 1260 { 1261 cvCalcCovarMatrix( (const void**)&temp_hdrs[0], count, 1262 test_array[OUTPUT][0], test_array[INPUT_OUTPUT][0], flags ); 1263 } 1264 1265 1266 void Core_CovarMatrixTest::prepare_to_validation( int ) 1267 { 1268 Mat& avg = test_mat[REF_INPUT_OUTPUT][0]; 1269 double scale = 1.; 1270 1271 if( !(flags & CV_COVAR_USE_AVG) ) 1272 { 1273 Mat hdrs0 = cvarrToMat(temp_hdrs[0]); 1274 1275 int i; 1276 avg = Scalar::all(0); 1277 1278 for( i = 0; i < count; i++ ) 1279 { 1280 Mat vec; 1281 if( flags & CV_COVAR_ROWS ) 1282 vec = hdrs0.row(i); 1283 else if( flags & CV_COVAR_COLS ) 1284 vec = hdrs0.col(i); 1285 else 1286 vec = cvarrToMat(temp_hdrs[i]); 1287 1288 cvtest::add(avg, 1, vec, 1, Scalar::all(0), avg, avg.type()); 1289 } 1290 1291 cvtest::add(avg, 1./count, avg, 0., Scalar::all(0), avg, avg.type()); 1292 } 1293 1294 if( flags & CV_COVAR_SCALE ) 1295 { 1296 scale = 1./count; 1297 } 1298 1299 Mat& temp0 = test_mat[TEMP][0]; 1300 cv::repeat( avg, temp0.rows/avg.rows, temp0.cols/avg.cols, temp0 ); 1301 cvtest::add( test_mat[INPUT][0], 1, temp0, -1, Scalar::all(0), temp0, temp0.type()); 1302 1303 cvtest::gemm( temp0, temp0, scale, Mat(), 0., test_mat[REF_OUTPUT][0], 1304 t_flag ^ ((flags & CV_COVAR_NORMAL) != 0) ? CV_GEMM_A_T : CV_GEMM_B_T ); 1305 temp_hdrs.clear(); 1306 } 1307 1308 1309 static void cvTsFloodWithZeros( Mat& mat, RNG& rng ) 1310 { 1311 int k, total = mat.rows*mat.cols, type = mat.type(); 1312 int zero_total = cvtest::randInt(rng) % total; 1313 CV_Assert( type == CV_32FC1 || type == CV_64FC1 ); 1314 1315 for( k = 0; k < zero_total; k++ ) 1316 { 1317 int i = cvtest::randInt(rng) % mat.rows; 1318 int j = cvtest::randInt(rng) % mat.cols; 1319 1320 if( type == CV_32FC1 ) 1321 mat.at<float>(i,j) = 0.f; 1322 else 1323 mat.at<double>(i,j) = 0.; 1324 } 1325 } 1326 1327 1328 ///////////////// determinant ///////////////////// 1329 1330 class Core_DetTest : public Core_MatrixTest 1331 { 1332 public: 1333 typedef Core_MatrixTest Base; 1334 Core_DetTest(); 1335 protected: 1336 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 1337 double get_success_error_level( int test_case_idx, int i, int j ); 1338 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ); 1339 int prepare_test_case( int test_case_idx ); 1340 void run_func(); 1341 void prepare_to_validation( int test_case_idx ); 1342 }; 1343 1344 1345 Core_DetTest::Core_DetTest() : Core_MatrixTest( 1, 1, false, true, 1 ) 1346 { 1347 test_case_count = 100; 1348 max_log_array_size = 7; 1349 test_array[TEMP].push_back(NULL); 1350 } 1351 1352 1353 void Core_DetTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 1354 { 1355 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1356 1357 sizes[INPUT][0].width = sizes[INPUT][0].height; 1358 sizes[TEMP][0] = sizes[INPUT][0]; 1359 types[TEMP][0] = CV_64FC1; 1360 } 1361 1362 1363 void Core_DetTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ) 1364 { 1365 low = cvScalarAll(-2.); 1366 high = cvScalarAll(2.); 1367 } 1368 1369 1370 double Core_DetTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 1371 { 1372 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-2 : 1e-5; 1373 } 1374 1375 1376 int Core_DetTest::prepare_test_case( int test_case_idx ) 1377 { 1378 int code = Core_MatrixTest::prepare_test_case( test_case_idx ); 1379 if( code > 0 ) 1380 cvTsFloodWithZeros( test_mat[INPUT][0], ts->get_rng() ); 1381 1382 return code; 1383 } 1384 1385 1386 void Core_DetTest::run_func() 1387 { 1388 test_mat[OUTPUT][0].at<Scalar>(0,0) = cvRealScalar(cvDet(test_array[INPUT][0])); 1389 } 1390 1391 1392 // LU method that chooses the optimal in a column pivot element 1393 static double cvTsLU( CvMat* a, CvMat* b=NULL, CvMat* x=NULL, int* rank=0 ) 1394 { 1395 int i, j, k, N = a->rows, N1 = a->cols, Nm = MIN(N, N1), step = a->step/sizeof(double); 1396 int M = b ? b->cols : 0, b_step = b ? b->step/sizeof(double) : 0; 1397 int x_step = x ? x->step/sizeof(double) : 0; 1398 double *a0 = a->data.db, *b0 = b ? b->data.db : 0; 1399 double *x0 = x ? x->data.db : 0; 1400 double t, det = 1.; 1401 assert( CV_MAT_TYPE(a->type) == CV_64FC1 && 1402 (!b || CV_ARE_TYPES_EQ(a,b)) && (!x || CV_ARE_TYPES_EQ(a,x))); 1403 1404 for( i = 0; i < Nm; i++ ) 1405 { 1406 double max_val = fabs(a0[i*step + i]); 1407 double *a1, *a2, *b1 = 0, *b2 = 0; 1408 k = i; 1409 1410 for( j = i+1; j < N; j++ ) 1411 { 1412 t = fabs(a0[j*step + i]); 1413 if( max_val < t ) 1414 { 1415 max_val = t; 1416 k = j; 1417 } 1418 } 1419 1420 if( k != i ) 1421 { 1422 for( j = i; j < N1; j++ ) 1423 CV_SWAP( a0[i*step + j], a0[k*step + j], t ); 1424 1425 for( j = 0; j < M; j++ ) 1426 CV_SWAP( b0[i*b_step + j], b0[k*b_step + j], t ); 1427 det = -det; 1428 } 1429 1430 if( max_val == 0 ) 1431 { 1432 if( rank ) 1433 *rank = i; 1434 return 0.; 1435 } 1436 1437 a1 = a0 + i*step; 1438 a2 = a1 + step; 1439 b1 = b0 + i*b_step; 1440 b2 = b1 + b_step; 1441 1442 for( j = i+1; j < N; j++, a2 += step, b2 += b_step ) 1443 { 1444 t = a2[i]/a1[i]; 1445 for( k = i+1; k < N1; k++ ) 1446 a2[k] -= t*a1[k]; 1447 1448 for( k = 0; k < M; k++ ) 1449 b2[k] -= t*b1[k]; 1450 } 1451 1452 det *= a1[i]; 1453 } 1454 1455 if( x ) 1456 { 1457 assert( b ); 1458 1459 for( i = N-1; i >= 0; i-- ) 1460 { 1461 double* a1 = a0 + i*step; 1462 double* b1 = b0 + i*b_step; 1463 for( j = 0; j < M; j++ ) 1464 { 1465 t = b1[j]; 1466 for( k = i+1; k < N1; k++ ) 1467 t -= a1[k]*x0[k*x_step + j]; 1468 x0[i*x_step + j] = t/a1[i]; 1469 } 1470 } 1471 } 1472 1473 if( rank ) 1474 *rank = i; 1475 return det; 1476 } 1477 1478 1479 void Core_DetTest::prepare_to_validation( int ) 1480 { 1481 test_mat[INPUT][0].convertTo(test_mat[TEMP][0], test_mat[TEMP][0].type()); 1482 CvMat temp0 = test_mat[TEMP][0]; 1483 test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = cvRealScalar(cvTsLU(&temp0, 0, 0)); 1484 } 1485 1486 1487 ///////////////// invert ///////////////////// 1488 1489 class Core_InvertTest : public Core_MatrixTest 1490 { 1491 public: 1492 typedef Core_MatrixTest Base; 1493 Core_InvertTest(); 1494 protected: 1495 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 1496 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ); 1497 double get_success_error_level( int test_case_idx, int i, int j ); 1498 int prepare_test_case( int test_case_idx ); 1499 void run_func(); 1500 void prepare_to_validation( int test_case_idx ); 1501 int method, rank; 1502 double result; 1503 }; 1504 1505 1506 Core_InvertTest::Core_InvertTest() 1507 : Core_MatrixTest( 1, 1, false, false, 1 ), method(0), rank(0), result(0.) 1508 { 1509 test_case_count = 100; 1510 max_log_array_size = 7; 1511 test_array[TEMP].push_back(NULL); 1512 test_array[TEMP].push_back(NULL); 1513 } 1514 1515 1516 void Core_InvertTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 1517 { 1518 RNG& rng = ts->get_rng(); 1519 int bits = cvtest::randInt(rng); 1520 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1521 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height ); 1522 1523 if( (bits & 3) == 0 ) 1524 { 1525 method = CV_SVD; 1526 if( bits & 4 ) 1527 { 1528 sizes[INPUT][0] = Size(min_size, min_size); 1529 if( bits & 16 ) 1530 method = CV_CHOLESKY; 1531 } 1532 } 1533 else 1534 { 1535 method = CV_LU; 1536 sizes[INPUT][0] = Size(min_size, min_size); 1537 } 1538 1539 sizes[TEMP][0].width = sizes[INPUT][0].height; 1540 sizes[TEMP][0].height = sizes[INPUT][0].width; 1541 sizes[TEMP][1] = sizes[INPUT][0]; 1542 types[TEMP][0] = types[INPUT][0]; 1543 types[TEMP][1] = CV_64FC1; 1544 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = Size(min_size, min_size); 1545 } 1546 1547 1548 double Core_InvertTest::get_success_error_level( int /*test_case_idx*/, int, int ) 1549 { 1550 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 1e-2 : 1e-6; 1551 } 1552 1553 int Core_InvertTest::prepare_test_case( int test_case_idx ) 1554 { 1555 int code = Core_MatrixTest::prepare_test_case( test_case_idx ); 1556 if( code > 0 ) 1557 { 1558 cvTsFloodWithZeros( test_mat[INPUT][0], ts->get_rng() ); 1559 1560 if( method == CV_CHOLESKY ) 1561 { 1562 cvtest::gemm( test_mat[INPUT][0], test_mat[INPUT][0], 1., 1563 Mat(), 0., test_mat[TEMP][0], CV_GEMM_B_T ); 1564 cvtest::copy( test_mat[TEMP][0], test_mat[INPUT][0] ); 1565 } 1566 } 1567 1568 return code; 1569 } 1570 1571 1572 1573 void Core_InvertTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ) 1574 { 1575 low = cvScalarAll(-1.); 1576 high = cvScalarAll(1.); 1577 } 1578 1579 1580 void Core_InvertTest::run_func() 1581 { 1582 result = cvInvert(test_array[INPUT][0], test_array[TEMP][0], method); 1583 } 1584 1585 1586 static double cvTsSVDet( CvMat* mat, double* ratio ) 1587 { 1588 int type = CV_MAT_TYPE(mat->type); 1589 int i, nm = MIN( mat->rows, mat->cols ); 1590 CvMat* w = cvCreateMat( nm, 1, type ); 1591 double det = 1.; 1592 1593 cvSVD( mat, w, 0, 0, 0 ); 1594 1595 if( type == CV_32FC1 ) 1596 { 1597 for( i = 0; i < nm; i++ ) 1598 det *= w->data.fl[i]; 1599 *ratio = w->data.fl[nm-1] < FLT_EPSILON ? 0 : w->data.fl[nm-1]/w->data.fl[0]; 1600 } 1601 else 1602 { 1603 for( i = 0; i < nm; i++ ) 1604 det *= w->data.db[i]; 1605 *ratio = w->data.db[nm-1] < FLT_EPSILON ? 0 : w->data.db[nm-1]/w->data.db[0]; 1606 } 1607 1608 cvReleaseMat( &w ); 1609 return det; 1610 } 1611 1612 void Core_InvertTest::prepare_to_validation( int ) 1613 { 1614 Mat& input = test_mat[INPUT][0]; 1615 Mat& temp0 = test_mat[TEMP][0]; 1616 Mat& temp1 = test_mat[TEMP][1]; 1617 Mat& dst0 = test_mat[REF_OUTPUT][0]; 1618 Mat& dst = test_mat[OUTPUT][0]; 1619 CvMat _input = input; 1620 double ratio = 0, det = cvTsSVDet( &_input, &ratio ); 1621 double threshold = (input.depth() == CV_32F ? FLT_EPSILON : DBL_EPSILON)*1000; 1622 1623 cvtest::convert( input, temp1, temp1.type() ); 1624 1625 if( det < threshold || 1626 ((method == CV_LU || method == CV_CHOLESKY) && (result == 0 || ratio < threshold)) || 1627 ((method == CV_SVD || method == CV_SVD_SYM) && result < threshold) ) 1628 { 1629 dst = Scalar::all(0); 1630 dst0 = Scalar::all(0); 1631 return; 1632 } 1633 1634 if( input.rows >= input.cols ) 1635 cvtest::gemm( temp0, input, 1., Mat(), 0., dst, 0 ); 1636 else 1637 cvtest::gemm( input, temp0, 1., Mat(), 0., dst, 0 ); 1638 1639 cv::setIdentity( dst0, Scalar::all(1) ); 1640 } 1641 1642 1643 ///////////////// solve ///////////////////// 1644 1645 class Core_SolveTest : public Core_MatrixTest 1646 { 1647 public: 1648 typedef Core_MatrixTest Base; 1649 Core_SolveTest(); 1650 protected: 1651 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 1652 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ); 1653 double get_success_error_level( int test_case_idx, int i, int j ); 1654 int prepare_test_case( int test_case_idx ); 1655 void run_func(); 1656 void prepare_to_validation( int test_case_idx ); 1657 int method, rank; 1658 double result; 1659 }; 1660 1661 1662 Core_SolveTest::Core_SolveTest() : Core_MatrixTest( 2, 1, false, false, 1 ), method(0), rank(0), result(0.) 1663 { 1664 test_case_count = 100; 1665 max_log_array_size = 7; 1666 test_array[TEMP].push_back(NULL); 1667 test_array[TEMP].push_back(NULL); 1668 } 1669 1670 1671 void Core_SolveTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 1672 { 1673 RNG& rng = ts->get_rng(); 1674 int bits = cvtest::randInt(rng); 1675 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1676 CvSize in_sz = sizes[INPUT][0]; 1677 if( in_sz.width > in_sz.height ) 1678 in_sz = cvSize(in_sz.height, in_sz.width); 1679 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1680 sizes[INPUT][0] = in_sz; 1681 int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height ); 1682 1683 if( (bits & 3) == 0 ) 1684 { 1685 method = CV_SVD; 1686 if( bits & 4 ) 1687 { 1688 sizes[INPUT][0] = Size(min_size, min_size); 1689 /*if( bits & 8 ) 1690 method = CV_SVD_SYM;*/ 1691 } 1692 } 1693 else 1694 { 1695 method = CV_LU; 1696 sizes[INPUT][0] = Size(min_size, min_size); 1697 } 1698 1699 sizes[INPUT][1].height = sizes[INPUT][0].height; 1700 sizes[TEMP][0].width = sizes[INPUT][1].width; 1701 sizes[TEMP][0].height = sizes[INPUT][0].width; 1702 sizes[TEMP][1] = sizes[INPUT][0]; 1703 types[TEMP][0] = types[INPUT][0]; 1704 types[TEMP][1] = CV_64FC1; 1705 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = Size(sizes[INPUT][1].width, min_size); 1706 } 1707 1708 1709 int Core_SolveTest::prepare_test_case( int test_case_idx ) 1710 { 1711 int code = Core_MatrixTest::prepare_test_case( test_case_idx ); 1712 1713 /*if( method == CV_SVD_SYM ) 1714 { 1715 cvTsGEMM( test_array[INPUT][0], test_array[INPUT][0], 1., 1716 0, 0., test_array[TEMP][0], CV_GEMM_B_T ); 1717 cvTsCopy( test_array[TEMP][0], test_array[INPUT][0] ); 1718 }*/ 1719 1720 return code; 1721 } 1722 1723 1724 void Core_SolveTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ) 1725 { 1726 low = cvScalarAll(-1.); 1727 high = cvScalarAll(1.); 1728 } 1729 1730 1731 double Core_SolveTest::get_success_error_level( int /*test_case_idx*/, int, int ) 1732 { 1733 return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 5e-2 : 1e-8; 1734 } 1735 1736 1737 void Core_SolveTest::run_func() 1738 { 1739 result = cvSolve(test_array[INPUT][0], test_array[INPUT][1], test_array[TEMP][0], method); 1740 } 1741 1742 void Core_SolveTest::prepare_to_validation( int ) 1743 { 1744 //int rank = test_mat[REF_OUTPUT][0].rows; 1745 Mat& input = test_mat[INPUT][0]; 1746 Mat& dst = test_mat[OUTPUT][0]; 1747 Mat& dst0 = test_mat[REF_OUTPUT][0]; 1748 1749 if( method == CV_LU ) 1750 { 1751 if( result == 0 ) 1752 { 1753 Mat& temp1 = test_mat[TEMP][1]; 1754 cvtest::convert(input, temp1, temp1.type()); 1755 dst = Scalar::all(0); 1756 CvMat _temp1 = temp1; 1757 double det = cvTsLU( &_temp1, 0, 0 ); 1758 dst0 = Scalar::all(det != 0); 1759 return; 1760 } 1761 1762 double threshold = (input.type() == CV_32F ? FLT_EPSILON : DBL_EPSILON)*1000; 1763 CvMat _input = input; 1764 double ratio = 0, det = cvTsSVDet( &_input, &ratio ); 1765 if( det < threshold || ratio < threshold ) 1766 { 1767 dst = Scalar::all(0); 1768 dst0 = Scalar::all(0); 1769 return; 1770 } 1771 } 1772 1773 Mat* pdst = input.rows <= input.cols ? &test_mat[OUTPUT][0] : &test_mat[INPUT][1]; 1774 1775 cvtest::gemm( input, test_mat[TEMP][0], 1., test_mat[INPUT][1], -1., *pdst, 0 ); 1776 if( pdst != &dst ) 1777 cvtest::gemm( input, *pdst, 1., Mat(), 0., dst, CV_GEMM_A_T ); 1778 dst0 = Scalar::all(0); 1779 } 1780 1781 1782 ///////////////// SVD ///////////////////// 1783 1784 class Core_SVDTest : public Core_MatrixTest 1785 { 1786 public: 1787 typedef Core_MatrixTest Base; 1788 Core_SVDTest(); 1789 protected: 1790 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 1791 double get_success_error_level( int test_case_idx, int i, int j ); 1792 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ); 1793 int prepare_test_case( int test_case_idx ); 1794 void run_func(); 1795 void prepare_to_validation( int test_case_idx ); 1796 int flags; 1797 bool have_u, have_v, symmetric, compact, vector_w; 1798 }; 1799 1800 1801 Core_SVDTest::Core_SVDTest() : 1802 Core_MatrixTest( 1, 4, false, false, 1 ), 1803 flags(0), have_u(false), have_v(false), symmetric(false), compact(false), vector_w(false) 1804 { 1805 test_case_count = 100; 1806 max_log_array_size = 8; 1807 test_array[TEMP].push_back(NULL); 1808 test_array[TEMP].push_back(NULL); 1809 test_array[TEMP].push_back(NULL); 1810 test_array[TEMP].push_back(NULL); 1811 } 1812 1813 1814 void Core_SVDTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 1815 { 1816 RNG& rng = ts->get_rng(); 1817 int bits = cvtest::randInt(rng); 1818 Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1819 int min_size, i, m, n; 1820 1821 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height ); 1822 1823 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T); 1824 have_u = (bits & 8) != 0; 1825 have_v = (bits & 16) != 0; 1826 symmetric = (bits & 32) != 0; 1827 compact = (bits & 64) != 0; 1828 vector_w = (bits & 128) != 0; 1829 1830 if( symmetric ) 1831 sizes[INPUT][0] = Size(min_size, min_size); 1832 1833 m = sizes[INPUT][0].height; 1834 n = sizes[INPUT][0].width; 1835 1836 if( compact ) 1837 sizes[TEMP][0] = Size(min_size, min_size); 1838 else 1839 sizes[TEMP][0] = sizes[INPUT][0]; 1840 sizes[TEMP][3] = Size(0,0); 1841 1842 if( vector_w ) 1843 { 1844 sizes[TEMP][3] = sizes[TEMP][0]; 1845 if( bits & 256 ) 1846 sizes[TEMP][0] = Size(1, min_size); 1847 else 1848 sizes[TEMP][0] = Size(min_size, 1); 1849 } 1850 1851 if( have_u ) 1852 { 1853 sizes[TEMP][1] = compact ? Size(min_size, m) : Size(m, m); 1854 1855 if( flags & CV_SVD_U_T ) 1856 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i ); 1857 } 1858 else 1859 sizes[TEMP][1] = Size(0,0); 1860 1861 if( have_v ) 1862 { 1863 sizes[TEMP][2] = compact ? Size(n, min_size) : Size(n, n); 1864 1865 if( !(flags & CV_SVD_V_T) ) 1866 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i ); 1867 } 1868 else 1869 sizes[TEMP][2] = Size(0,0); 1870 1871 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[TEMP][3] = types[INPUT][0]; 1872 types[OUTPUT][0] = types[OUTPUT][1] = types[OUTPUT][2] = types[INPUT][0]; 1873 types[OUTPUT][3] = CV_8UC1; 1874 sizes[OUTPUT][0] = !have_u || !have_v ? Size(0,0) : sizes[INPUT][0]; 1875 sizes[OUTPUT][1] = !have_u ? Size(0,0) : compact ? Size(min_size,min_size) : Size(m,m); 1876 sizes[OUTPUT][2] = !have_v ? Size(0,0) : compact ? Size(min_size,min_size) : Size(n,n); 1877 sizes[OUTPUT][3] = Size(min_size,1); 1878 1879 for( i = 0; i < 4; i++ ) 1880 { 1881 sizes[REF_OUTPUT][i] = sizes[OUTPUT][i]; 1882 types[REF_OUTPUT][i] = types[OUTPUT][i]; 1883 } 1884 } 1885 1886 1887 int Core_SVDTest::prepare_test_case( int test_case_idx ) 1888 { 1889 int code = Core_MatrixTest::prepare_test_case( test_case_idx ); 1890 if( code > 0 ) 1891 { 1892 Mat& input = test_mat[INPUT][0]; 1893 cvTsFloodWithZeros( input, ts->get_rng() ); 1894 1895 if( symmetric && (have_u || have_v) ) 1896 { 1897 Mat& temp = test_mat[TEMP][have_u ? 1 : 2]; 1898 cvtest::gemm( input, input, 1., Mat(), 0., temp, CV_GEMM_B_T ); 1899 cvtest::copy( temp, input ); 1900 } 1901 1902 if( (flags & CV_SVD_MODIFY_A) && test_array[OUTPUT][0] ) 1903 cvtest::copy( input, test_mat[OUTPUT][0] ); 1904 } 1905 1906 return code; 1907 } 1908 1909 1910 void Core_SVDTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ) 1911 { 1912 low = cvScalarAll(-2.); 1913 high = cvScalarAll(2.); 1914 } 1915 1916 double Core_SVDTest::get_success_error_level( int test_case_idx, int i, int j ) 1917 { 1918 int input_depth = CV_MAT_DEPTH(cvGetElemType( test_array[INPUT][0] )); 1919 double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ? 1e-5 : 5e-11; 1920 double output_precision = Base::get_success_error_level( test_case_idx, i, j ); 1921 return MAX(input_precision, output_precision); 1922 } 1923 1924 void Core_SVDTest::run_func() 1925 { 1926 CvArr* src = test_array[!(flags & CV_SVD_MODIFY_A) ? INPUT : OUTPUT][0]; 1927 if( !src ) 1928 src = test_array[INPUT][0]; 1929 cvSVD( src, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags ); 1930 } 1931 1932 1933 void Core_SVDTest::prepare_to_validation( int /*test_case_idx*/ ) 1934 { 1935 Mat& input = test_mat[INPUT][0]; 1936 int depth = input.depth(); 1937 int i, m = input.rows, n = input.cols, min_size = MIN(m, n); 1938 Mat *src, *dst, *w; 1939 double prev = 0, threshold = depth == CV_32F ? FLT_EPSILON : DBL_EPSILON; 1940 1941 if( have_u ) 1942 { 1943 src = &test_mat[TEMP][1]; 1944 dst = &test_mat[OUTPUT][1]; 1945 cvtest::gemm( *src, *src, 1., Mat(), 0., *dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T ); 1946 cv::setIdentity( test_mat[REF_OUTPUT][1], Scalar::all(1.) ); 1947 } 1948 1949 if( have_v ) 1950 { 1951 src = &test_mat[TEMP][2]; 1952 dst = &test_mat[OUTPUT][2]; 1953 cvtest::gemm( *src, *src, 1., Mat(), 0., *dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T ); 1954 cv::setIdentity( test_mat[REF_OUTPUT][2], Scalar::all(1.) ); 1955 } 1956 1957 w = &test_mat[TEMP][0]; 1958 for( i = 0; i < min_size; i++ ) 1959 { 1960 double normval = 0, aii; 1961 if( w->rows > 1 && w->cols > 1 ) 1962 { 1963 normval = cvtest::norm( w->row(i), NORM_L1 ); 1964 aii = depth == CV_32F ? w->at<float>(i,i) : w->at<double>(i,i); 1965 } 1966 else 1967 { 1968 normval = aii = depth == CV_32F ? w->at<float>(i) : w->at<double>(i); 1969 } 1970 1971 normval = fabs(normval - aii); 1972 test_mat[OUTPUT][3].at<uchar>(i) = aii >= 0 && normval < threshold && (i == 0 || aii <= prev); 1973 prev = aii; 1974 } 1975 1976 test_mat[REF_OUTPUT][3] = Scalar::all(1); 1977 1978 if( have_u && have_v ) 1979 { 1980 if( vector_w ) 1981 { 1982 test_mat[TEMP][3] = Scalar::all(0); 1983 for( i = 0; i < min_size; i++ ) 1984 { 1985 double val = depth == CV_32F ? w->at<float>(i) : w->at<double>(i); 1986 cvSetReal2D( test_array[TEMP][3], i, i, val ); 1987 } 1988 w = &test_mat[TEMP][3]; 1989 } 1990 1991 if( m >= n ) 1992 { 1993 cvtest::gemm( test_mat[TEMP][1], *w, 1., Mat(), 0., test_mat[REF_OUTPUT][0], 1994 flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 ); 1995 cvtest::gemm( test_mat[REF_OUTPUT][0], test_mat[TEMP][2], 1., Mat(), 0., 1996 test_mat[OUTPUT][0], flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T ); 1997 } 1998 else 1999 { 2000 cvtest::gemm( *w, test_mat[TEMP][2], 1., Mat(), 0., test_mat[REF_OUTPUT][0], 2001 flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T ); 2002 cvtest::gemm( test_mat[TEMP][1], test_mat[REF_OUTPUT][0], 1., Mat(), 0., 2003 test_mat[OUTPUT][0], flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 ); 2004 } 2005 2006 cvtest::copy( test_mat[INPUT][0], test_mat[REF_OUTPUT][0] ); 2007 } 2008 } 2009 2010 2011 2012 ///////////////// SVBkSb ///////////////////// 2013 2014 class Core_SVBkSbTest : public Core_MatrixTest 2015 { 2016 public: 2017 typedef Core_MatrixTest Base; 2018 Core_SVBkSbTest(); 2019 protected: 2020 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 2021 double get_success_error_level( int test_case_idx, int i, int j ); 2022 void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ); 2023 int prepare_test_case( int test_case_idx ); 2024 void run_func(); 2025 void prepare_to_validation( int test_case_idx ); 2026 int flags; 2027 bool have_b, symmetric, compact, vector_w; 2028 }; 2029 2030 2031 Core_SVBkSbTest::Core_SVBkSbTest() : Core_MatrixTest( 2, 1, false, false, 1 ), 2032 flags(0), have_b(false), symmetric(false), compact(false), vector_w(false) 2033 { 2034 test_case_count = 100; 2035 test_array[TEMP].push_back(NULL); 2036 test_array[TEMP].push_back(NULL); 2037 test_array[TEMP].push_back(NULL); 2038 } 2039 2040 2041 void Core_SVBkSbTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, 2042 vector<vector<int> >& types ) 2043 { 2044 RNG& rng = ts->get_rng(); 2045 int bits = cvtest::randInt(rng); 2046 Base::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 2047 int min_size, i, m, n; 2048 CvSize b_size; 2049 2050 min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height ); 2051 2052 flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T); 2053 have_b = (bits & 16) != 0; 2054 symmetric = (bits & 32) != 0; 2055 compact = (bits & 64) != 0; 2056 vector_w = (bits & 128) != 0; 2057 2058 if( symmetric ) 2059 sizes[INPUT][0] = Size(min_size, min_size); 2060 2061 m = sizes[INPUT][0].height; 2062 n = sizes[INPUT][0].width; 2063 2064 sizes[INPUT][1] = Size(0,0); 2065 b_size = Size(m,m); 2066 if( have_b ) 2067 { 2068 sizes[INPUT][1].height = sizes[INPUT][0].height; 2069 sizes[INPUT][1].width = cvtest::randInt(rng) % 100 + 1; 2070 b_size = sizes[INPUT][1]; 2071 } 2072 2073 if( compact ) 2074 sizes[TEMP][0] = Size(min_size, min_size); 2075 else 2076 sizes[TEMP][0] = sizes[INPUT][0]; 2077 2078 if( vector_w ) 2079 { 2080 if( bits & 256 ) 2081 sizes[TEMP][0] = Size(1, min_size); 2082 else 2083 sizes[TEMP][0] = Size(min_size, 1); 2084 } 2085 2086 sizes[TEMP][1] = compact ? Size(min_size, m) : Size(m, m); 2087 2088 if( flags & CV_SVD_U_T ) 2089 CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i ); 2090 2091 sizes[TEMP][2] = compact ? Size(n, min_size) : Size(n, n); 2092 2093 if( !(flags & CV_SVD_V_T) ) 2094 CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i ); 2095 2096 types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0]; 2097 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][0]; 2098 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = Size( b_size.width, n ); 2099 } 2100 2101 2102 int Core_SVBkSbTest::prepare_test_case( int test_case_idx ) 2103 { 2104 int code = Base::prepare_test_case( test_case_idx ); 2105 if( code > 0 ) 2106 { 2107 Mat& input = test_mat[INPUT][0]; 2108 cvTsFloodWithZeros( input, ts->get_rng() ); 2109 2110 if( symmetric ) 2111 { 2112 Mat& temp = test_mat[TEMP][1]; 2113 cvtest::gemm( input, input, 1., Mat(), 0., temp, CV_GEMM_B_T ); 2114 cvtest::copy( temp, input ); 2115 } 2116 2117 CvMat _input = input; 2118 cvSVD( &_input, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags ); 2119 } 2120 2121 return code; 2122 } 2123 2124 2125 void Core_SVBkSbTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high ) 2126 { 2127 low = cvScalarAll(-2.); 2128 high = cvScalarAll(2.); 2129 } 2130 2131 2132 double Core_SVBkSbTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 2133 { 2134 return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-3 : 1e-7; 2135 } 2136 2137 2138 void Core_SVBkSbTest::run_func() 2139 { 2140 cvSVBkSb( test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], 2141 test_array[INPUT][1], test_array[OUTPUT][0], flags ); 2142 } 2143 2144 2145 void Core_SVBkSbTest::prepare_to_validation( int ) 2146 { 2147 Mat& input = test_mat[INPUT][0]; 2148 int i, m = input.rows, n = input.cols, min_size = MIN(m, n); 2149 bool is_float = input.type() == CV_32F; 2150 Size w_size = compact ? Size(min_size,min_size) : Size(m,n); 2151 Mat& w = test_mat[TEMP][0]; 2152 Mat wdb( w_size.height, w_size.width, CV_64FC1 ); 2153 CvMat _w = w, _wdb = wdb; 2154 // use exactly the same threshold as in icvSVD... , 2155 // so the changes in the library and here should be synchronized. 2156 double threshold = cv::sum(w)[0]*(DBL_EPSILON*2);//(is_float ? FLT_EPSILON*10 : DBL_EPSILON*2); 2157 2158 wdb = Scalar::all(0); 2159 for( i = 0; i < min_size; i++ ) 2160 { 2161 double wii = vector_w ? cvGetReal1D(&_w,i) : cvGetReal2D(&_w,i,i); 2162 cvSetReal2D( &_wdb, i, i, wii > threshold ? 1./wii : 0. ); 2163 } 2164 2165 Mat u = test_mat[TEMP][1]; 2166 Mat v = test_mat[TEMP][2]; 2167 Mat b = test_mat[INPUT][1]; 2168 2169 if( is_float ) 2170 { 2171 test_mat[TEMP][1].convertTo(u, CV_64F); 2172 test_mat[TEMP][2].convertTo(v, CV_64F); 2173 if( !b.empty() ) 2174 test_mat[INPUT][1].convertTo(b, CV_64F); 2175 } 2176 2177 Mat t0, t1; 2178 2179 if( !b.empty() ) 2180 cvtest::gemm( u, b, 1., Mat(), 0., t0, !(flags & CV_SVD_U_T) ? CV_GEMM_A_T : 0 ); 2181 else if( flags & CV_SVD_U_T ) 2182 cvtest::copy( u, t0 ); 2183 else 2184 cvtest::transpose( u, t0 ); 2185 2186 cvtest::gemm( wdb, t0, 1, Mat(), 0, t1, 0 ); 2187 2188 cvtest::gemm( v, t1, 1, Mat(), 0, t0, flags & CV_SVD_V_T ? CV_GEMM_A_T : 0 ); 2189 Mat& dst0 = test_mat[REF_OUTPUT][0]; 2190 t0.convertTo(dst0, dst0.type() ); 2191 } 2192 2193 2194 typedef std::complex<double> complex_type; 2195 2196 struct pred_complex 2197 { 2198 bool operator() (const complex_type& lhs, const complex_type& rhs) const 2199 { 2200 return fabs(lhs.real() - rhs.real()) > fabs(rhs.real())*FLT_EPSILON ? lhs.real() < rhs.real() : lhs.imag() < rhs.imag(); 2201 } 2202 }; 2203 2204 struct pred_double 2205 { 2206 bool operator() (const double& lhs, const double& rhs) const 2207 { 2208 return lhs < rhs; 2209 } 2210 }; 2211 2212 class Core_SolvePolyTest : public cvtest::BaseTest 2213 { 2214 public: 2215 Core_SolvePolyTest(); 2216 ~Core_SolvePolyTest(); 2217 protected: 2218 virtual void run( int start_from ); 2219 }; 2220 2221 Core_SolvePolyTest::Core_SolvePolyTest() {} 2222 2223 Core_SolvePolyTest::~Core_SolvePolyTest() {} 2224 2225 void Core_SolvePolyTest::run( int ) 2226 { 2227 RNG& rng = ts->get_rng(); 2228 int fig = 100; 2229 double range = 50; 2230 double err_eps = 1e-4; 2231 2232 for (int idx = 0, max_idx = 1000, progress = 0; idx < max_idx; ++idx) 2233 { 2234 progress = update_progress(progress, idx-1, max_idx, 0); 2235 int n = cvtest::randInt(rng) % 13 + 1; 2236 std::vector<complex_type> r(n), ar(n), c(n + 1, 0); 2237 std::vector<double> a(n + 1), u(n * 2), ar1(n), ar2(n); 2238 2239 int rr_odds = 3; // odds that we get a real root 2240 for (int j = 0; j < n;) 2241 { 2242 if (cvtest::randInt(rng) % rr_odds == 0 || j == n - 1) 2243 r[j++] = cvtest::randReal(rng) * range; 2244 else 2245 { 2246 r[j] = complex_type(cvtest::randReal(rng) * range, 2247 cvtest::randReal(rng) * range + 1); 2248 r[j + 1] = std::conj(r[j]); 2249 j += 2; 2250 } 2251 } 2252 2253 for (int j = 0, k = 1 << n, jj, kk; j < k; ++j) 2254 { 2255 int p = 0; 2256 complex_type v(1); 2257 for (jj = 0, kk = 1; jj < n && !(j & kk); ++jj, ++p, kk <<= 1) 2258 ; 2259 for (; jj < n; ++jj, kk <<= 1) 2260 { 2261 if (j & kk) 2262 v *= -r[jj]; 2263 else 2264 ++p; 2265 } 2266 c[p] += v; 2267 } 2268 2269 bool pass = false; 2270 double div = 0, s = 0; 2271 int cubic_case = idx & 1; 2272 for (int maxiter = 100; !pass && maxiter < 10000; maxiter *= 2, cubic_case = (cubic_case + 1) % 2) 2273 { 2274 for (int j = 0; j < n + 1; ++j) 2275 a[j] = c[j].real(); 2276 2277 CvMat amat, umat; 2278 cvInitMatHeader(&amat, n + 1, 1, CV_64FC1, &a[0]); 2279 cvInitMatHeader(&umat, n, 1, CV_64FC2, &u[0]); 2280 cvSolvePoly(&amat, &umat, maxiter, fig); 2281 2282 for (int j = 0; j < n; ++j) 2283 ar[j] = complex_type(u[j * 2], u[j * 2 + 1]); 2284 2285 std::sort(r.begin(), r.end(), pred_complex()); 2286 std::sort(ar.begin(), ar.end(), pred_complex()); 2287 2288 pass = true; 2289 if( n == 3 ) 2290 { 2291 ar2.resize(n); 2292 cv::Mat _umat2(3, 1, CV_64F, &ar2[0]), umat2 = _umat2; 2293 cvFlip(&amat, &amat, 0); 2294 int nr2; 2295 if( cubic_case == 0 ) 2296 nr2 = cv::solveCubic(cv::cvarrToMat(&amat),umat2); 2297 else 2298 nr2 = cv::solveCubic(cv::Mat_<float>(cv::cvarrToMat(&amat)), umat2); 2299 cvFlip(&amat, &amat, 0); 2300 if(nr2 > 0) 2301 std::sort(ar2.begin(), ar2.begin()+nr2, pred_double()); 2302 ar2.resize(nr2); 2303 2304 int nr1 = 0; 2305 for(int j = 0; j < n; j++) 2306 if( fabs(r[j].imag()) < DBL_EPSILON ) 2307 ar1[nr1++] = r[j].real(); 2308 2309 pass = pass && nr1 == nr2; 2310 if( nr2 > 0 ) 2311 { 2312 div = s = 0; 2313 for(int j = 0; j < nr1; j++) 2314 { 2315 s += fabs(ar1[j]); 2316 div += fabs(ar1[j] - ar2[j]); 2317 } 2318 div /= s; 2319 pass = pass && div < err_eps; 2320 } 2321 } 2322 2323 div = s = 0; 2324 for (int j = 0; j < n; ++j) 2325 { 2326 s += fabs(r[j].real()) + fabs(r[j].imag()); 2327 div += sqrt(pow(r[j].real() - ar[j].real(), 2) + pow(r[j].imag() - ar[j].imag(), 2)); 2328 } 2329 div /= s; 2330 pass = pass && div < err_eps; 2331 } 2332 2333 if (!pass) 2334 { 2335 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); 2336 ts->printf( cvtest::TS::LOG, "too big diff = %g\n", div ); 2337 2338 for (size_t j=0;j<ar2.size();++j) 2339 ts->printf( cvtest::TS::LOG, "ar2[%d]=%g\n", j, ar2[j]); 2340 ts->printf(cvtest::TS::LOG, "\n"); 2341 2342 for (size_t j=0;j<r.size();++j) 2343 ts->printf( cvtest::TS::LOG, "r[%d]=(%g, %g)\n", j, r[j].real(), r[j].imag()); 2344 ts->printf( cvtest::TS::LOG, "\n" ); 2345 for (size_t j=0;j<ar.size();++j) 2346 ts->printf( cvtest::TS::LOG, "ar[%d]=(%g, %g)\n", j, ar[j].real(), ar[j].imag()); 2347 break; 2348 } 2349 } 2350 } 2351 2352 class Core_PhaseTest : public cvtest::BaseTest 2353 { 2354 public: 2355 Core_PhaseTest() {} 2356 ~Core_PhaseTest() {} 2357 protected: 2358 virtual void run(int) 2359 { 2360 const float maxAngleDiff = 0.5; //in degrees 2361 const int axisCount = 8; 2362 const int dim = theRNG().uniform(1,10); 2363 const float scale = theRNG().uniform(1.f, 100.f); 2364 Mat x(axisCount + 1, dim, CV_32FC1), 2365 y(axisCount + 1, dim, CV_32FC1); 2366 Mat anglesInDegrees(axisCount + 1, dim, CV_32FC1); 2367 2368 // fill the data 2369 x.row(0).setTo(Scalar(0)); 2370 y.row(0).setTo(Scalar(0)); 2371 anglesInDegrees.row(0).setTo(Scalar(0)); 2372 2373 x.row(1).setTo(Scalar(scale)); 2374 y.row(1).setTo(Scalar(0)); 2375 anglesInDegrees.row(1).setTo(Scalar(0)); 2376 2377 x.row(2).setTo(Scalar(scale)); 2378 y.row(2).setTo(Scalar(scale)); 2379 anglesInDegrees.row(2).setTo(Scalar(45)); 2380 2381 x.row(3).setTo(Scalar(0)); 2382 y.row(3).setTo(Scalar(scale)); 2383 anglesInDegrees.row(3).setTo(Scalar(90)); 2384 2385 x.row(4).setTo(Scalar(-scale)); 2386 y.row(4).setTo(Scalar(scale)); 2387 anglesInDegrees.row(4).setTo(Scalar(135)); 2388 2389 x.row(5).setTo(Scalar(-scale)); 2390 y.row(5).setTo(Scalar(0)); 2391 anglesInDegrees.row(5).setTo(Scalar(180)); 2392 2393 x.row(6).setTo(Scalar(-scale)); 2394 y.row(6).setTo(Scalar(-scale)); 2395 anglesInDegrees.row(6).setTo(Scalar(225)); 2396 2397 x.row(7).setTo(Scalar(0)); 2398 y.row(7).setTo(Scalar(-scale)); 2399 anglesInDegrees.row(7).setTo(Scalar(270)); 2400 2401 x.row(8).setTo(Scalar(scale)); 2402 y.row(8).setTo(Scalar(-scale)); 2403 anglesInDegrees.row(8).setTo(Scalar(315)); 2404 2405 Mat resInRad, resInDeg; 2406 phase(x, y, resInRad, false); 2407 phase(x, y, resInDeg, true); 2408 2409 CV_Assert(resInRad.size() == x.size()); 2410 CV_Assert(resInRad.type() == x.type()); 2411 2412 CV_Assert(resInDeg.size() == x.size()); 2413 CV_Assert(resInDeg.type() == x.type()); 2414 2415 // check the result 2416 int outOfRangeCount = countNonZero((resInDeg > 360) | (resInDeg < 0)); 2417 if(outOfRangeCount > 0) 2418 { 2419 ts->printf(cvtest::TS::LOG, "There are result angles that are out of range [0, 360] (part of them is %f)\n", 2420 static_cast<float>(outOfRangeCount)/resInDeg.total()); 2421 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); 2422 } 2423 2424 Mat diff = abs(anglesInDegrees - resInDeg); 2425 size_t errDegCount = diff.total() - countNonZero((diff < maxAngleDiff) | ((360 - diff) < maxAngleDiff)); 2426 if(errDegCount > 0) 2427 { 2428 ts->printf(cvtest::TS::LOG, "There are incorrect result angles (in degrees) (part of them is %f)\n", 2429 static_cast<float>(errDegCount)/resInDeg.total()); 2430 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); 2431 } 2432 2433 Mat convertedRes = resInRad * 180. / CV_PI; 2434 double normDiff = cvtest::norm(convertedRes - resInDeg, NORM_INF); 2435 if(normDiff > FLT_EPSILON * 180.) 2436 { 2437 ts->printf(cvtest::TS::LOG, "There are incorrect result angles (in radians)\n"); 2438 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); 2439 } 2440 2441 ts->set_failed_test_info(cvtest::TS::OK); 2442 } 2443 }; 2444 2445 class Core_CheckRange_Empty : public cvtest::BaseTest 2446 { 2447 public: 2448 Core_CheckRange_Empty(){} 2449 ~Core_CheckRange_Empty(){} 2450 protected: 2451 virtual void run( int start_from ); 2452 }; 2453 2454 void Core_CheckRange_Empty::run( int ) 2455 { 2456 cv::Mat m; 2457 ASSERT_TRUE( cv::checkRange(m) ); 2458 } 2459 2460 TEST(Core_CheckRange_Empty, accuracy) { Core_CheckRange_Empty test; test.safe_run(); } 2461 2462 class Core_CheckRange_INT_MAX : public cvtest::BaseTest 2463 { 2464 public: 2465 Core_CheckRange_INT_MAX(){} 2466 ~Core_CheckRange_INT_MAX(){} 2467 protected: 2468 virtual void run( int start_from ); 2469 }; 2470 2471 void Core_CheckRange_INT_MAX::run( int ) 2472 { 2473 cv::Mat m(3, 3, CV_32SC1, cv::Scalar(INT_MAX)); 2474 ASSERT_FALSE( cv::checkRange(m, true, 0, 0, INT_MAX) ); 2475 ASSERT_TRUE( cv::checkRange(m) ); 2476 } 2477 2478 TEST(Core_CheckRange_INT_MAX, accuracy) { Core_CheckRange_INT_MAX test; test.safe_run(); } 2479 2480 template <typename T> class Core_CheckRange : public testing::Test {}; 2481 2482 TYPED_TEST_CASE_P(Core_CheckRange); 2483 2484 TYPED_TEST_P(Core_CheckRange, Negative) 2485 { 2486 double min_bound = 4.5; 2487 double max_bound = 16.0; 2488 2489 TypeParam data[] = {5, 10, 15, 4, 10, 2, 8, 12, 14}; 2490 cv::Mat src = cv::Mat(3,3, cv::DataDepth<TypeParam>::value, data); 2491 2492 cv::Point bad_pt(0, 0); 2493 2494 ASSERT_FALSE(checkRange(src, true, &bad_pt, min_bound, max_bound)); 2495 ASSERT_EQ(bad_pt.x, 0); 2496 ASSERT_EQ(bad_pt.y, 1); 2497 } 2498 2499 TYPED_TEST_P(Core_CheckRange, Positive) 2500 { 2501 double min_bound = -1; 2502 double max_bound = 16.0; 2503 2504 TypeParam data[] = {5, 10, 15, 4, 10, 2, 8, 12, 14}; 2505 cv::Mat src = cv::Mat(3,3, cv::DataDepth<TypeParam>::value, data); 2506 2507 cv::Point bad_pt(0, 0); 2508 2509 ASSERT_TRUE(checkRange(src, true, &bad_pt, min_bound, max_bound)); 2510 ASSERT_EQ(bad_pt.x, 0); 2511 ASSERT_EQ(bad_pt.y, 0); 2512 } 2513 2514 TYPED_TEST_P(Core_CheckRange, Bounds) 2515 { 2516 double min_bound = 24.5; 2517 double max_bound = 1.0; 2518 2519 TypeParam data[] = {5, 10, 15, 4, 10, 2, 8, 12, 14}; 2520 cv::Mat src = cv::Mat(3,3, cv::DataDepth<TypeParam>::value, data); 2521 2522 cv::Point bad_pt(0, 0); 2523 2524 ASSERT_FALSE(checkRange(src, true, &bad_pt, min_bound, max_bound)); 2525 ASSERT_EQ(bad_pt.x, 0); 2526 ASSERT_EQ(bad_pt.y, 0); 2527 } 2528 2529 TYPED_TEST_P(Core_CheckRange, Zero) 2530 { 2531 double min_bound = 0.0; 2532 double max_bound = 0.1; 2533 2534 cv::Mat src1 = cv::Mat::zeros(3, 3, cv::DataDepth<TypeParam>::value); 2535 2536 int sizes[] = {5, 6, 7}; 2537 cv::Mat src2 = cv::Mat::zeros(3, sizes, cv::DataDepth<TypeParam>::value); 2538 2539 ASSERT_TRUE( checkRange(src1, true, NULL, min_bound, max_bound) ); 2540 ASSERT_TRUE( checkRange(src2, true, NULL, min_bound, max_bound) ); 2541 } 2542 2543 TYPED_TEST_P(Core_CheckRange, One) 2544 { 2545 double min_bound = 1.0; 2546 double max_bound = 1.1; 2547 2548 cv::Mat src1 = cv::Mat::ones(3, 3, cv::DataDepth<TypeParam>::value); 2549 2550 int sizes[] = {5, 6, 7}; 2551 cv::Mat src2 = cv::Mat::ones(3, sizes, cv::DataDepth<TypeParam>::value); 2552 2553 ASSERT_TRUE( checkRange(src1, true, NULL, min_bound, max_bound) ); 2554 ASSERT_TRUE( checkRange(src2, true, NULL, min_bound, max_bound) ); 2555 } 2556 2557 REGISTER_TYPED_TEST_CASE_P(Core_CheckRange, Negative, Positive, Bounds, Zero, One); 2558 2559 typedef ::testing::Types<signed char,unsigned char, signed short, unsigned short, signed int> mat_data_types; 2560 INSTANTIATE_TYPED_TEST_CASE_P(Negative_Test, Core_CheckRange, mat_data_types); 2561 2562 TEST(Core_Invert, small) 2563 { 2564 cv::Mat a = (cv::Mat_<float>(3,3) << 2.42104644730331, 1.81444796521479, -3.98072565304758, 0, 7.08389214348967e-3, 5.55326770986007e-3, 0,0, 7.44556154284261e-3); 2565 //cv::randu(a, -1, 1); 2566 2567 cv::Mat b = a.t()*a; 2568 cv::Mat c, i = Mat_<float>::eye(3, 3); 2569 cv::invert(b, c, cv::DECOMP_LU); //std::cout << b*c << std::endl; 2570 ASSERT_LT( cvtest::norm(b*c, i, CV_C), 0.1 ); 2571 cv::invert(b, c, cv::DECOMP_SVD); //std::cout << b*c << std::endl; 2572 ASSERT_LT( cvtest::norm(b*c, i, CV_C), 0.1 ); 2573 cv::invert(b, c, cv::DECOMP_CHOLESKY); //std::cout << b*c << std::endl; 2574 ASSERT_LT( cvtest::norm(b*c, i, CV_C), 0.1 ); 2575 } 2576 2577 ///////////////////////////////////////////////////////////////////////////////////////////////////// 2578 2579 TEST(Core_CovarMatrix, accuracy) { Core_CovarMatrixTest test; test.safe_run(); } 2580 TEST(Core_CrossProduct, accuracy) { Core_CrossProductTest test; test.safe_run(); } 2581 TEST(Core_Determinant, accuracy) { Core_DetTest test; test.safe_run(); } 2582 TEST(Core_DotProduct, accuracy) { Core_DotProductTest test; test.safe_run(); } 2583 TEST(Core_GEMM, accuracy) { Core_GEMMTest test; test.safe_run(); } 2584 TEST(Core_Invert, accuracy) { Core_InvertTest test; test.safe_run(); } 2585 TEST(Core_Mahalanobis, accuracy) { Core_MahalanobisTest test; test.safe_run(); } 2586 TEST(Core_MulTransposed, accuracy) { Core_MulTransposedTest test; test.safe_run(); } 2587 TEST(Core_Transform, accuracy) { Core_TransformTest test; test.safe_run(); } 2588 TEST(Core_PerspectiveTransform, accuracy) { Core_PerspectiveTransformTest test; test.safe_run(); } 2589 TEST(Core_Pow, accuracy) { Core_PowTest test; test.safe_run(); } 2590 TEST(Core_SolveLinearSystem, accuracy) { Core_SolveTest test; test.safe_run(); } 2591 TEST(Core_SVD, accuracy) { Core_SVDTest test; test.safe_run(); } 2592 TEST(Core_SVBkSb, accuracy) { Core_SVBkSbTest test; test.safe_run(); } 2593 TEST(Core_Trace, accuracy) { Core_TraceTest test; test.safe_run(); } 2594 TEST(Core_SolvePoly, accuracy) { Core_SolvePolyTest test; test.safe_run(); } 2595 TEST(Core_Phase, accuracy) { Core_PhaseTest test; test.safe_run(); } 2596 2597 2598 TEST(Core_SVD, flt) 2599 { 2600 float a[] = { 2601 1.23377746e+011f, -7.05490125e+010f, -4.18380882e+010f, -11693456.f, 2602 -39091328.f, 77492224.f, -7.05490125e+010f, 2.36211143e+011f, 2603 -3.51093473e+010f, 70773408.f, -4.83386156e+005f, -129560368.f, 2604 -4.18380882e+010f, -3.51093473e+010f, 9.25311222e+010f, -49052424.f, 2605 43922752.f, 12176842.f, -11693456.f, 70773408.f, -49052424.f, 8.40836094e+004f, 2606 5.17475293e+003f, -1.16122949e+004f, -39091328.f, -4.83386156e+005f, 2607 43922752.f, 5.17475293e+003f, 5.16047969e+004f, 5.68887842e+003f, 77492224.f, 2608 -129560368.f, 12176842.f, -1.16122949e+004f, 5.68887842e+003f, 2609 1.28060578e+005f 2610 }; 2611 2612 float b[] = { 2613 283751232.f, 2.61604198e+009f, -745033216.f, 2.31125625e+005f, 2614 -4.52429188e+005f, -1.37596525e+006f 2615 }; 2616 2617 Mat A(6, 6, CV_32F, a); 2618 Mat B(6, 1, CV_32F, b); 2619 Mat X, B1; 2620 solve(A, B, X, DECOMP_SVD); 2621 B1 = A*X; 2622 EXPECT_LE(cvtest::norm(B1, B, NORM_L2 + NORM_RELATIVE), FLT_EPSILON*10); 2623 } 2624 2625 2626 // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)), 2627 2628 enum 2629 { 2630 MAT_N_DIM_C1, 2631 MAT_N_1_CDIM, 2632 MAT_1_N_CDIM, 2633 MAT_N_DIM_C1_NONCONT, 2634 MAT_N_1_CDIM_NONCONT, 2635 VECTOR 2636 }; 2637 2638 class CV_KMeansSingularTest : public cvtest::BaseTest 2639 { 2640 public: 2641 CV_KMeansSingularTest() {} 2642 ~CV_KMeansSingularTest() {} 2643 protected: 2644 void run(int inVariant) 2645 { 2646 int i, iter = 0, N = 0, N0 = 0, K = 0, dims = 0; 2647 Mat labels; 2648 try 2649 { 2650 RNG& rng = theRNG(); 2651 const int MAX_DIM=5; 2652 int MAX_POINTS = 100, maxIter = 100; 2653 for( iter = 0; iter < maxIter; iter++ ) 2654 { 2655 ts->update_context(this, iter, true); 2656 dims = rng.uniform(inVariant == MAT_1_N_CDIM ? 2 : 1, MAX_DIM+1); 2657 N = rng.uniform(1, MAX_POINTS+1); 2658 N0 = rng.uniform(1, MAX(N/10, 2)); 2659 K = rng.uniform(1, N+1); 2660 2661 if (inVariant == VECTOR) 2662 { 2663 dims = 2; 2664 2665 std::vector<cv::Point2f> data0(N0); 2666 rng.fill(data0, RNG::UNIFORM, -1, 1); 2667 2668 std::vector<cv::Point2f> data(N); 2669 for( i = 0; i < N; i++ ) 2670 data[i] = data0[rng.uniform(0, N0)]; 2671 2672 kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0), 2673 5, KMEANS_PP_CENTERS); 2674 } 2675 else 2676 { 2677 Mat data0(N0, dims, CV_32F); 2678 rng.fill(data0, RNG::UNIFORM, -1, 1); 2679 2680 Mat data; 2681 2682 switch (inVariant) 2683 { 2684 case MAT_N_DIM_C1: 2685 data.create(N, dims, CV_32F); 2686 for( i = 0; i < N; i++ ) 2687 data0.row(rng.uniform(0, N0)).copyTo(data.row(i)); 2688 break; 2689 2690 case MAT_N_1_CDIM: 2691 data.create(N, 1, CV_32FC(dims)); 2692 for( i = 0; i < N; i++ ) 2693 memcpy(data.ptr(i), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float)); 2694 break; 2695 2696 case MAT_1_N_CDIM: 2697 data.create(1, N, CV_32FC(dims)); 2698 for( i = 0; i < N; i++ ) 2699 memcpy(data.ptr() + i * dims * sizeof(float), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float)); 2700 break; 2701 2702 case MAT_N_DIM_C1_NONCONT: 2703 data.create(N, dims + 5, CV_32F); 2704 data = data(Range(0, N), Range(0, dims)); 2705 for( i = 0; i < N; i++ ) 2706 data0.row(rng.uniform(0, N0)).copyTo(data.row(i)); 2707 break; 2708 2709 case MAT_N_1_CDIM_NONCONT: 2710 data.create(N, 3, CV_32FC(dims)); 2711 data = data.colRange(0, 1); 2712 for( i = 0; i < N; i++ ) 2713 memcpy(data.ptr(i), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float)); 2714 break; 2715 } 2716 2717 kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0), 2718 5, KMEANS_PP_CENTERS); 2719 } 2720 2721 Mat hist(K, 1, CV_32S, Scalar(0)); 2722 for( i = 0; i < N; i++ ) 2723 { 2724 int l = labels.at<int>(i); 2725 CV_Assert(0 <= l && l < K); 2726 hist.at<int>(l)++; 2727 } 2728 for( i = 0; i < K; i++ ) 2729 CV_Assert( hist.at<int>(i) != 0 ); 2730 } 2731 } 2732 catch(...) 2733 { 2734 ts->printf(cvtest::TS::LOG, 2735 "context: iteration=%d, N=%d, N0=%d, K=%d\n", 2736 iter, N, N0, K); 2737 std::cout << labels << std::endl; 2738 ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); 2739 } 2740 } 2741 }; 2742 2743 TEST(Core_KMeans, singular) { CV_KMeansSingularTest test; test.safe_run(MAT_N_DIM_C1); } 2744 2745 CV_ENUM(KMeansInputVariant, MAT_N_DIM_C1, MAT_N_1_CDIM, MAT_1_N_CDIM, MAT_N_DIM_C1_NONCONT, MAT_N_1_CDIM_NONCONT, VECTOR) 2746 2747 typedef testing::TestWithParam<KMeansInputVariant> Core_KMeans_InputVariants; 2748 2749 TEST_P(Core_KMeans_InputVariants, singular) 2750 { 2751 CV_KMeansSingularTest test; 2752 test.safe_run(GetParam()); 2753 } 2754 2755 INSTANTIATE_TEST_CASE_P(AllVariants, Core_KMeans_InputVariants, KMeansInputVariant::all()); 2756 2757 TEST(CovariationMatrixVectorOfMat, accuracy) 2758 { 2759 unsigned int col_problem_size = 8, row_problem_size = 8, vector_size = 16; 2760 cv::Mat src(vector_size, col_problem_size * row_problem_size, CV_32F); 2761 int singleMatFlags = CV_COVAR_ROWS; 2762 2763 cv::Mat gold; 2764 cv::Mat goldMean; 2765 cv::randu(src,cv::Scalar(-128), cv::Scalar(128)); 2766 cv::calcCovarMatrix(src,gold,goldMean,singleMatFlags,CV_32F); 2767 std::vector<cv::Mat> srcVec; 2768 for(size_t i = 0; i < vector_size; i++) 2769 { 2770 srcVec.push_back(src.row(static_cast<int>(i)).reshape(0,col_problem_size)); 2771 } 2772 2773 cv::Mat actual; 2774 cv::Mat actualMean; 2775 cv::calcCovarMatrix(srcVec, actual, actualMean,singleMatFlags,CV_32F); 2776 2777 cv::Mat diff; 2778 cv::absdiff(gold, actual, diff); 2779 cv::Scalar s = cv::sum(diff); 2780 ASSERT_EQ(s.dot(s), 0.0); 2781 2782 cv::Mat meanDiff; 2783 cv::absdiff(goldMean, actualMean.reshape(0,1), meanDiff); 2784 cv::Scalar sDiff = cv::sum(meanDiff); 2785 ASSERT_EQ(sDiff.dot(sDiff), 0.0); 2786 } 2787 2788 TEST(CovariationMatrixVectorOfMatWithMean, accuracy) 2789 { 2790 unsigned int col_problem_size = 8, row_problem_size = 8, vector_size = 16; 2791 cv::Mat src(vector_size, col_problem_size * row_problem_size, CV_32F); 2792 int singleMatFlags = CV_COVAR_ROWS | CV_COVAR_USE_AVG; 2793 2794 cv::Mat gold; 2795 cv::randu(src,cv::Scalar(-128), cv::Scalar(128)); 2796 cv::Mat goldMean; 2797 2798 cv::reduce(src,goldMean,0 ,CV_REDUCE_AVG, CV_32F); 2799 2800 cv::calcCovarMatrix(src,gold,goldMean,singleMatFlags,CV_32F); 2801 2802 std::vector<cv::Mat> srcVec; 2803 for(size_t i = 0; i < vector_size; i++) 2804 { 2805 srcVec.push_back(src.row(static_cast<int>(i)).reshape(0,col_problem_size)); 2806 } 2807 2808 cv::Mat actual; 2809 cv::Mat actualMean = goldMean.reshape(0, row_problem_size); 2810 cv::calcCovarMatrix(srcVec, actual, actualMean,singleMatFlags,CV_32F); 2811 2812 cv::Mat diff; 2813 cv::absdiff(gold, actual, diff); 2814 cv::Scalar s = cv::sum(diff); 2815 ASSERT_EQ(s.dot(s), 0.0); 2816 2817 cv::Mat meanDiff; 2818 cv::absdiff(goldMean, actualMean.reshape(0,1), meanDiff); 2819 cv::Scalar sDiff = cv::sum(meanDiff); 2820 ASSERT_EQ(sDiff.dot(sDiff), 0.0); 2821 } 2822 2823 TEST(Core_Pow, special) 2824 { 2825 for( int i = 0; i < 100; i++ ) 2826 { 2827 int n = theRNG().uniform(1, 30); 2828 Mat mtx0(1, n, CV_8S), mtx, result; 2829 randu(mtx0, -5, 5); 2830 2831 int type = theRNG().uniform(0, 2) ? CV_64F : CV_32F; 2832 double eps = type == CV_32F ? 1e-3 : 1e-10; 2833 mtx0.convertTo(mtx, type); 2834 // generate power from [-n, n] interval with 1/8 step - enough to check various cases. 2835 const int max_pf = 3; 2836 int pf = theRNG().uniform(0, max_pf*2+1); 2837 double power = ((1 << pf) - (1 << (max_pf*2-1)))/16.; 2838 int ipower = cvRound(power); 2839 bool is_ipower = ipower == power; 2840 cv::pow(mtx, power, result); 2841 for( int j = 0; j < n; j++ ) 2842 { 2843 double val = type == CV_32F ? (double)mtx.at<float>(j) : mtx.at<double>(j); 2844 double r = type == CV_32F ? (double)result.at<float>(j) : result.at<double>(j); 2845 double r0; 2846 if( power == 0. ) 2847 r0 = 1; 2848 else if( is_ipower ) 2849 { 2850 r0 = 1; 2851 for( int k = 0; k < std::abs(ipower); k++ ) 2852 r0 *= val; 2853 if( ipower < 0 ) 2854 r0 = 1./r0; 2855 } 2856 else 2857 r0 = std::pow(val, power); 2858 if( cvIsInf(r0) ) 2859 { 2860 ASSERT_TRUE(cvIsInf(r) != 0); 2861 } 2862 else if( cvIsNaN(r0) ) 2863 { 2864 ASSERT_TRUE(cvIsNaN(r) != 0); 2865 } 2866 else 2867 { 2868 ASSERT_TRUE(cvIsInf(r) == 0 && cvIsNaN(r) == 0); 2869 ASSERT_LT(fabs(r - r0), eps); 2870 } 2871 } 2872 } 2873 } 2874 2875 /* End of file. */ 2876