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 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2000, Intel Corporation, all rights reserved. 14 // Third party copyrights are property of their respective owners. 15 // 16 // Redistribution and use in source and binary forms, with or without modification, 17 // are permitted provided that the following conditions are met: 18 // 19 // * Redistribution's of source code must retain the above copyright notice, 20 // this list of conditions and the following disclaimer. 21 // 22 // * Redistribution's in binary form must reproduce the above copyright notice, 23 // this list of conditions and the following disclaimer in the documentation 24 // and/or other materials provided with the distribution. 25 // 26 // * The name of Intel Corporation may not be used to endorse or promote products 27 // derived from this software without specific prior written permission. 28 // 29 // This software is provided by the copyright holders and contributors "as is" and 30 // any express or implied warranties, including, but not limited to, the implied 31 // warranties of merchantability and fitness for a particular purpose are disclaimed. 32 // In no event shall the Intel Corporation or contributors be liable for any direct, 33 // indirect, incidental, special, exemplary, or consequential damages 34 // (including, but not limited to, procurement of substitute goods or services; 35 // loss of use, data, or profits; or business interruption) however caused 36 // and on any theory of liability, whether in contract, strict liability, 37 // or tort (including negligence or otherwise) arising in any way out of 38 // the use of this software, even if advised of the possibility of such damage. 39 // 40 //M*/ 41 42 #include "test_precomp.hpp" 43 44 using namespace cv; 45 using namespace std; 46 47 class CV_FilterBaseTest : public cvtest::ArrayTest 48 { 49 public: 50 CV_FilterBaseTest( bool _fp_kernel ); 51 52 protected: 53 int prepare_test_case( int test_case_idx ); 54 int read_params( CvFileStorage* fs ); 55 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 56 void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high ); 57 CvSize aperture_size; 58 CvPoint anchor; 59 int max_aperture_size; 60 bool fp_kernel; 61 bool inplace; 62 int border; 63 }; 64 65 66 CV_FilterBaseTest::CV_FilterBaseTest( bool _fp_kernel ) : fp_kernel(_fp_kernel) 67 { 68 test_array[INPUT].push_back(NULL); 69 test_array[INPUT].push_back(NULL); 70 test_array[OUTPUT].push_back(NULL); 71 test_array[REF_OUTPUT].push_back(NULL); 72 max_aperture_size = 13; 73 inplace = false; 74 aperture_size = cvSize(0,0); 75 anchor = cvPoint(0,0); 76 element_wise_relative_error = false; 77 } 78 79 80 int CV_FilterBaseTest::read_params( CvFileStorage* fs ) 81 { 82 int code = cvtest::ArrayTest::read_params( fs ); 83 if( code < 0 ) 84 return code; 85 86 max_aperture_size = cvReadInt( find_param( fs, "max_aperture_size" ), max_aperture_size ); 87 max_aperture_size = cvtest::clipInt( max_aperture_size, 1, 100 ); 88 89 return code; 90 } 91 92 93 void CV_FilterBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high ) 94 { 95 cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high ); 96 if( i == INPUT ) 97 { 98 if( j == 1 ) 99 { 100 if( fp_kernel ) 101 { 102 RNG& rng = ts->get_rng(); 103 double val = exp( cvtest::randReal(rng)*10 - 4 ); 104 low = Scalar::all(-val); 105 high = Scalar::all(val); 106 } 107 else 108 { 109 low = Scalar::all(0); 110 high = Scalar::all(2); 111 } 112 } 113 else if( CV_MAT_DEPTH(type) == CV_16U ) 114 { 115 low = Scalar::all(0.); 116 high = Scalar::all(40000.); 117 } 118 else if( CV_MAT_DEPTH(type) == CV_32F ) 119 { 120 low = Scalar::all(-10.); 121 high = Scalar::all(10.); 122 } 123 } 124 } 125 126 127 void CV_FilterBaseTest::get_test_array_types_and_sizes( int test_case_idx, 128 vector<vector<Size> >& sizes, 129 vector<vector<int> >& types ) 130 { 131 RNG& rng = ts->get_rng(); 132 int depth = cvtest::randInt(rng) % CV_32F; 133 int cn = cvtest::randInt(rng) % 3 + 1; 134 cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 135 depth += depth == CV_8S; 136 cn += cn == 2; 137 138 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn); 139 140 aperture_size.width = cvtest::randInt(rng) % max_aperture_size + 1; 141 aperture_size.height = cvtest::randInt(rng) % max_aperture_size + 1; 142 anchor.x = cvtest::randInt(rng) % aperture_size.width; 143 anchor.y = cvtest::randInt(rng) % aperture_size.height; 144 145 types[INPUT][1] = fp_kernel ? CV_32FC1 : CV_8UC1; 146 sizes[INPUT][1] = aperture_size; 147 148 inplace = cvtest::randInt(rng) % 2 != 0; 149 border = BORDER_REPLICATE; 150 } 151 152 153 int CV_FilterBaseTest::prepare_test_case( int test_case_idx ) 154 { 155 int code = cvtest::ArrayTest::prepare_test_case( test_case_idx ); 156 if( code > 0 ) 157 { 158 if( inplace && test_mat[INPUT][0].type() == test_mat[OUTPUT][0].type()) 159 cvtest::copy( test_mat[INPUT][0], test_mat[OUTPUT][0] ); 160 else 161 inplace = false; 162 } 163 return code; 164 } 165 166 167 ///////////////////////// 168 169 class CV_MorphologyBaseTest : public CV_FilterBaseTest 170 { 171 public: 172 CV_MorphologyBaseTest(); 173 174 protected: 175 void prepare_to_validation( int test_case_idx ); 176 int prepare_test_case( int test_case_idx ); 177 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 178 double get_success_error_level( int test_case_idx, int i, int j ); 179 int optype, optype_min, optype_max; 180 int shape; 181 IplConvKernel* element; 182 }; 183 184 185 CV_MorphologyBaseTest::CV_MorphologyBaseTest() : CV_FilterBaseTest( false ) 186 { 187 shape = -1; 188 element = 0; 189 optype = optype_min = optype_max = -1; 190 } 191 192 193 void CV_MorphologyBaseTest::get_test_array_types_and_sizes( int test_case_idx, 194 vector<vector<Size> >& sizes, vector<vector<int> >& types ) 195 { 196 RNG& rng = ts->get_rng(); 197 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 198 int depth = cvtest::randInt(rng) % 4; 199 depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : depth == 2 ? CV_16S : CV_32F; 200 int cn = CV_MAT_CN(types[INPUT][0]); 201 202 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn); 203 shape = cvtest::randInt(rng) % 4; 204 if( shape >= 3 ) 205 shape = CV_SHAPE_CUSTOM; 206 else 207 sizes[INPUT][1] = cvSize(0,0); 208 optype = cvtest::randInt(rng) % (optype_max - optype_min + 1) + optype_min; 209 } 210 211 212 double CV_MorphologyBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 213 { 214 return test_mat[INPUT][0].depth() < CV_32F || 215 (optype == CV_MOP_ERODE || optype == CV_MOP_DILATE || 216 optype == CV_MOP_OPEN || optype == CV_MOP_CLOSE) ? 0 : 1e-5; 217 } 218 219 220 int CV_MorphologyBaseTest::prepare_test_case( int test_case_idx ) 221 { 222 int code = CV_FilterBaseTest::prepare_test_case( test_case_idx ); 223 vector<int> eldata; 224 225 if( code <= 0 ) 226 return code; 227 228 if( shape == CV_SHAPE_CUSTOM ) 229 { 230 eldata.resize(aperture_size.width*aperture_size.height); 231 const uchar* src = test_mat[INPUT][1].ptr(); 232 int srcstep = (int)test_mat[INPUT][1].step; 233 int i, j, nonzero = 0; 234 235 for( i = 0; i < aperture_size.height; i++ ) 236 { 237 for( j = 0; j < aperture_size.width; j++ ) 238 { 239 eldata[i*aperture_size.width + j] = src[i*srcstep + j]; 240 nonzero += src[i*srcstep + j] != 0; 241 } 242 } 243 244 if( nonzero == 0 ) 245 eldata[anchor.y*aperture_size.width + anchor.x] = 1; 246 } 247 248 cvReleaseStructuringElement( &element ); 249 element = cvCreateStructuringElementEx( aperture_size.width, aperture_size.height, 250 anchor.x, anchor.y, shape, eldata.empty() ? 0 : &eldata[0] ); 251 return code; 252 } 253 254 255 void CV_MorphologyBaseTest::prepare_to_validation( int /*test_case_idx*/ ) 256 { 257 Mat& src = test_mat[INPUT][0], &dst = test_mat[REF_OUTPUT][0]; 258 Mat _ielement(element->nRows, element->nCols, CV_32S, element->values); 259 Mat _element; 260 _ielement.convertTo(_element, CV_8U); 261 Point _anchor(element->anchorX, element->anchorY); 262 int _border = BORDER_REPLICATE; 263 264 if( optype == CV_MOP_ERODE ) 265 { 266 cvtest::erode( src, dst, _element, _anchor, _border ); 267 } 268 else if( optype == CV_MOP_DILATE ) 269 { 270 cvtest::dilate( src, dst, _element, _anchor, _border ); 271 } 272 else 273 { 274 Mat temp; 275 if( optype == CV_MOP_OPEN ) 276 { 277 cvtest::erode( src, temp, _element, _anchor, _border ); 278 cvtest::dilate( temp, dst, _element, _anchor, _border ); 279 } 280 else if( optype == CV_MOP_CLOSE ) 281 { 282 cvtest::dilate( src, temp, _element, _anchor, _border ); 283 cvtest::erode( temp, dst, _element, _anchor, _border ); 284 } 285 else if( optype == CV_MOP_GRADIENT ) 286 { 287 cvtest::erode( src, temp, _element, _anchor, _border ); 288 cvtest::dilate( src, dst, _element, _anchor, _border ); 289 cvtest::add( dst, 1, temp, -1, Scalar::all(0), dst, dst.type() ); 290 } 291 else if( optype == CV_MOP_TOPHAT ) 292 { 293 cvtest::erode( src, temp, _element, _anchor, _border ); 294 cvtest::dilate( temp, dst, _element, _anchor, _border ); 295 cvtest::add( src, 1, dst, -1, Scalar::all(0), dst, dst.type() ); 296 } 297 else if( optype == CV_MOP_BLACKHAT ) 298 { 299 cvtest::dilate( src, temp, _element, _anchor, _border ); 300 cvtest::erode( temp, dst, _element, _anchor, _border ); 301 cvtest::add( dst, 1, src, -1, Scalar::all(0), dst, dst.type() ); 302 } 303 else 304 CV_Error( CV_StsBadArg, "Unknown operation" ); 305 } 306 307 cvReleaseStructuringElement( &element ); 308 } 309 310 311 /////////////// erode /////////////// 312 313 class CV_ErodeTest : public CV_MorphologyBaseTest 314 { 315 public: 316 CV_ErodeTest(); 317 protected: 318 void run_func(); 319 }; 320 321 322 CV_ErodeTest::CV_ErodeTest() 323 { 324 optype_min = optype_max = CV_MOP_ERODE; 325 } 326 327 328 void CV_ErodeTest::run_func() 329 { 330 cvErode( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0], 331 test_array[OUTPUT][0], element, 1 ); 332 } 333 334 335 /////////////// dilate /////////////// 336 337 class CV_DilateTest : public CV_MorphologyBaseTest 338 { 339 public: 340 CV_DilateTest(); 341 protected: 342 void run_func(); 343 }; 344 345 346 CV_DilateTest::CV_DilateTest() 347 { 348 optype_min = optype_max = CV_MOP_DILATE; 349 } 350 351 352 void CV_DilateTest::run_func() 353 { 354 cvDilate( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0], 355 test_array[OUTPUT][0], element, 1 ); 356 } 357 358 /////////////// morphEx /////////////// 359 360 class CV_MorphExTest : public CV_MorphologyBaseTest 361 { 362 public: 363 CV_MorphExTest(); 364 protected: 365 void run_func(); 366 }; 367 368 369 CV_MorphExTest::CV_MorphExTest() 370 { 371 optype_min = CV_MOP_ERODE; 372 optype_max = CV_MOP_BLACKHAT; 373 } 374 375 376 void CV_MorphExTest::run_func() 377 { 378 cvMorphologyEx( test_array[inplace ? OUTPUT : INPUT][0], 379 test_array[OUTPUT][0], 0, element, optype, 1 ); 380 } 381 382 /////////////// generic filter /////////////// 383 384 class CV_FilterTest : public CV_FilterBaseTest 385 { 386 public: 387 CV_FilterTest(); 388 389 protected: 390 void prepare_to_validation( int test_case_idx ); 391 void run_func(); 392 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 393 double get_success_error_level( int test_case_idx, int i, int j ); 394 }; 395 396 397 CV_FilterTest::CV_FilterTest() : CV_FilterBaseTest( true ) 398 { 399 } 400 401 402 void CV_FilterTest::get_test_array_types_and_sizes( int test_case_idx, 403 vector<vector<Size> >& sizes, vector<vector<int> >& types ) 404 { 405 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 406 RNG& rng = ts->get_rng(); 407 int depth = cvtest::randInt(rng)%3; 408 int cn = CV_MAT_CN(types[INPUT][0]); 409 depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : CV_32F; 410 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn); 411 } 412 413 414 double CV_FilterTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 415 { 416 int depth = test_mat[INPUT][0].depth(); 417 return depth <= CV_8S ? 2 : depth <= CV_32S ? 32 : 418 depth == CV_32F ? 1e-4 : 1e-10; 419 } 420 421 422 void CV_FilterTest::run_func() 423 { 424 CvMat kernel = test_mat[INPUT][1]; 425 cvFilter2D( test_array[inplace ? OUTPUT : INPUT][0], 426 test_array[OUTPUT][0], &kernel, anchor ); 427 } 428 429 430 void CV_FilterTest::prepare_to_validation( int /*test_case_idx*/ ) 431 { 432 cvtest::filter2D( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].type(), 433 test_mat[INPUT][1], anchor, 0, BORDER_REPLICATE ); 434 } 435 436 437 //////////////////////// 438 439 class CV_DerivBaseTest : public CV_FilterBaseTest 440 { 441 public: 442 CV_DerivBaseTest(); 443 protected: 444 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 445 double get_success_error_level( int test_case_idx, int i, int j ); 446 int _aperture_size; 447 }; 448 449 450 CV_DerivBaseTest::CV_DerivBaseTest() : CV_FilterBaseTest( true ) 451 { 452 max_aperture_size = 7; 453 } 454 455 456 void CV_DerivBaseTest::get_test_array_types_and_sizes( int test_case_idx, 457 vector<vector<Size> >& sizes, vector<vector<int> >& types ) 458 { 459 RNG& rng = ts->get_rng(); 460 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 461 int depth = cvtest::randInt(rng) % 2; 462 depth = depth == 0 ? CV_8U : CV_32F; 463 types[INPUT][0] = CV_MAKETYPE(depth,1); 464 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth==CV_8U?CV_16S:CV_32F,1); 465 _aperture_size = (cvtest::randInt(rng)%5)*2 - 1; 466 sizes[INPUT][1] = aperture_size = cvSize(_aperture_size, _aperture_size); 467 } 468 469 470 double CV_DerivBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 471 { 472 int depth = test_mat[INPUT][0].depth(); 473 return depth <= CV_8S ? 2 : 5e-4; 474 } 475 476 477 /////////////// sobel /////////////// 478 479 class CV_SobelTest : public CV_DerivBaseTest 480 { 481 public: 482 CV_SobelTest(); 483 484 protected: 485 void prepare_to_validation( int test_case_idx ); 486 void run_func(); 487 void get_test_array_types_and_sizes( int test_case_idx, 488 vector<vector<Size> >& sizes, vector<vector<int> >& types ); 489 int dx, dy, origin; 490 }; 491 492 493 CV_SobelTest::CV_SobelTest() {} 494 495 496 void CV_SobelTest::get_test_array_types_and_sizes( int test_case_idx, 497 vector<vector<Size> >& sizes, 498 vector<vector<int> >& types ) 499 { 500 RNG& rng = ts->get_rng(); 501 CV_DerivBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 502 int max_d = _aperture_size > 0 ? 2 : 1; 503 origin = cvtest::randInt(rng) % 2; 504 dx = cvtest::randInt(rng) % (max_d + 1); 505 dy = cvtest::randInt(rng) % (max_d + 1 - dx); 506 if( dx == 0 && dy == 0 ) 507 dx = 1; 508 if( cvtest::randInt(rng) % 2 ) 509 { 510 int t; 511 CV_SWAP( dx, dy, t ); 512 } 513 514 if( _aperture_size < 0 ) 515 aperture_size = cvSize(3, 3); 516 else if( _aperture_size == 1 ) 517 { 518 if( dx == 0 ) 519 aperture_size = cvSize(1, 3); 520 else if( dy == 0 ) 521 aperture_size = cvSize(3, 1); 522 else 523 { 524 _aperture_size = 3; 525 aperture_size = cvSize(3, 3); 526 } 527 } 528 else 529 aperture_size = cvSize(_aperture_size, _aperture_size); 530 531 sizes[INPUT][1] = aperture_size; 532 anchor.x = aperture_size.width / 2; 533 anchor.y = aperture_size.height / 2; 534 } 535 536 537 void CV_SobelTest::run_func() 538 { 539 cvSobel( test_array[inplace ? OUTPUT : INPUT][0], 540 test_array[OUTPUT][0], dx, dy, _aperture_size ); 541 /*cv::Sobel( test_mat[inplace ? OUTPUT : INPUT][0], 542 test_mat[OUTPUT][0], test_mat[OUTPUT][0].depth(), 543 dx, dy, _aperture_size, 1, 0, border );*/ 544 } 545 546 547 void CV_SobelTest::prepare_to_validation( int /*test_case_idx*/ ) 548 { 549 Mat kernel = cvtest::calcSobelKernel2D( dx, dy, _aperture_size, 0 ); 550 cvtest::filter2D( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].depth(), 551 kernel, anchor, 0, BORDER_REPLICATE); 552 } 553 554 555 /////////////// laplace /////////////// 556 557 class CV_LaplaceTest : public CV_DerivBaseTest 558 { 559 public: 560 CV_LaplaceTest(); 561 562 protected: 563 int prepare_test_case( int test_case_idx ); 564 void prepare_to_validation( int test_case_idx ); 565 void run_func(); 566 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 567 }; 568 569 570 CV_LaplaceTest::CV_LaplaceTest() 571 { 572 } 573 574 575 void CV_LaplaceTest::get_test_array_types_and_sizes( int test_case_idx, 576 vector<vector<Size> >& sizes, vector<vector<int> >& types ) 577 { 578 CV_DerivBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 579 if( _aperture_size <= 1 ) 580 { 581 if( _aperture_size < 0 ) 582 _aperture_size = 1; 583 aperture_size = cvSize(3, 3); 584 } 585 else 586 aperture_size = cvSize(_aperture_size, _aperture_size); 587 588 sizes[INPUT][1] = aperture_size; 589 anchor.x = aperture_size.width / 2; 590 anchor.y = aperture_size.height / 2; 591 } 592 593 594 void CV_LaplaceTest::run_func() 595 { 596 cvLaplace( test_array[inplace ? OUTPUT : INPUT][0], 597 test_array[OUTPUT][0], _aperture_size ); 598 } 599 600 601 int CV_LaplaceTest::prepare_test_case( int test_case_idx ) 602 { 603 int code = CV_DerivBaseTest::prepare_test_case( test_case_idx ); 604 return _aperture_size < 0 ? 0 : code; 605 } 606 607 608 void CV_LaplaceTest::prepare_to_validation( int /*test_case_idx*/ ) 609 { 610 Mat kernel = cvtest::calcLaplaceKernel2D( _aperture_size ); 611 cvtest::filter2D( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].depth(), 612 kernel, anchor, 0, BORDER_REPLICATE ); 613 } 614 615 616 //////////////////////////////////////////////////////////// 617 618 class CV_SmoothBaseTest : public CV_FilterBaseTest 619 { 620 public: 621 CV_SmoothBaseTest(); 622 623 protected: 624 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 625 double get_success_error_level( int test_case_idx, int i, int j ); 626 const char* smooth_type; 627 }; 628 629 630 CV_SmoothBaseTest::CV_SmoothBaseTest() : CV_FilterBaseTest( true ) 631 { 632 smooth_type = ""; 633 } 634 635 636 void CV_SmoothBaseTest::get_test_array_types_and_sizes( int test_case_idx, 637 vector<vector<Size> >& sizes, vector<vector<int> >& types ) 638 { 639 RNG& rng = ts->get_rng(); 640 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 641 int depth = cvtest::randInt(rng) % 2; 642 int cn = CV_MAT_CN(types[INPUT][0]); 643 depth = depth == 0 ? CV_8U : CV_32F; 644 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn); 645 anchor.x = cvtest::randInt(rng)%(max_aperture_size/2+1); 646 anchor.y = cvtest::randInt(rng)%(max_aperture_size/2+1); 647 aperture_size.width = anchor.x*2 + 1; 648 aperture_size.height = anchor.y*2 + 1; 649 sizes[INPUT][1] = aperture_size; 650 } 651 652 653 double CV_SmoothBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 654 { 655 int depth = test_mat[INPUT][0].depth(); 656 return depth <= CV_8S ? 1 : 1e-5; 657 } 658 659 660 /////////////// blur /////////////// 661 662 class CV_BlurTest : public CV_SmoothBaseTest 663 { 664 public: 665 CV_BlurTest(); 666 667 protected: 668 int prepare_test_case( int test_case_idx ); 669 void prepare_to_validation( int test_case_idx ); 670 void run_func(); 671 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 672 bool normalize; 673 }; 674 675 676 CV_BlurTest::CV_BlurTest() 677 { 678 } 679 680 681 void CV_BlurTest::get_test_array_types_and_sizes( int test_case_idx, 682 vector<vector<Size> >& sizes, vector<vector<int> >& types ) 683 { 684 RNG& rng = ts->get_rng(); 685 CV_SmoothBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 686 int depth = cvtest::randInt(rng) % 4; 687 int cn = (cvtest::randInt(rng) % 4) + 1; 688 depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : depth == 2 ? CV_16S : CV_32F; 689 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][0] = CV_MAKETYPE(depth, cn); 690 normalize = cvtest::randInt(rng) % 2 != 0; 691 if( !normalize ) 692 { 693 types[INPUT][0] = CV_MAKETYPE(depth, 1); 694 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth==CV_8U?CV_16S:CV_32F,1); 695 } 696 } 697 698 699 void CV_BlurTest::run_func() 700 { 701 cvSmooth( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0], 702 test_array[OUTPUT][0], normalize ? CV_BLUR : CV_BLUR_NO_SCALE, 703 aperture_size.width, aperture_size.height ); 704 } 705 706 707 int CV_BlurTest::prepare_test_case( int test_case_idx ) 708 { 709 int code = CV_SmoothBaseTest::prepare_test_case( test_case_idx ); 710 return code > 0 && !normalize && test_mat[INPUT][0].channels() > 1 ? 0 : code; 711 } 712 713 714 void CV_BlurTest::prepare_to_validation( int /*test_case_idx*/ ) 715 { 716 Mat kernel(aperture_size, CV_64F); 717 kernel.setTo(Scalar::all(normalize ? 1./(aperture_size.width*aperture_size.height) : 1.)); 718 cvtest::filter2D( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].depth(), 719 kernel, anchor, 0, BORDER_REPLICATE ); 720 } 721 722 723 /////////////// gaussian /////////////// 724 725 class CV_GaussianBlurTest : public CV_SmoothBaseTest 726 { 727 public: 728 CV_GaussianBlurTest(); 729 730 protected: 731 void prepare_to_validation( int test_case_idx ); 732 void run_func(); 733 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 734 double get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ); 735 double sigma; 736 int param1, param2; 737 }; 738 739 740 CV_GaussianBlurTest::CV_GaussianBlurTest() : CV_SmoothBaseTest() 741 { 742 sigma = 0.; 743 smooth_type = "Gaussian"; 744 } 745 746 747 double CV_GaussianBlurTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 748 { 749 int depth = test_mat[INPUT][0].depth(); 750 return depth <= CV_8S ? 8 : 1e-5; 751 } 752 753 754 void CV_GaussianBlurTest::get_test_array_types_and_sizes( int test_case_idx, 755 vector<vector<Size> >& sizes, vector<vector<int> >& types ) 756 { 757 RNG& rng = ts->get_rng(); 758 int kernel_case = cvtest::randInt(rng) % 2; 759 CV_SmoothBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 760 anchor = cvPoint(aperture_size.width/2,aperture_size.height/2); 761 762 sigma = exp(cvtest::randReal(rng)*5-2); 763 param1 = aperture_size.width; 764 param2 = aperture_size.height; 765 766 if( kernel_case == 0 ) 767 sigma = 0.; 768 } 769 770 void CV_GaussianBlurTest::run_func() 771 { 772 cvSmooth( test_array[inplace ? OUTPUT : INPUT][0], 773 test_array[OUTPUT][0], CV_GAUSSIAN, 774 param1, param2, sigma, sigma ); 775 } 776 777 778 // !!! Copied from cvSmooth, if the code is changed in cvSmooth, 779 // make sure to update this one too. 780 #define SMALL_GAUSSIAN_SIZE 7 781 static void 782 calcGaussianKernel( int n, double sigma, vector<float>& kernel ) 783 { 784 static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] = 785 { 786 {1.f}, 787 {0.25f, 0.5f, 0.25f}, 788 {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f}, 789 {0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125} 790 }; 791 792 kernel.resize(n); 793 if( n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 ) 794 { 795 assert( n%2 == 1 ); 796 memcpy( &kernel[0], small_gaussian_tab[n>>1], n*sizeof(kernel[0])); 797 } 798 else 799 { 800 double sigmaX = sigma > 0 ? sigma : (n/2 - 1)*0.3 + 0.8; 801 double scale2X = -0.5/(sigmaX*sigmaX); 802 double sum = 1.; 803 int i; 804 sum = kernel[n/2] = 1.f; 805 806 for( i = 1; i <= n/2; i++ ) 807 { 808 kernel[n/2+i] = kernel[n/2-i] = (float)exp(scale2X*i*i); 809 sum += kernel[n/2+i]*2; 810 } 811 812 sum = 1./sum; 813 for( i = 0; i <= n/2; i++ ) 814 kernel[n/2+i] = kernel[n/2-i] = (float)(kernel[n/2+i]*sum); 815 } 816 } 817 818 819 static Mat calcGaussianKernel2D( Size ksize, double sigma ) 820 { 821 vector<float> kx, ky; 822 Mat kernel(ksize, CV_32F); 823 824 calcGaussianKernel( kernel.cols, sigma, kx ); 825 calcGaussianKernel( kernel.rows, sigma, ky ); 826 827 for( int i = 0; i < kernel.rows; i++ ) 828 for( int j = 0; j < kernel.cols; j++ ) 829 kernel.at<float>(i, j) = kx[j]*ky[i]; 830 return kernel; 831 } 832 833 834 void CV_GaussianBlurTest::prepare_to_validation( int /*test_case_idx*/ ) 835 { 836 Mat kernel = calcGaussianKernel2D( aperture_size, sigma ); 837 cvtest::filter2D( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].depth(), 838 kernel, anchor, 0, border & ~BORDER_ISOLATED ); 839 } 840 841 842 /////////////// median /////////////// 843 844 class CV_MedianBlurTest : public CV_SmoothBaseTest 845 { 846 public: 847 CV_MedianBlurTest(); 848 849 protected: 850 void prepare_to_validation( int test_case_idx ); 851 double get_success_error_level( int test_case_idx, int i, int j ); 852 void run_func(); 853 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 854 }; 855 856 857 CV_MedianBlurTest::CV_MedianBlurTest() 858 { 859 smooth_type = "Median"; 860 } 861 862 863 void CV_MedianBlurTest::get_test_array_types_and_sizes( int test_case_idx, 864 vector<vector<Size> >& sizes, vector<vector<int> >& types ) 865 { 866 CV_SmoothBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 867 int depth = CV_8U; 868 int cn = CV_MAT_CN(types[INPUT][0]); 869 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn); 870 types[INPUT][1] = CV_MAKETYPE(depth,1); 871 872 aperture_size.height = aperture_size.width; 873 anchor.x = anchor.y = aperture_size.width / 2; 874 sizes[INPUT][1] = cvSize(aperture_size.width,aperture_size.height); 875 876 sizes[OUTPUT][0] = sizes[INPUT][0]; 877 sizes[REF_OUTPUT][0] = sizes[INPUT][0]; 878 879 inplace = false; 880 border = BORDER_REPLICATE | BORDER_ISOLATED; 881 } 882 883 884 double CV_MedianBlurTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 885 { 886 return 0; 887 } 888 889 890 void CV_MedianBlurTest::run_func() 891 { 892 cvSmooth( test_array[INPUT][0], test_array[OUTPUT][0], 893 CV_MEDIAN, aperture_size.width ); 894 } 895 896 897 struct median_pair 898 { 899 int col; 900 int val; 901 median_pair() { } 902 median_pair( int _col, int _val ) : col(_col), val(_val) { } 903 }; 904 905 906 static void test_medianFilter( const Mat& src, Mat& dst, int m ) 907 { 908 int i, j, k, l, m2 = m*m, n; 909 vector<int> col_buf(m+1); 910 vector<median_pair> _buf0(m*m+1), _buf1(m*m+1); 911 median_pair *buf0 = &_buf0[0], *buf1 = &_buf1[0]; 912 int step = (int)(src.step/src.elemSize()); 913 914 assert( src.rows == dst.rows + m - 1 && src.cols == dst.cols + m - 1 && 915 src.type() == dst.type() && src.type() == CV_8UC1 ); 916 917 for( i = 0; i < dst.rows; i++ ) 918 { 919 uchar* dst1 = dst.ptr<uchar>(i); 920 for( k = 0; k < m; k++ ) 921 { 922 const uchar* src1 = src.ptr<uchar>(i+k); 923 for( j = 0; j < m-1; j++ ) 924 *buf0++ = median_pair(j, src1[j]); 925 } 926 927 n = m2 - m; 928 buf0 -= n; 929 for( k = n-1; k > 0; k-- ) 930 { 931 int f = 0; 932 for( j = 0; j < k; j++ ) 933 { 934 if( buf0[j].val > buf0[j+1].val ) 935 { 936 median_pair t; 937 CV_SWAP( buf0[j], buf0[j+1], t ); 938 f = 1; 939 } 940 } 941 if( !f ) 942 break; 943 } 944 945 for( j = 0; j < dst.cols; j++ ) 946 { 947 int ins_col = j + m - 1; 948 int del_col = j - 1; 949 const uchar* src1 = src.ptr<uchar>(i) + ins_col; 950 for( k = 0; k < m; k++, src1 += step ) 951 { 952 col_buf[k] = src1[0]; 953 for( l = k-1; l >= 0; l-- ) 954 { 955 int t; 956 if( col_buf[l] < col_buf[l+1] ) 957 break; 958 CV_SWAP( col_buf[l], col_buf[l+1], t ); 959 } 960 } 961 962 col_buf[m] = INT_MAX; 963 964 for( k = 0, l = 0; k < n; ) 965 { 966 if( buf0[k].col == del_col ) 967 k++; 968 else if( buf0[k].val < col_buf[l] ) 969 *buf1++ = buf0[k++]; 970 else 971 { 972 assert( col_buf[l] < INT_MAX ); 973 *buf1++ = median_pair(ins_col,col_buf[l++]); 974 } 975 } 976 977 for( ; l < m; l++ ) 978 *buf1++ = median_pair(ins_col,col_buf[l]); 979 980 if( del_col < 0 ) 981 n += m; 982 buf1 -= n; 983 assert( n == m2 ); 984 dst1[j] = (uchar)buf1[n/2].val; 985 median_pair* tbuf; 986 CV_SWAP( buf0, buf1, tbuf ); 987 } 988 } 989 } 990 991 992 void CV_MedianBlurTest::prepare_to_validation( int /*test_case_idx*/ ) 993 { 994 // CV_SmoothBaseTest::prepare_to_validation( test_case_idx ); 995 const Mat& src0 = test_mat[INPUT][0]; 996 Mat& dst0 = test_mat[REF_OUTPUT][0]; 997 int i, cn = src0.channels(); 998 int m = aperture_size.width; 999 Mat src(src0.rows + m - 1, src0.cols + m - 1, src0.depth()); 1000 Mat dst; 1001 if( cn == 1 ) 1002 dst = dst0; 1003 else 1004 dst.create(src0.size(), src0.depth()); 1005 1006 for( i = 0; i < cn; i++ ) 1007 { 1008 Mat ptr = src0; 1009 if( cn > 1 ) 1010 { 1011 cvtest::extract( src0, dst, i ); 1012 ptr = dst; 1013 } 1014 cvtest::copyMakeBorder( ptr, src, m/2, m/2, m/2, m/2, border & ~BORDER_ISOLATED ); 1015 test_medianFilter( src, dst, m ); 1016 if( cn > 1 ) 1017 cvtest::insert( dst, dst0, i ); 1018 } 1019 } 1020 1021 1022 /////////////// pyramid tests /////////////// 1023 1024 class CV_PyramidBaseTest : public CV_FilterBaseTest 1025 { 1026 public: 1027 CV_PyramidBaseTest( bool downsample ); 1028 1029 protected: 1030 double get_success_error_level( int test_case_idx, int i, int j ); 1031 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 1032 bool downsample; 1033 Mat kernel; 1034 }; 1035 1036 1037 CV_PyramidBaseTest::CV_PyramidBaseTest( bool _downsample ) : CV_FilterBaseTest(true) 1038 { 1039 static float kdata[] = { 1.f, 4.f, 6.f, 4.f, 1.f }; 1040 downsample = _downsample; 1041 Mat kernel1d(1, 5, CV_32F, kdata); 1042 kernel = (kernel1d.t()*kernel1d)*((downsample ? 1 : 4)/256.); 1043 } 1044 1045 1046 double CV_PyramidBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 1047 { 1048 int depth = test_mat[INPUT][0].depth(); 1049 return depth < CV_32F ? 1 : 1e-5; 1050 } 1051 1052 1053 void CV_PyramidBaseTest::get_test_array_types_and_sizes( int test_case_idx, 1054 vector<vector<Size> >& sizes, 1055 vector<vector<int> >& types ) 1056 { 1057 const int channels[] = {1, 3, 4}; 1058 const int depthes[] = {CV_8U, CV_16S, CV_16U, CV_32F}; 1059 1060 RNG& rng = ts->get_rng(); 1061 CvSize sz; 1062 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1063 1064 int depth = depthes[cvtest::randInt(rng) % (sizeof(depthes)/sizeof(depthes[0]))]; 1065 int cn = channels[cvtest::randInt(rng) % (sizeof(channels)/sizeof(channels[0]))]; 1066 1067 aperture_size = cvSize(5,5); 1068 anchor = cvPoint(aperture_size.width/2, aperture_size.height/2); 1069 1070 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn); 1071 1072 sz.width = MAX( sizes[INPUT][0].width/2, 1 ); 1073 sz.height = MAX( sizes[INPUT][0].height/2, 1 ); 1074 1075 if( downsample ) 1076 { 1077 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz; 1078 sz.width *= 2; 1079 sz.height *= 2; 1080 sizes[INPUT][0] = sz; 1081 } 1082 else 1083 { 1084 sizes[INPUT][0] = sz; 1085 sz.width *= 2; 1086 sz.height *= 2; 1087 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz; 1088 } 1089 1090 sizes[INPUT][1] = aperture_size; 1091 inplace = false; 1092 } 1093 1094 1095 /////// pyrdown //////// 1096 1097 class CV_PyramidDownTest : public CV_PyramidBaseTest 1098 { 1099 public: 1100 CV_PyramidDownTest(); 1101 1102 protected: 1103 void run_func(); 1104 void prepare_to_validation( int ); 1105 }; 1106 1107 1108 CV_PyramidDownTest::CV_PyramidDownTest() : CV_PyramidBaseTest( true ) 1109 { 1110 } 1111 1112 1113 void CV_PyramidDownTest::run_func() 1114 { 1115 cvPyrDown( test_array[INPUT][0], test_array[OUTPUT][0], CV_GAUSSIAN_5x5 ); 1116 } 1117 1118 1119 void CV_PyramidDownTest::prepare_to_validation( int /*test_case_idx*/ ) 1120 { 1121 Mat& src = test_mat[INPUT][0], &dst = test_mat[REF_OUTPUT][0]; 1122 Mat temp; 1123 cvtest::filter2D(src, temp, src.depth(), 1124 kernel, Point(kernel.cols/2, kernel.rows/2), 1125 0, BORDER_REFLECT_101); 1126 1127 size_t elem_size = temp.elemSize(); 1128 size_t ncols = dst.cols*elem_size; 1129 1130 for( int i = 0; i < dst.rows; i++ ) 1131 { 1132 const uchar* src_row = temp.ptr(i*2); 1133 uchar* dst_row = dst.ptr(i); 1134 1135 for( size_t j = 0; j < ncols; j += elem_size ) 1136 { 1137 for( size_t k = 0; k < elem_size; k++ ) 1138 dst_row[j+k] = src_row[j*2+k]; 1139 } 1140 } 1141 } 1142 1143 1144 /////// pyrup //////// 1145 1146 class CV_PyramidUpTest : public CV_PyramidBaseTest 1147 { 1148 public: 1149 CV_PyramidUpTest(); 1150 1151 protected: 1152 void run_func(); 1153 void prepare_to_validation( int ); 1154 }; 1155 1156 1157 CV_PyramidUpTest::CV_PyramidUpTest() : CV_PyramidBaseTest( false ) 1158 { 1159 } 1160 1161 1162 void CV_PyramidUpTest::run_func() 1163 { 1164 cvPyrUp( test_array[INPUT][0], test_array[OUTPUT][0], CV_GAUSSIAN_5x5 ); 1165 } 1166 1167 1168 void CV_PyramidUpTest::prepare_to_validation( int /*test_case_idx*/ ) 1169 { 1170 Mat& src = test_mat[INPUT][0], &dst = test_mat[REF_OUTPUT][0]; 1171 Mat temp(dst.size(), dst.type()); 1172 1173 size_t elem_size = src.elemSize(); 1174 size_t ncols = src.cols*elem_size; 1175 1176 for( int i = 0; i < src.rows; i++ ) 1177 { 1178 const uchar* src_row = src.ptr(i); 1179 uchar* dst_row = temp.ptr(i*2); 1180 1181 if( i*2 + 1 < temp.rows ) 1182 memset( temp.ptr(i*2+1), 0, temp.cols*elem_size ); 1183 for( size_t j = 0; j < ncols; j += elem_size ) 1184 { 1185 for( size_t k = 0; k < elem_size; k++ ) 1186 { 1187 dst_row[j*2+k] = src_row[j+k]; 1188 dst_row[j*2+k+elem_size] = 0; 1189 } 1190 } 1191 } 1192 1193 cvtest::filter2D(temp, dst, dst.depth(), 1194 kernel, Point(kernel.cols/2, kernel.rows/2), 1195 0, BORDER_REFLECT_101); 1196 } 1197 1198 1199 //////////////////////// feature selection ////////////////////////// 1200 1201 class CV_FeatureSelBaseTest : public cvtest::ArrayTest 1202 { 1203 public: 1204 CV_FeatureSelBaseTest( int width_factor ); 1205 1206 protected: 1207 int read_params( CvFileStorage* fs ); 1208 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 1209 void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high ); 1210 double get_success_error_level( int test_case_idx, int i, int j ); 1211 int aperture_size, block_size; 1212 int max_aperture_size; 1213 int max_block_size; 1214 int width_factor; 1215 }; 1216 1217 1218 CV_FeatureSelBaseTest::CV_FeatureSelBaseTest( int _width_factor ) 1219 { 1220 max_aperture_size = 7; 1221 max_block_size = 21; 1222 // 1 input, 1 output, temp arrays are allocated in the reference functions 1223 test_array[INPUT].push_back(NULL); 1224 test_array[OUTPUT].push_back(NULL); 1225 test_array[REF_OUTPUT].push_back(NULL); 1226 element_wise_relative_error = false; 1227 width_factor = _width_factor; 1228 } 1229 1230 1231 int CV_FeatureSelBaseTest::read_params( CvFileStorage* fs ) 1232 { 1233 int code = cvtest::BaseTest::read_params( fs ); 1234 if( code < 0 ) 1235 return code; 1236 1237 max_aperture_size = cvReadInt( find_param( fs, "max_aperture_size" ), max_aperture_size ); 1238 max_aperture_size = cvtest::clipInt( max_aperture_size, 1, 9 ); 1239 max_block_size = cvReadInt( find_param( fs, "max_block_size" ), max_block_size ); 1240 max_block_size = cvtest::clipInt( max_aperture_size, 1, 100 ); 1241 1242 return code; 1243 } 1244 1245 1246 double CV_FeatureSelBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 1247 { 1248 int depth = test_mat[INPUT][0].depth(); 1249 return depth <= CV_8S ? 3e-2 : depth == CV_32F ? 1e-3 : 1e-10; 1250 } 1251 1252 1253 void CV_FeatureSelBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high ) 1254 { 1255 cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high ); 1256 if( i == INPUT && CV_MAT_DEPTH(type) == CV_32F ) 1257 { 1258 low = Scalar::all(-10.); 1259 high = Scalar::all(10.); 1260 } 1261 } 1262 1263 1264 void CV_FeatureSelBaseTest::get_test_array_types_and_sizes( int test_case_idx, 1265 vector<vector<Size> >& sizes, vector<vector<int> >& types ) 1266 { 1267 RNG& rng = ts->get_rng(); 1268 cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1269 int depth = cvtest::randInt(rng) % 2, asz; 1270 1271 depth = depth == 0 ? CV_8U : CV_32F; 1272 types[INPUT][0] = depth; 1273 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_32FC1; 1274 1275 aperture_size = (cvtest::randInt(rng) % (max_aperture_size+2) - 1) | 1; 1276 if( aperture_size == 1 ) 1277 aperture_size = 3; 1278 if( depth == CV_8U ) 1279 aperture_size = MIN( aperture_size, 5 ); 1280 block_size = (cvtest::randInt(rng) % max_block_size + 1) | 1; 1281 if( block_size <= 3 ) 1282 block_size = 3; 1283 asz = aperture_size > 0 ? aperture_size : 3; 1284 1285 sizes[INPUT][0].width = MAX( sizes[INPUT][0].width, asz + block_size ); 1286 sizes[INPUT][0].height = MAX( sizes[INPUT][0].height, asz + block_size ); 1287 sizes[OUTPUT][0].height = sizes[REF_OUTPUT][0].height = sizes[INPUT][0].height; 1288 sizes[OUTPUT][0].width = sizes[REF_OUTPUT][0].width = sizes[INPUT][0].width*width_factor; 1289 } 1290 1291 1292 static void 1293 test_cornerEigenValsVecs( const Mat& src, Mat& eigenv, Mat& ocv_eigenv, 1294 int block_size, int _aperture_size, int mode ) 1295 { 1296 int i, j; 1297 int aperture_size = _aperture_size < 0 ? 3 : _aperture_size; 1298 Point anchor( aperture_size/2, aperture_size/2 ); 1299 1300 CV_Assert( src.type() == CV_8UC1 || src.type() == CV_32FC1 ); 1301 CV_Assert( eigenv.type() == CV_32FC1 ); 1302 CV_Assert( src.rows == eigenv.rows && 1303 ((mode > 0 && src.cols == eigenv.cols) || 1304 (mode == 0 && src.cols*6 == eigenv.cols)) ); 1305 1306 int type = src.type(); 1307 int ftype = CV_32FC1; 1308 double kernel_scale = type != ftype ? 1./255 : 1; 1309 1310 Mat dx2, dy2, dxdy(src.size(), CV_32F), kernel; 1311 1312 kernel = cvtest::calcSobelKernel2D( 1, 0, _aperture_size ); 1313 cvtest::filter2D( src, dx2, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE ); 1314 kernel = cvtest::calcSobelKernel2D( 0, 1, _aperture_size ); 1315 cvtest::filter2D( src, dy2, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE ); 1316 1317 double denom = (1 << (aperture_size-1))*block_size; 1318 denom = denom * denom; 1319 if( _aperture_size < 0 ) 1320 denom *= 4; 1321 denom = 1./denom; 1322 1323 for( i = 0; i < src.rows; i++ ) 1324 { 1325 float* dxdyp = dxdy.ptr<float>(i); 1326 float* dx2p = dx2.ptr<float>(i); 1327 float* dy2p = dy2.ptr<float>(i); 1328 1329 for( j = 0; j < src.cols; j++ ) 1330 { 1331 double xval = dx2p[j], yval = dy2p[j]; 1332 dxdyp[j] = (float)(xval*yval*denom); 1333 dx2p[j] = (float)(xval*xval*denom); 1334 dy2p[j] = (float)(yval*yval*denom); 1335 } 1336 } 1337 1338 kernel = Mat::ones(block_size, block_size, CV_32F); 1339 anchor = Point(block_size/2, block_size/2); 1340 1341 cvtest::filter2D( dx2, dx2, ftype, kernel, anchor, 0, BORDER_REPLICATE ); 1342 cvtest::filter2D( dy2, dy2, ftype, kernel, anchor, 0, BORDER_REPLICATE ); 1343 cvtest::filter2D( dxdy, dxdy, ftype, kernel, anchor, 0, BORDER_REPLICATE ); 1344 1345 if( mode == 0 ) 1346 { 1347 for( i = 0; i < src.rows; i++ ) 1348 { 1349 float* eigenvp = eigenv.ptr<float>(i); 1350 float* ocv_eigenvp = ocv_eigenv.ptr<float>(i); 1351 const float* dxdyp = dxdy.ptr<float>(i); 1352 const float* dx2p = dx2.ptr<float>(i); 1353 const float* dy2p = dy2.ptr<float>(i); 1354 1355 for( j = 0; j < src.cols; j++ ) 1356 { 1357 double a = dx2p[j], b = dxdyp[j], c = dy2p[j]; 1358 double d = sqrt((a-c)*(a-c) + 4*b*b); 1359 double l1 = 0.5*(a + c + d); 1360 double l2 = 0.5*(a + c - d); 1361 double x1, y1, x2, y2, s; 1362 1363 if( fabs(a - l1) + fabs(b) >= 1e-3 ) 1364 x1 = b, y1 = l1 - a; 1365 else 1366 x1 = l1 - c, y1 = b; 1367 s = 1./(sqrt(x1*x1+y1*y1)+DBL_EPSILON); 1368 x1 *= s; y1 *= s; 1369 1370 if( fabs(a - l2) + fabs(b) >= 1e-3 ) 1371 x2 = b, y2 = l2 - a; 1372 else 1373 x2 = l2 - c, y2 = b; 1374 s = 1./(sqrt(x2*x2+y2*y2)+DBL_EPSILON); 1375 x2 *= s; y2 *= s; 1376 1377 /* the orientation of eigen vectors might be inversed relative to OpenCV function, 1378 which is normal */ 1379 if( (fabs(x1) >= fabs(y1) && ocv_eigenvp[j*6+2]*x1 < 0) || 1380 (fabs(x1) < fabs(y1) && ocv_eigenvp[j*6+3]*y1 < 0) ) 1381 x1 = -x1, y1 = -y1; 1382 1383 if( (fabs(x2) >= fabs(y2) && ocv_eigenvp[j*6+4]*x2 < 0) || 1384 (fabs(x2) < fabs(y2) && ocv_eigenvp[j*6+5]*y2 < 0) ) 1385 x2 = -x2, y2 = -y2; 1386 1387 eigenvp[j*6] = (float)l1; 1388 eigenvp[j*6+1] = (float)l2; 1389 eigenvp[j*6+2] = (float)x1; 1390 eigenvp[j*6+3] = (float)y1; 1391 eigenvp[j*6+4] = (float)x2; 1392 eigenvp[j*6+5] = (float)y2; 1393 } 1394 } 1395 } 1396 else if( mode == 1 ) 1397 { 1398 for( i = 0; i < src.rows; i++ ) 1399 { 1400 float* eigenvp = eigenv.ptr<float>(i); 1401 const float* dxdyp = dxdy.ptr<float>(i); 1402 const float* dx2p = dx2.ptr<float>(i); 1403 const float* dy2p = dy2.ptr<float>(i); 1404 1405 for( j = 0; j < src.cols; j++ ) 1406 { 1407 double a = dx2p[j], b = dxdyp[j], c = dy2p[j]; 1408 double d = sqrt((a-c)*(a-c) + 4*b*b); 1409 eigenvp[j] = (float)(0.5*(a + c - d)); 1410 } 1411 } 1412 } 1413 } 1414 1415 1416 // min eigenval 1417 class CV_MinEigenValTest : public CV_FeatureSelBaseTest 1418 { 1419 public: 1420 CV_MinEigenValTest(); 1421 1422 protected: 1423 void run_func(); 1424 void prepare_to_validation( int ); 1425 }; 1426 1427 1428 CV_MinEigenValTest::CV_MinEigenValTest() : CV_FeatureSelBaseTest( 1 ) 1429 { 1430 } 1431 1432 1433 void CV_MinEigenValTest::run_func() 1434 { 1435 cvCornerMinEigenVal( test_array[INPUT][0], test_array[OUTPUT][0], 1436 block_size, aperture_size ); 1437 } 1438 1439 1440 void CV_MinEigenValTest::prepare_to_validation( int /*test_case_idx*/ ) 1441 { 1442 test_cornerEigenValsVecs( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], 1443 test_mat[OUTPUT][0], block_size, aperture_size, 1 ); 1444 } 1445 1446 1447 // eigenval's & vec's 1448 class CV_EigenValVecTest : public CV_FeatureSelBaseTest 1449 { 1450 public: 1451 CV_EigenValVecTest(); 1452 1453 protected: 1454 void run_func(); 1455 void prepare_to_validation( int ); 1456 }; 1457 1458 1459 CV_EigenValVecTest::CV_EigenValVecTest() : CV_FeatureSelBaseTest( 6 ) 1460 { 1461 } 1462 1463 1464 void CV_EigenValVecTest::run_func() 1465 { 1466 cvCornerEigenValsAndVecs( test_array[INPUT][0], test_array[OUTPUT][0], 1467 block_size, aperture_size ); 1468 } 1469 1470 1471 void CV_EigenValVecTest::prepare_to_validation( int /*test_case_idx*/ ) 1472 { 1473 test_cornerEigenValsVecs( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], 1474 test_mat[OUTPUT][0], block_size, aperture_size, 0 ); 1475 } 1476 1477 1478 // precornerdetect 1479 class CV_PreCornerDetectTest : public CV_FeatureSelBaseTest 1480 { 1481 public: 1482 CV_PreCornerDetectTest(); 1483 1484 protected: 1485 void run_func(); 1486 void prepare_to_validation( int ); 1487 int prepare_test_case( int ); 1488 }; 1489 1490 1491 CV_PreCornerDetectTest::CV_PreCornerDetectTest() : CV_FeatureSelBaseTest( 1 ) 1492 { 1493 } 1494 1495 1496 void CV_PreCornerDetectTest::run_func() 1497 { 1498 cvPreCornerDetect( test_array[INPUT][0], test_array[OUTPUT][0], aperture_size ); 1499 } 1500 1501 1502 int CV_PreCornerDetectTest::prepare_test_case( int test_case_idx ) 1503 { 1504 int code = CV_FeatureSelBaseTest::prepare_test_case( test_case_idx ); 1505 if( aperture_size < 0 ) 1506 aperture_size = 3; 1507 return code; 1508 } 1509 1510 1511 void CV_PreCornerDetectTest::prepare_to_validation( int /*test_case_idx*/ ) 1512 { 1513 /*cvTsCornerEigenValsVecs( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], 1514 block_size, aperture_size, 0 );*/ 1515 const Mat& src = test_mat[INPUT][0]; 1516 Mat& dst = test_mat[REF_OUTPUT][0]; 1517 1518 int type = src.type(), ftype = CV_32FC1; 1519 Point anchor(aperture_size/2, aperture_size/2); 1520 1521 double kernel_scale = type != ftype ? 1./255 : 1.; 1522 1523 Mat dx, dy, d2x, d2y, dxy, kernel; 1524 1525 kernel = cvtest::calcSobelKernel2D(1, 0, aperture_size); 1526 cvtest::filter2D(src, dx, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE); 1527 kernel = cvtest::calcSobelKernel2D(2, 0, aperture_size); 1528 cvtest::filter2D(src, d2x, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE); 1529 kernel = cvtest::calcSobelKernel2D(0, 1, aperture_size); 1530 cvtest::filter2D(src, dy, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE); 1531 kernel = cvtest::calcSobelKernel2D(0, 2, aperture_size); 1532 cvtest::filter2D(src, d2y, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE); 1533 kernel = cvtest::calcSobelKernel2D(1, 1, aperture_size); 1534 cvtest::filter2D(src, dxy, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE); 1535 1536 double denom = 1 << (aperture_size-1); 1537 denom = denom * denom * denom; 1538 denom = 1./denom; 1539 1540 for( int i = 0; i < src.rows; i++ ) 1541 { 1542 const float* _dx = dx.ptr<float>(i); 1543 const float* _dy = dy.ptr<float>(i); 1544 const float* _d2x = d2x.ptr<float>(i); 1545 const float* _d2y = d2y.ptr<float>(i); 1546 const float* _dxy = dxy.ptr<float>(i); 1547 float* corner = dst.ptr<float>(i); 1548 1549 for( int j = 0; j < src.cols; j++ ) 1550 { 1551 double x = _dx[j]; 1552 double y = _dy[j]; 1553 1554 corner[j] = (float)(denom*(x*x*_d2y[j] + y*y*_d2x[j] - 2*x*y*_dxy[j])); 1555 } 1556 } 1557 } 1558 1559 1560 ///////// integral ///////// 1561 1562 class CV_IntegralTest : public cvtest::ArrayTest 1563 { 1564 public: 1565 CV_IntegralTest(); 1566 1567 protected: 1568 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 1569 void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high ); 1570 double get_success_error_level( int test_case_idx, int i, int j ); 1571 void run_func(); 1572 void prepare_to_validation( int ); 1573 1574 int prepare_test_case( int test_case_idx ); 1575 }; 1576 1577 1578 CV_IntegralTest::CV_IntegralTest() 1579 { 1580 test_array[INPUT].push_back(NULL); 1581 test_array[OUTPUT].push_back(NULL); 1582 test_array[OUTPUT].push_back(NULL); 1583 test_array[OUTPUT].push_back(NULL); 1584 test_array[REF_OUTPUT].push_back(NULL); 1585 test_array[REF_OUTPUT].push_back(NULL); 1586 test_array[REF_OUTPUT].push_back(NULL); 1587 element_wise_relative_error = true; 1588 } 1589 1590 1591 void CV_IntegralTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high ) 1592 { 1593 cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high ); 1594 int depth = CV_MAT_DEPTH(type); 1595 if( depth == CV_32F ) 1596 { 1597 low = Scalar::all(-10.); 1598 high = Scalar::all(10.); 1599 } 1600 } 1601 1602 1603 void CV_IntegralTest::get_test_array_types_and_sizes( int test_case_idx, 1604 vector<vector<Size> >& sizes, vector<vector<int> >& types ) 1605 { 1606 RNG& rng = ts->get_rng(); 1607 int depth = cvtest::randInt(rng) % 2, sum_depth; 1608 int cn = cvtest::randInt(rng) % 3 + 1; 1609 cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1610 Size sum_size; 1611 1612 depth = depth == 0 ? CV_8U : CV_32F; 1613 cn += cn == 2; 1614 int b = (cvtest::randInt(rng) & 1) != 0; 1615 sum_depth = depth == CV_8U && b ? CV_32S : b ? CV_32F : CV_64F; 1616 1617 types[INPUT][0] = CV_MAKETYPE(depth,cn); 1618 types[OUTPUT][0] = types[REF_OUTPUT][0] = 1619 types[OUTPUT][2] = types[REF_OUTPUT][2] = CV_MAKETYPE(sum_depth, cn); 1620 types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_MAKETYPE(CV_64F, cn); 1621 1622 sum_size.width = sizes[INPUT][0].width + 1; 1623 sum_size.height = sizes[INPUT][0].height + 1; 1624 1625 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sum_size; 1626 sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = 1627 sizes[OUTPUT][2] = sizes[REF_OUTPUT][2] = Size(0,0); 1628 1629 if( cvtest::randInt(rng) % 3 > 0 ) 1630 { 1631 sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = sum_size; 1632 if( cvtest::randInt(rng) % 2 > 0 ) 1633 sizes[REF_OUTPUT][2] = sizes[OUTPUT][2] = sum_size; 1634 } 1635 } 1636 1637 1638 double CV_IntegralTest::get_success_error_level( int, int i, int j ) 1639 { 1640 int depth = test_mat[i][j].depth(); 1641 return depth == CV_32S ? 0 : depth == CV_64F ? FLT_EPSILON : 5e-3; 1642 } 1643 1644 1645 int CV_IntegralTest::prepare_test_case( int test_case_idx ) 1646 { 1647 int code = cvtest::ArrayTest::prepare_test_case( test_case_idx ); 1648 return code > 0 && ((test_array[OUTPUT][2] && test_mat[OUTPUT][2].channels() > 1) || 1649 test_mat[OUTPUT][0].depth() < test_mat[INPUT][0].depth()) ? 0 : code; 1650 } 1651 1652 1653 void CV_IntegralTest::run_func() 1654 { 1655 cvIntegral( test_array[INPUT][0], test_array[OUTPUT][0], 1656 test_array[OUTPUT][1], test_array[OUTPUT][2] ); 1657 } 1658 1659 1660 static void test_integral( const Mat& img, Mat* sum, Mat* sqsum, Mat* tilted ) 1661 { 1662 CV_Assert( img.depth() == CV_32F ); 1663 1664 sum->create(img.rows+1, img.cols+1, CV_64F); 1665 if( sqsum ) 1666 sqsum->create(img.rows+1, img.cols+1, CV_64F); 1667 if( tilted ) 1668 tilted->create(img.rows+1, img.cols+1, CV_64F); 1669 1670 const float* data = img.ptr<float>(); 1671 double* sdata = sum->ptr<double>(); 1672 double* sqdata = sqsum ? sqsum->ptr<double>() : 0; 1673 double* tdata = tilted ? tilted->ptr<double>() : 0; 1674 int step = (int)(img.step/sizeof(data[0])); 1675 int sstep = (int)(sum->step/sizeof(sdata[0])); 1676 int sqstep = sqsum ? (int)(sqsum->step/sizeof(sqdata[0])) : 0; 1677 int tstep = tilted ? (int)(tilted->step/sizeof(tdata[0])) : 0; 1678 Size size = img.size(); 1679 1680 memset( sdata, 0, (size.width+1)*sizeof(sdata[0]) ); 1681 if( sqsum ) 1682 memset( sqdata, 0, (size.width+1)*sizeof(sqdata[0]) ); 1683 if( tilted ) 1684 memset( tdata, 0, (size.width+1)*sizeof(tdata[0]) ); 1685 1686 for( ; size.height--; data += step ) 1687 { 1688 double s = 0, sq = 0; 1689 int x; 1690 sdata += sstep; 1691 sqdata += sqstep; 1692 tdata += tstep; 1693 1694 for( x = 0; x <= size.width; x++ ) 1695 { 1696 double t = x > 0 ? data[x-1] : 0, ts = t; 1697 s += t; 1698 sq += t*t; 1699 1700 sdata[x] = s + sdata[x - sstep]; 1701 if( sqdata ) 1702 sqdata[x] = sq + sqdata[x - sqstep]; 1703 1704 if( !tdata ) 1705 continue; 1706 1707 if( x == 0 ) 1708 ts += tdata[-tstep+1]; 1709 else 1710 { 1711 ts += tdata[x-tstep-1]; 1712 if( data > img.ptr<float>() ) 1713 { 1714 ts += data[x-step-1]; 1715 if( x < size.width ) 1716 ts += tdata[x-tstep+1] - tdata[x-tstep*2]; 1717 } 1718 } 1719 1720 tdata[x] = ts; 1721 } 1722 } 1723 } 1724 1725 1726 void CV_IntegralTest::prepare_to_validation( int /*test_case_idx*/ ) 1727 { 1728 Mat& src = test_mat[INPUT][0]; 1729 int cn = src.channels(); 1730 1731 Mat* sum0 = &test_mat[REF_OUTPUT][0]; 1732 Mat* sqsum0 = test_array[REF_OUTPUT][1] ? &test_mat[REF_OUTPUT][1] : 0; 1733 Mat* tsum0 = test_array[REF_OUTPUT][2] ? &test_mat[REF_OUTPUT][2] : 0; 1734 1735 Mat plane, srcf, psum, psqsum, ptsum, psum2, psqsum2, ptsum2; 1736 if( cn == 1 ) 1737 { 1738 plane = src; 1739 psum2 = *sum0; 1740 psqsum2 = sqsum0 ? *sqsum0 : Mat(); 1741 ptsum2 = tsum0 ? *tsum0 : Mat(); 1742 } 1743 1744 for( int i = 0; i < cn; i++ ) 1745 { 1746 if( cn > 1 ) 1747 cvtest::extract(src, plane, i); 1748 plane.convertTo(srcf, CV_32F); 1749 1750 test_integral( srcf, &psum, sqsum0 ? &psqsum : 0, tsum0 ? &ptsum : 0 ); 1751 psum.convertTo(psum2, sum0->depth()); 1752 if( sqsum0 ) 1753 psqsum.convertTo(psqsum2, sqsum0->depth()); 1754 if( tsum0 ) 1755 ptsum.convertTo(ptsum2, tsum0->depth()); 1756 1757 if( cn > 1 ) 1758 { 1759 cvtest::insert(psum2, *sum0, i); 1760 if( sqsum0 ) 1761 cvtest::insert(psqsum2, *sqsum0, i); 1762 if( tsum0 ) 1763 cvtest::insert(ptsum2, *tsum0, i); 1764 } 1765 } 1766 } 1767 1768 1769 /////////////////////////////////////////////////////////////////////////////////// 1770 1771 TEST(Imgproc_Erode, accuracy) { CV_ErodeTest test; test.safe_run(); } 1772 TEST(Imgproc_Dilate, accuracy) { CV_DilateTest test; test.safe_run(); } 1773 TEST(Imgproc_MorphologyEx, accuracy) { CV_MorphExTest test; test.safe_run(); } 1774 TEST(Imgproc_Filter2D, accuracy) { CV_FilterTest test; test.safe_run(); } 1775 TEST(Imgproc_Sobel, accuracy) { CV_SobelTest test; test.safe_run(); } 1776 TEST(Imgproc_Laplace, accuracy) { CV_LaplaceTest test; test.safe_run(); } 1777 TEST(Imgproc_Blur, accuracy) { CV_BlurTest test; test.safe_run(); } 1778 TEST(Imgproc_GaussianBlur, accuracy) { CV_GaussianBlurTest test; test.safe_run(); } 1779 TEST(Imgproc_MedianBlur, accuracy) { CV_MedianBlurTest test; test.safe_run(); } 1780 TEST(Imgproc_PyramidDown, accuracy) { CV_PyramidDownTest test; test.safe_run(); } 1781 TEST(Imgproc_PyramidUp, accuracy) { CV_PyramidUpTest test; test.safe_run(); } 1782 TEST(Imgproc_MinEigenVal, accuracy) { CV_MinEigenValTest test; test.safe_run(); } 1783 TEST(Imgproc_EigenValsVecs, accuracy) { CV_EigenValVecTest test; test.safe_run(); } 1784 TEST(Imgproc_PreCornerDetect, accuracy) { CV_PreCornerDetectTest test; test.safe_run(); } 1785 TEST(Imgproc_Integral, accuracy) { CV_IntegralTest test; test.safe_run(); } 1786 1787 ////////////////////////////////////////////////////////////////////////////////// 1788 1789 class CV_FilterSupportedFormatsTest : public cvtest::BaseTest 1790 { 1791 public: 1792 CV_FilterSupportedFormatsTest() {} 1793 ~CV_FilterSupportedFormatsTest() {} 1794 protected: 1795 void run(int) 1796 { 1797 const int depths[][2] = 1798 { 1799 {CV_8U, CV_8U}, 1800 {CV_8U, CV_16U}, 1801 {CV_8U, CV_16S}, 1802 {CV_8U, CV_32F}, 1803 {CV_8U, CV_64F}, 1804 {CV_16U, CV_16U}, 1805 {CV_16U, CV_32F}, 1806 {CV_16U, CV_64F}, 1807 {CV_16S, CV_16S}, 1808 {CV_16S, CV_32F}, 1809 {CV_16S, CV_64F}, 1810 {CV_32F, CV_32F}, 1811 {CV_64F, CV_64F}, 1812 {-1, -1} 1813 }; 1814 1815 int i = 0; 1816 volatile int fidx = -1; 1817 try 1818 { 1819 // use some "odd" size to do yet another smoke 1820 // testing of the non-SIMD loop tails 1821 Size sz(163, 117); 1822 Mat small_kernel(5, 5, CV_32F), big_kernel(21, 21, CV_32F); 1823 Mat kernelX(11, 1, CV_32F), kernelY(7, 1, CV_32F); 1824 Mat symkernelX(11, 1, CV_32F), symkernelY(7, 1, CV_32F); 1825 randu(small_kernel, -10, 10); 1826 randu(big_kernel, -1, 1); 1827 randu(kernelX, -1, 1); 1828 randu(kernelY, -1, 1); 1829 flip(kernelX, symkernelX, 0); 1830 symkernelX += kernelX; 1831 flip(kernelY, symkernelY, 0); 1832 symkernelY += kernelY; 1833 1834 Mat elem_ellipse = getStructuringElement(MORPH_ELLIPSE, Size(7, 7)); 1835 Mat elem_rect = getStructuringElement(MORPH_RECT, Size(7, 7)); 1836 1837 for( i = 0; depths[i][0] >= 0; i++ ) 1838 { 1839 int sdepth = depths[i][0]; 1840 int ddepth = depths[i][1]; 1841 Mat src(sz, CV_MAKETYPE(sdepth, 5)), dst; 1842 randu(src, 0, 100); 1843 // non-separable filtering with a small kernel 1844 fidx = 0; 1845 filter2D(src, dst, ddepth, small_kernel); 1846 fidx++; 1847 filter2D(src, dst, ddepth, big_kernel); 1848 fidx++; 1849 sepFilter2D(src, dst, ddepth, kernelX, kernelY); 1850 fidx++; 1851 sepFilter2D(src, dst, ddepth, symkernelX, symkernelY); 1852 fidx++; 1853 Sobel(src, dst, ddepth, 2, 0, 5); 1854 fidx++; 1855 Scharr(src, dst, ddepth, 0, 1); 1856 if( sdepth != ddepth ) 1857 continue; 1858 fidx++; 1859 GaussianBlur(src, dst, Size(5, 5), 1.2, 1.2); 1860 fidx++; 1861 blur(src, dst, Size(11, 11)); 1862 fidx++; 1863 morphologyEx(src, dst, MORPH_GRADIENT, elem_ellipse); 1864 fidx++; 1865 morphologyEx(src, dst, MORPH_GRADIENT, elem_rect); 1866 } 1867 } 1868 catch(...) 1869 { 1870 ts->printf(cvtest::TS::LOG, "Combination of depths %d => %d in %s is not supported (yet it should be)", 1871 depths[i][0], depths[i][1], 1872 fidx == 0 ? "filter2D (small kernel)" : 1873 fidx == 1 ? "filter2D (large kernel)" : 1874 fidx == 2 ? "sepFilter2D" : 1875 fidx == 3 ? "sepFilter2D (symmetrical/asymmetrical kernel)" : 1876 fidx == 4 ? "Sobel" : 1877 fidx == 5 ? "Scharr" : 1878 fidx == 6 ? "GaussianBlur" : 1879 fidx == 7 ? "blur" : 1880 fidx == 8 || fidx == 9 ? "morphologyEx" : 1881 "unknown???"); 1882 1883 ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); 1884 } 1885 } 1886 }; 1887 1888 TEST(Imgproc_Filtering, supportedFormats) { CV_FilterSupportedFormatsTest test; test.safe_run(); } 1889 1890 TEST(Imgproc_Blur, borderTypes) 1891 { 1892 Size kernelSize(3, 3); 1893 1894 /// ksize > src_roi.size() 1895 Mat src(3, 3, CV_8UC1, cv::Scalar::all(255)), dst; 1896 Mat src_roi = src(Rect(1, 1, 1, 1)); 1897 src_roi.setTo(cv::Scalar::all(0)); 1898 1899 // should work like !BORDER_ISOLATED 1900 blur(src_roi, dst, kernelSize, Point(-1, -1), BORDER_REPLICATE); 1901 EXPECT_EQ(227, dst.at<uchar>(0, 0)); 1902 1903 // should work like BORDER_ISOLATED 1904 blur(src_roi, dst, kernelSize, Point(-1, -1), BORDER_REPLICATE | BORDER_ISOLATED); 1905 EXPECT_EQ(0, dst.at<uchar>(0, 0)); 1906 1907 /// ksize <= src_roi.size() 1908 src = Mat(5, 5, CV_8UC1, cv::Scalar(255)); 1909 src_roi = src(Rect(1, 1, 3, 3)); 1910 src_roi.setTo(0); 1911 src.at<uchar>(2, 2) = 255; 1912 1913 // should work like !BORDER_ISOLATED 1914 blur(src_roi, dst, kernelSize, Point(-1, -1), BORDER_REPLICATE); 1915 Mat expected_dst = 1916 (Mat_<uchar>(3, 3) << 170, 113, 170, 113, 28, 113, 170, 113, 170); 1917 EXPECT_EQ(expected_dst.type(), dst.type()); 1918 EXPECT_EQ(expected_dst.size(), dst.size()); 1919 EXPECT_DOUBLE_EQ(0.0, cvtest::norm(expected_dst, dst, NORM_INF)); 1920 } 1921 1922 TEST(Imgproc_Morphology, iterated) 1923 { 1924 RNG& rng = theRNG(); 1925 for( int iter = 0; iter < 30; iter++ ) 1926 { 1927 int width = rng.uniform(5, 33); 1928 int height = rng.uniform(5, 33); 1929 int cn = rng.uniform(1, 5); 1930 int iterations = rng.uniform(1, 11); 1931 int op = rng.uniform(0, 2); 1932 Mat src(height, width, CV_8UC(cn)), dst0, dst1, dst2; 1933 1934 randu(src, 0, 256); 1935 if( op == 0 ) 1936 dilate(src, dst0, Mat(), Point(-1,-1), iterations); 1937 else 1938 erode(src, dst0, Mat(), Point(-1,-1), iterations); 1939 1940 for( int i = 0; i < iterations; i++ ) 1941 if( op == 0 ) 1942 dilate(i == 0 ? src : dst1, dst1, Mat(), Point(-1,-1), 1); 1943 else 1944 erode(i == 0 ? src : dst1, dst1, Mat(), Point(-1,-1), 1); 1945 1946 Mat kern = getStructuringElement(MORPH_RECT, Size(3,3)); 1947 if( op == 0 ) 1948 dilate(src, dst2, kern, Point(-1,-1), iterations); 1949 else 1950 erode(src, dst2, kern, Point(-1,-1), iterations); 1951 ASSERT_EQ(0.0, norm(dst0, dst1, NORM_INF)); 1952 ASSERT_EQ(0.0, norm(dst0, dst2, NORM_INF)); 1953 } 1954 } 1955