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_ImgWarpBaseTest : public cvtest::ArrayTest 48 { 49 public: 50 CV_ImgWarpBaseTest( bool warp_matrix ); 51 52 protected: 53 int read_params( CvFileStorage* fs ); 54 int prepare_test_case( int test_case_idx ); 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 void fill_array( int test_case_idx, int i, int j, Mat& arr ); 58 59 int interpolation; 60 int max_interpolation; 61 double spatial_scale_zoom, spatial_scale_decimate; 62 }; 63 64 65 CV_ImgWarpBaseTest::CV_ImgWarpBaseTest( bool warp_matrix ) 66 { 67 test_array[INPUT].push_back(NULL); 68 if( warp_matrix ) 69 test_array[INPUT].push_back(NULL); 70 test_array[INPUT_OUTPUT].push_back(NULL); 71 test_array[REF_INPUT_OUTPUT].push_back(NULL); 72 max_interpolation = 5; 73 interpolation = 0; 74 element_wise_relative_error = false; 75 spatial_scale_zoom = 0.01; 76 spatial_scale_decimate = 0.005; 77 } 78 79 80 int CV_ImgWarpBaseTest::read_params( CvFileStorage* fs ) 81 { 82 int code = cvtest::ArrayTest::read_params( fs ); 83 return code; 84 } 85 86 87 void CV_ImgWarpBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high ) 88 { 89 cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high ); 90 if( CV_MAT_DEPTH(type) == CV_32F ) 91 { 92 low = Scalar::all(-10.); 93 high = Scalar::all(10); 94 } 95 } 96 97 98 void CV_ImgWarpBaseTest::get_test_array_types_and_sizes( int test_case_idx, 99 vector<vector<Size> >& sizes, vector<vector<int> >& types ) 100 { 101 RNG& rng = ts->get_rng(); 102 int depth = cvtest::randInt(rng) % 3; 103 int cn = cvtest::randInt(rng) % 3 + 1; 104 cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 105 depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : CV_32F; 106 cn += cn == 2; 107 108 types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn); 109 if( test_array[INPUT].size() > 1 ) 110 types[INPUT][1] = cvtest::randInt(rng) & 1 ? CV_32FC1 : CV_64FC1; 111 112 interpolation = cvtest::randInt(rng) % max_interpolation; 113 } 114 115 116 void CV_ImgWarpBaseTest::fill_array( int test_case_idx, int i, int j, Mat& arr ) 117 { 118 if( i != INPUT || j != 0 ) 119 cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr ); 120 } 121 122 int CV_ImgWarpBaseTest::prepare_test_case( int test_case_idx ) 123 { 124 int code = cvtest::ArrayTest::prepare_test_case( test_case_idx ); 125 Mat& img = test_mat[INPUT][0]; 126 int i, j, cols = img.cols; 127 int type = img.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); 128 double scale = depth == CV_16U ? 1000. : 255.*0.5; 129 double space_scale = spatial_scale_decimate; 130 vector<float> buffer(img.cols*cn); 131 132 if( code <= 0 ) 133 return code; 134 135 if( test_mat[INPUT_OUTPUT][0].cols >= img.cols && 136 test_mat[INPUT_OUTPUT][0].rows >= img.rows ) 137 space_scale = spatial_scale_zoom; 138 139 for( i = 0; i < img.rows; i++ ) 140 { 141 uchar* ptr = img.ptr(i); 142 switch( cn ) 143 { 144 case 1: 145 for( j = 0; j < cols; j++ ) 146 buffer[j] = (float)((sin((i+1)*space_scale)*sin((j+1)*space_scale)+1.)*scale); 147 break; 148 case 2: 149 for( j = 0; j < cols; j++ ) 150 { 151 buffer[j*2] = (float)((sin((i+1)*space_scale)+1.)*scale); 152 buffer[j*2+1] = (float)((sin((i+j)*space_scale)+1.)*scale); 153 } 154 break; 155 case 3: 156 for( j = 0; j < cols; j++ ) 157 { 158 buffer[j*3] = (float)((sin((i+1)*space_scale)+1.)*scale); 159 buffer[j*3+1] = (float)((sin(j*space_scale)+1.)*scale); 160 buffer[j*3+2] = (float)((sin((i+j)*space_scale)+1.)*scale); 161 } 162 break; 163 case 4: 164 for( j = 0; j < cols; j++ ) 165 { 166 buffer[j*4] = (float)((sin((i+1)*space_scale)+1.)*scale); 167 buffer[j*4+1] = (float)((sin(j*space_scale)+1.)*scale); 168 buffer[j*4+2] = (float)((sin((i+j)*space_scale)+1.)*scale); 169 buffer[j*4+3] = (float)((sin((i-j)*space_scale)+1.)*scale); 170 } 171 break; 172 default: 173 assert(0); 174 } 175 176 /*switch( depth ) 177 { 178 case CV_8U: 179 for( j = 0; j < cols*cn; j++ ) 180 ptr[j] = (uchar)cvRound(buffer[j]); 181 break; 182 case CV_16U: 183 for( j = 0; j < cols*cn; j++ ) 184 ((ushort*)ptr)[j] = (ushort)cvRound(buffer[j]); 185 break; 186 case CV_32F: 187 for( j = 0; j < cols*cn; j++ ) 188 ((float*)ptr)[j] = (float)buffer[j]; 189 break; 190 default: 191 assert(0); 192 }*/ 193 cv::Mat src(1, cols*cn, CV_32F, &buffer[0]); 194 cv::Mat dst(1, cols*cn, depth, ptr); 195 src.convertTo(dst, dst.type()); 196 } 197 198 return code; 199 } 200 201 202 ///////////////////////// 203 204 class CV_ResizeTest : public CV_ImgWarpBaseTest 205 { 206 public: 207 CV_ResizeTest(); 208 209 protected: 210 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 211 void run_func(); 212 void prepare_to_validation( int /*test_case_idx*/ ); 213 double get_success_error_level( int test_case_idx, int i, int j ); 214 }; 215 216 217 CV_ResizeTest::CV_ResizeTest() : CV_ImgWarpBaseTest( false ) 218 { 219 } 220 221 222 void CV_ResizeTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 223 { 224 RNG& rng = ts->get_rng(); 225 CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 226 CvSize sz; 227 228 sz.width = (cvtest::randInt(rng) % sizes[INPUT][0].width) + 1; 229 sz.height = (cvtest::randInt(rng) % sizes[INPUT][0].height) + 1; 230 231 if( cvtest::randInt(rng) & 1 ) 232 { 233 int xfactor = cvtest::randInt(rng) % 10 + 1; 234 int yfactor = cvtest::randInt(rng) % 10 + 1; 235 236 if( cvtest::randInt(rng) & 1 ) 237 yfactor = xfactor; 238 239 sz.width = sizes[INPUT][0].width / xfactor; 240 sz.width = MAX(sz.width,1); 241 sz.height = sizes[INPUT][0].height / yfactor; 242 sz.height = MAX(sz.height,1); 243 sizes[INPUT][0].width = sz.width * xfactor; 244 sizes[INPUT][0].height = sz.height * yfactor; 245 } 246 247 if( cvtest::randInt(rng) & 1 ) 248 sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = sz; 249 else 250 { 251 sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = sizes[INPUT][0]; 252 sizes[INPUT][0] = sz; 253 } 254 if( interpolation == 4 && 255 (MIN(sizes[INPUT][0].width,sizes[INPUT_OUTPUT][0].width) < 4 || 256 MIN(sizes[INPUT][0].height,sizes[INPUT_OUTPUT][0].height) < 4)) 257 interpolation = 2; 258 } 259 260 261 void CV_ResizeTest::run_func() 262 { 263 cvResize( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], interpolation ); 264 } 265 266 267 double CV_ResizeTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 268 { 269 int depth = test_mat[INPUT][0].depth(); 270 return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 1e-1; 271 } 272 273 274 void CV_ResizeTest::prepare_to_validation( int /*test_case_idx*/ ) 275 { 276 CvMat _src = test_mat[INPUT][0], _dst = test_mat[REF_INPUT_OUTPUT][0]; 277 CvMat *src = &_src, *dst = &_dst; 278 int i, j, k; 279 CvMat* x_idx = cvCreateMat( 1, dst->cols, CV_32SC1 ); 280 CvMat* y_idx = cvCreateMat( 1, dst->rows, CV_32SC1 ); 281 int* x_tab = x_idx->data.i; 282 int elem_size = CV_ELEM_SIZE(src->type); 283 int drows = dst->rows, dcols = dst->cols; 284 285 if( interpolation == CV_INTER_NN ) 286 { 287 for( j = 0; j < dcols; j++ ) 288 { 289 int t = (j*src->cols*2 + MIN(src->cols,dcols) - 1)/(dcols*2); 290 t -= t >= src->cols; 291 x_idx->data.i[j] = t*elem_size; 292 } 293 294 for( j = 0; j < drows; j++ ) 295 { 296 int t = (j*src->rows*2 + MIN(src->rows,drows) - 1)/(drows*2); 297 t -= t >= src->rows; 298 y_idx->data.i[j] = t; 299 } 300 } 301 else 302 { 303 double scale_x = (double)src->cols/dcols; 304 double scale_y = (double)src->rows/drows; 305 306 for( j = 0; j < dcols; j++ ) 307 { 308 double f = ((j+0.5)*scale_x - 0.5); 309 i = cvRound(f); 310 x_idx->data.i[j] = (i < 0 ? 0 : i >= src->cols ? src->cols - 1 : i)*elem_size; 311 } 312 313 for( j = 0; j < drows; j++ ) 314 { 315 double f = ((j+0.5)*scale_y - 0.5); 316 i = cvRound(f); 317 y_idx->data.i[j] = i < 0 ? 0 : i >= src->rows ? src->rows - 1 : i; 318 } 319 } 320 321 for( i = 0; i < drows; i++ ) 322 { 323 uchar* dptr = dst->data.ptr + dst->step*i; 324 const uchar* sptr0 = src->data.ptr + src->step*y_idx->data.i[i]; 325 326 for( j = 0; j < dcols; j++, dptr += elem_size ) 327 { 328 const uchar* sptr = sptr0 + x_tab[j]; 329 for( k = 0; k < elem_size; k++ ) 330 dptr[k] = sptr[k]; 331 } 332 } 333 334 cvReleaseMat( &x_idx ); 335 cvReleaseMat( &y_idx ); 336 } 337 338 339 ///////////////////////// 340 341 static void test_remap( const Mat& src, Mat& dst, const Mat& mapx, const Mat& mapy, 342 Mat* mask=0, int interpolation=CV_INTER_LINEAR ) 343 { 344 int x, y, k; 345 int drows = dst.rows, dcols = dst.cols; 346 int srows = src.rows, scols = src.cols; 347 const uchar* sptr0 = src.ptr(); 348 int depth = src.depth(), cn = src.channels(); 349 int elem_size = (int)src.elemSize(); 350 int step = (int)(src.step / CV_ELEM_SIZE(depth)); 351 int delta; 352 353 if( interpolation != CV_INTER_CUBIC ) 354 { 355 delta = 0; 356 scols -= 1; srows -= 1; 357 } 358 else 359 { 360 delta = 1; 361 scols = MAX(scols - 3, 0); 362 srows = MAX(srows - 3, 0); 363 } 364 365 int scols1 = MAX(scols - 2, 0); 366 int srows1 = MAX(srows - 2, 0); 367 368 if( mask ) 369 *mask = Scalar::all(0); 370 371 for( y = 0; y < drows; y++ ) 372 { 373 uchar* dptr = dst.ptr(y); 374 const float* mx = mapx.ptr<float>(y); 375 const float* my = mapy.ptr<float>(y); 376 uchar* m = mask ? mask->ptr(y) : 0; 377 378 for( x = 0; x < dcols; x++, dptr += elem_size ) 379 { 380 float xs = mx[x]; 381 float ys = my[x]; 382 int ixs = cvFloor(xs); 383 int iys = cvFloor(ys); 384 385 if( (unsigned)(ixs - delta - 1) >= (unsigned)scols1 || 386 (unsigned)(iys - delta - 1) >= (unsigned)srows1 ) 387 { 388 if( m ) 389 m[x] = 1; 390 if( (unsigned)(ixs - delta) >= (unsigned)scols || 391 (unsigned)(iys - delta) >= (unsigned)srows ) 392 continue; 393 } 394 395 xs -= ixs; 396 ys -= iys; 397 398 switch( depth ) 399 { 400 case CV_8U: 401 { 402 const uchar* sptr = sptr0 + iys*step + ixs*cn; 403 for( k = 0; k < cn; k++ ) 404 { 405 float v00 = sptr[k]; 406 float v01 = sptr[cn + k]; 407 float v10 = sptr[step + k]; 408 float v11 = sptr[step + cn + k]; 409 410 v00 = v00 + xs*(v01 - v00); 411 v10 = v10 + xs*(v11 - v10); 412 v00 = v00 + ys*(v10 - v00); 413 dptr[k] = (uchar)cvRound(v00); 414 } 415 } 416 break; 417 case CV_16U: 418 { 419 const ushort* sptr = (const ushort*)sptr0 + iys*step + ixs*cn; 420 for( k = 0; k < cn; k++ ) 421 { 422 float v00 = sptr[k]; 423 float v01 = sptr[cn + k]; 424 float v10 = sptr[step + k]; 425 float v11 = sptr[step + cn + k]; 426 427 v00 = v00 + xs*(v01 - v00); 428 v10 = v10 + xs*(v11 - v10); 429 v00 = v00 + ys*(v10 - v00); 430 ((ushort*)dptr)[k] = (ushort)cvRound(v00); 431 } 432 } 433 break; 434 case CV_32F: 435 { 436 const float* sptr = (const float*)sptr0 + iys*step + ixs*cn; 437 for( k = 0; k < cn; k++ ) 438 { 439 float v00 = sptr[k]; 440 float v01 = sptr[cn + k]; 441 float v10 = sptr[step + k]; 442 float v11 = sptr[step + cn + k]; 443 444 v00 = v00 + xs*(v01 - v00); 445 v10 = v10 + xs*(v11 - v10); 446 v00 = v00 + ys*(v10 - v00); 447 ((float*)dptr)[k] = (float)v00; 448 } 449 } 450 break; 451 default: 452 assert(0); 453 } 454 } 455 } 456 } 457 458 ///////////////////////// 459 460 class CV_WarpAffineTest : public CV_ImgWarpBaseTest 461 { 462 public: 463 CV_WarpAffineTest(); 464 465 protected: 466 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 467 void run_func(); 468 int prepare_test_case( int test_case_idx ); 469 void prepare_to_validation( int /*test_case_idx*/ ); 470 double get_success_error_level( int test_case_idx, int i, int j ); 471 }; 472 473 474 CV_WarpAffineTest::CV_WarpAffineTest() : CV_ImgWarpBaseTest( true ) 475 { 476 //spatial_scale_zoom = spatial_scale_decimate; 477 spatial_scale_decimate = spatial_scale_zoom; 478 } 479 480 481 void CV_WarpAffineTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 482 { 483 CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 484 CvSize sz = sizes[INPUT][0]; 485 // run for the second time to get output of a different size 486 CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 487 sizes[INPUT][0] = sz; 488 sizes[INPUT][1] = cvSize( 3, 2 ); 489 } 490 491 492 void CV_WarpAffineTest::run_func() 493 { 494 CvMat mtx = test_mat[INPUT][1]; 495 cvWarpAffine( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &mtx, interpolation ); 496 } 497 498 499 double CV_WarpAffineTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 500 { 501 int depth = test_mat[INPUT][0].depth(); 502 return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2; 503 } 504 505 506 int CV_WarpAffineTest::prepare_test_case( int test_case_idx ) 507 { 508 RNG& rng = ts->get_rng(); 509 int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); 510 const Mat& src = test_mat[INPUT][0]; 511 const Mat& dst = test_mat[INPUT_OUTPUT][0]; 512 Mat& mat = test_mat[INPUT][1]; 513 CvPoint2D32f center; 514 double scale, angle; 515 516 if( code <= 0 ) 517 return code; 518 519 double buffer[6]; 520 Mat tmp( 2, 3, mat.type(), buffer ); 521 522 center.x = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.cols); 523 center.y = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.rows); 524 angle = cvtest::randReal(rng)*360; 525 scale = ((double)dst.rows/src.rows + (double)dst.cols/src.cols)*0.5; 526 getRotationMatrix2D(center, angle, scale).convertTo(mat, mat.depth()); 527 rng.fill( tmp, CV_RAND_NORMAL, Scalar::all(1.), Scalar::all(0.01) ); 528 cv::max(tmp, 0.9, tmp); 529 cv::min(tmp, 1.1, tmp); 530 cv::multiply(tmp, mat, mat, 1.); 531 532 return code; 533 } 534 535 536 void CV_WarpAffineTest::prepare_to_validation( int /*test_case_idx*/ ) 537 { 538 const Mat& src = test_mat[INPUT][0]; 539 Mat& dst = test_mat[REF_INPUT_OUTPUT][0]; 540 Mat& dst0 = test_mat[INPUT_OUTPUT][0]; 541 Mat mapx(dst.size(), CV_32F), mapy(dst.size(), CV_32F); 542 double m[6]; 543 Mat srcAb, dstAb( 2, 3, CV_64FC1, m ); 544 545 //cvInvert( &tM, &M, CV_LU ); 546 // [R|t] -> [R^-1 | -(R^-1)*t] 547 test_mat[INPUT][1].convertTo( srcAb, CV_64F ); 548 Mat A = srcAb.colRange(0, 2); 549 Mat b = srcAb.col(2); 550 Mat invA = dstAb.colRange(0, 2); 551 Mat invAb = dstAb.col(2); 552 cv::invert(A, invA, CV_SVD); 553 cv::gemm(invA, b, -1, Mat(), 0, invAb); 554 555 for( int y = 0; y < dst.rows; y++ ) 556 for( int x = 0; x < dst.cols; x++ ) 557 { 558 mapx.at<float>(y, x) = (float)(x*m[0] + y*m[1] + m[2]); 559 mapy.at<float>(y, x) = (float)(x*m[3] + y*m[4] + m[5]); 560 } 561 562 Mat mask( dst.size(), CV_8U ); 563 test_remap( src, dst, mapx, mapy, &mask ); 564 dst.setTo(Scalar::all(0), mask); 565 dst0.setTo(Scalar::all(0), mask); 566 } 567 568 569 ///////////////////////// 570 571 class CV_WarpPerspectiveTest : public CV_ImgWarpBaseTest 572 { 573 public: 574 CV_WarpPerspectiveTest(); 575 576 protected: 577 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 578 void run_func(); 579 int prepare_test_case( int test_case_idx ); 580 void prepare_to_validation( int /*test_case_idx*/ ); 581 double get_success_error_level( int test_case_idx, int i, int j ); 582 }; 583 584 585 CV_WarpPerspectiveTest::CV_WarpPerspectiveTest() : CV_ImgWarpBaseTest( true ) 586 { 587 //spatial_scale_zoom = spatial_scale_decimate; 588 spatial_scale_decimate = spatial_scale_zoom; 589 } 590 591 592 void CV_WarpPerspectiveTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 593 { 594 CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 595 CvSize sz = sizes[INPUT][0]; 596 // run for the second time to get output of a different size 597 CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 598 sizes[INPUT][0] = sz; 599 sizes[INPUT][1] = cvSize( 3, 3 ); 600 } 601 602 603 void CV_WarpPerspectiveTest::run_func() 604 { 605 CvMat mtx = test_mat[INPUT][1]; 606 cvWarpPerspective( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &mtx, interpolation ); 607 } 608 609 610 double CV_WarpPerspectiveTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 611 { 612 int depth = test_mat[INPUT][0].depth(); 613 return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2; 614 } 615 616 617 int CV_WarpPerspectiveTest::prepare_test_case( int test_case_idx ) 618 { 619 RNG& rng = ts->get_rng(); 620 int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); 621 const CvMat& src = test_mat[INPUT][0]; 622 const CvMat& dst = test_mat[INPUT_OUTPUT][0]; 623 Mat& mat = test_mat[INPUT][1]; 624 Point2f s[4], d[4]; 625 int i; 626 627 if( code <= 0 ) 628 return code; 629 630 s[0] = Point2f(0,0); 631 d[0] = Point2f(0,0); 632 s[1] = Point2f(src.cols-1.f,0); 633 d[1] = Point2f(dst.cols-1.f,0); 634 s[2] = Point2f(src.cols-1.f,src.rows-1.f); 635 d[2] = Point2f(dst.cols-1.f,dst.rows-1.f); 636 s[3] = Point2f(0,src.rows-1.f); 637 d[3] = Point2f(0,dst.rows-1.f); 638 639 float bufer[16]; 640 Mat tmp( 1, 16, CV_32FC1, bufer ); 641 642 rng.fill( tmp, CV_RAND_NORMAL, Scalar::all(0.), Scalar::all(0.1) ); 643 644 for( i = 0; i < 4; i++ ) 645 { 646 s[i].x += bufer[i*4]*src.cols/2; 647 s[i].y += bufer[i*4+1]*src.rows/2; 648 d[i].x += bufer[i*4+2]*dst.cols/2; 649 d[i].y += bufer[i*4+3]*dst.rows/2; 650 } 651 652 cv::getPerspectiveTransform( s, d ).convertTo( mat, mat.depth() ); 653 return code; 654 } 655 656 657 void CV_WarpPerspectiveTest::prepare_to_validation( int /*test_case_idx*/ ) 658 { 659 Mat& src = test_mat[INPUT][0]; 660 Mat& dst = test_mat[REF_INPUT_OUTPUT][0]; 661 Mat& dst0 = test_mat[INPUT_OUTPUT][0]; 662 Mat mapx(dst.size(), CV_32F), mapy(dst.size(), CV_32F); 663 double m[9]; 664 Mat srcM, dstM(3, 3, CV_64F, m); 665 666 //cvInvert( &tM, &M, CV_LU ); 667 // [R|t] -> [R^-1 | -(R^-1)*t] 668 test_mat[INPUT][1].convertTo( srcM, CV_64F ); 669 cv::invert(srcM, dstM, CV_SVD); 670 671 for( int y = 0; y < dst.rows; y++ ) 672 { 673 for( int x = 0; x < dst.cols; x++ ) 674 { 675 double xs = x*m[0] + y*m[1] + m[2]; 676 double ys = x*m[3] + y*m[4] + m[5]; 677 double ds = x*m[6] + y*m[7] + m[8]; 678 679 ds = ds ? 1./ds : 0; 680 xs *= ds; 681 ys *= ds; 682 683 mapx.at<float>(y, x) = (float)xs; 684 mapy.at<float>(y, x) = (float)ys; 685 } 686 } 687 688 Mat mask( dst.size(), CV_8U ); 689 test_remap( src, dst, mapx, mapy, &mask ); 690 dst.setTo(Scalar::all(0), mask); 691 dst0.setTo(Scalar::all(0), mask); 692 } 693 694 695 ///////////////////////// 696 697 class CV_RemapTest : public CV_ImgWarpBaseTest 698 { 699 public: 700 CV_RemapTest(); 701 702 protected: 703 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 704 void run_func(); 705 int prepare_test_case( int test_case_idx ); 706 void prepare_to_validation( int /*test_case_idx*/ ); 707 double get_success_error_level( int test_case_idx, int i, int j ); 708 void fill_array( int test_case_idx, int i, int j, Mat& arr ); 709 }; 710 711 712 CV_RemapTest::CV_RemapTest() : CV_ImgWarpBaseTest( false ) 713 { 714 //spatial_scale_zoom = spatial_scale_decimate; 715 test_array[INPUT].push_back(NULL); 716 test_array[INPUT].push_back(NULL); 717 718 spatial_scale_decimate = spatial_scale_zoom; 719 } 720 721 722 void CV_RemapTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 723 { 724 CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 725 types[INPUT][1] = types[INPUT][2] = CV_32FC1; 726 interpolation = CV_INTER_LINEAR; 727 } 728 729 730 void CV_RemapTest::fill_array( int test_case_idx, int i, int j, Mat& arr ) 731 { 732 if( i != INPUT ) 733 CV_ImgWarpBaseTest::fill_array( test_case_idx, i, j, arr ); 734 } 735 736 737 void CV_RemapTest::run_func() 738 { 739 cvRemap( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], 740 test_array[INPUT][1], test_array[INPUT][2], interpolation ); 741 } 742 743 744 double CV_RemapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 745 { 746 int depth = test_mat[INPUT][0].depth(); 747 return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2; 748 } 749 750 751 int CV_RemapTest::prepare_test_case( int test_case_idx ) 752 { 753 RNG& rng = ts->get_rng(); 754 int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); 755 const Mat& src = test_mat[INPUT][0]; 756 double a[9] = {0,0,0,0,0,0,0,0,1}, k[4]; 757 Mat _a( 3, 3, CV_64F, a ); 758 Mat _k( 4, 1, CV_64F, k ); 759 double sz = MAX(src.rows, src.cols); 760 761 if( code <= 0 ) 762 return code; 763 764 double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7; 765 a[2] = (src.cols - 1)*0.5 + cvtest::randReal(rng)*10 - 5; 766 a[5] = (src.rows - 1)*0.5 + cvtest::randReal(rng)*10 - 5; 767 a[0] = sz/(0.9 - cvtest::randReal(rng)*0.6); 768 a[4] = aspect_ratio*a[0]; 769 k[0] = cvtest::randReal(rng)*0.06 - 0.03; 770 k[1] = cvtest::randReal(rng)*0.06 - 0.03; 771 if( k[0]*k[1] > 0 ) 772 k[1] = -k[1]; 773 k[2] = cvtest::randReal(rng)*0.004 - 0.002; 774 k[3] = cvtest::randReal(rng)*0.004 - 0.002; 775 776 cvtest::initUndistortMap( _a, _k, test_mat[INPUT][1].size(), test_mat[INPUT][1], test_mat[INPUT][2] ); 777 return code; 778 } 779 780 781 void CV_RemapTest::prepare_to_validation( int /*test_case_idx*/ ) 782 { 783 Mat& dst = test_mat[REF_INPUT_OUTPUT][0]; 784 Mat& dst0 = test_mat[INPUT_OUTPUT][0]; 785 Mat mask( dst.size(), CV_8U ); 786 test_remap(test_mat[INPUT][0], dst, test_mat[INPUT][1], 787 test_mat[INPUT][2], &mask, interpolation ); 788 dst.setTo(Scalar::all(0), mask); 789 dst0.setTo(Scalar::all(0), mask); 790 } 791 792 793 ////////////////////////////// undistort ///////////////////////////////// 794 795 class CV_UndistortTest : public CV_ImgWarpBaseTest 796 { 797 public: 798 CV_UndistortTest(); 799 800 protected: 801 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 802 void run_func(); 803 int prepare_test_case( int test_case_idx ); 804 void prepare_to_validation( int /*test_case_idx*/ ); 805 double get_success_error_level( int test_case_idx, int i, int j ); 806 void fill_array( int test_case_idx, int i, int j, Mat& arr ); 807 808 private: 809 bool useCPlus; 810 cv::Mat input0; 811 cv::Mat input1; 812 cv::Mat input2; 813 cv::Mat input_new_cam; 814 cv::Mat input_output; 815 816 bool zero_new_cam; 817 bool zero_distortion; 818 }; 819 820 821 CV_UndistortTest::CV_UndistortTest() : CV_ImgWarpBaseTest( false ) 822 { 823 //spatial_scale_zoom = spatial_scale_decimate; 824 test_array[INPUT].push_back(NULL); 825 test_array[INPUT].push_back(NULL); 826 test_array[INPUT].push_back(NULL); 827 828 spatial_scale_decimate = spatial_scale_zoom; 829 } 830 831 832 void CV_UndistortTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 833 { 834 RNG& rng = ts->get_rng(); 835 CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 836 int type = types[INPUT][0]; 837 type = CV_MAKETYPE( CV_8U, CV_MAT_CN(type) ); 838 types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = type; 839 types[INPUT][1] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F; 840 types[INPUT][2] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F; 841 sizes[INPUT][1] = cvSize(3,3); 842 sizes[INPUT][2] = cvtest::randInt(rng)%2 ? cvSize(4,1) : cvSize(1,4); 843 types[INPUT][3] = types[INPUT][1]; 844 sizes[INPUT][3] = sizes[INPUT][1]; 845 interpolation = CV_INTER_LINEAR; 846 } 847 848 849 void CV_UndistortTest::fill_array( int test_case_idx, int i, int j, Mat& arr ) 850 { 851 if( i != INPUT ) 852 CV_ImgWarpBaseTest::fill_array( test_case_idx, i, j, arr ); 853 } 854 855 856 void CV_UndistortTest::run_func() 857 { 858 if (!useCPlus) 859 { 860 CvMat a = test_mat[INPUT][1], k = test_mat[INPUT][2]; 861 cvUndistort2( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &a, &k); 862 } 863 else 864 { 865 if (zero_distortion) 866 { 867 cv::undistort(input0,input_output,input1,cv::Mat()); 868 } 869 else 870 { 871 cv::undistort(input0,input_output,input1,input2); 872 } 873 } 874 } 875 876 877 double CV_UndistortTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 878 { 879 int depth = test_mat[INPUT][0].depth(); 880 return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2; 881 } 882 883 884 int CV_UndistortTest::prepare_test_case( int test_case_idx ) 885 { 886 RNG& rng = ts->get_rng(); 887 int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); 888 889 const Mat& src = test_mat[INPUT][0]; 890 double k[4], a[9] = {0,0,0,0,0,0,0,0,1}; 891 double new_cam[9] = {0,0,0,0,0,0,0,0,1}; 892 double sz = MAX(src.rows, src.cols); 893 894 Mat& _new_cam0 = test_mat[INPUT][3]; 895 Mat _new_cam(test_mat[INPUT][3].rows,test_mat[INPUT][3].cols,CV_64F,new_cam); 896 Mat& _a0 = test_mat[INPUT][1]; 897 Mat _a(3,3,CV_64F,a); 898 Mat& _k0 = test_mat[INPUT][2]; 899 Mat _k(_k0.rows,_k0.cols, CV_MAKETYPE(CV_64F,_k0.channels()),k); 900 901 if( code <= 0 ) 902 return code; 903 904 double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7; 905 a[2] = (src.cols - 1)*0.5 + cvtest::randReal(rng)*10 - 5; 906 a[5] = (src.rows - 1)*0.5 + cvtest::randReal(rng)*10 - 5; 907 a[0] = sz/(0.9 - cvtest::randReal(rng)*0.6); 908 a[4] = aspect_ratio*a[0]; 909 k[0] = cvtest::randReal(rng)*0.06 - 0.03; 910 k[1] = cvtest::randReal(rng)*0.06 - 0.03; 911 if( k[0]*k[1] > 0 ) 912 k[1] = -k[1]; 913 if( cvtest::randInt(rng)%4 != 0 ) 914 { 915 k[2] = cvtest::randReal(rng)*0.004 - 0.002; 916 k[3] = cvtest::randReal(rng)*0.004 - 0.002; 917 } 918 else 919 k[2] = k[3] = 0; 920 921 new_cam[0] = a[0] + (cvtest::randReal(rng) - (double)0.5)*0.2*a[0]; //10% 922 new_cam[4] = a[4] + (cvtest::randReal(rng) - (double)0.5)*0.2*a[4]; //10% 923 new_cam[2] = a[2] + (cvtest::randReal(rng) - (double)0.5)*0.3*test_mat[INPUT][0].rows; //15% 924 new_cam[5] = a[5] + (cvtest::randReal(rng) - (double)0.5)*0.3*test_mat[INPUT][0].cols; //15% 925 926 _a.convertTo(_a0, _a0.depth()); 927 928 zero_distortion = (cvtest::randInt(rng)%2) == 0 ? false : true; 929 _k.convertTo(_k0, _k0.depth()); 930 931 zero_new_cam = (cvtest::randInt(rng)%2) == 0 ? false : true; 932 _new_cam.convertTo(_new_cam0, _new_cam0.depth()); 933 934 //Testing C++ code 935 useCPlus = ((cvtest::randInt(rng) % 2)!=0); 936 if (useCPlus) 937 { 938 input0 = test_mat[INPUT][0]; 939 input1 = test_mat[INPUT][1]; 940 input2 = test_mat[INPUT][2]; 941 input_new_cam = test_mat[INPUT][3]; 942 } 943 944 return code; 945 } 946 947 948 void CV_UndistortTest::prepare_to_validation( int /*test_case_idx*/ ) 949 { 950 if (useCPlus) 951 { 952 Mat& output = test_mat[INPUT_OUTPUT][0]; 953 input_output.convertTo(output, output.type()); 954 } 955 Mat& src = test_mat[INPUT][0]; 956 Mat& dst = test_mat[REF_INPUT_OUTPUT][0]; 957 Mat& dst0 = test_mat[INPUT_OUTPUT][0]; 958 Mat mapx, mapy; 959 cvtest::initUndistortMap( test_mat[INPUT][1], test_mat[INPUT][2], dst.size(), mapx, mapy ); 960 Mat mask( dst.size(), CV_8U ); 961 test_remap( src, dst, mapx, mapy, &mask, interpolation ); 962 dst.setTo(Scalar::all(0), mask); 963 dst0.setTo(Scalar::all(0), mask); 964 } 965 966 967 class CV_UndistortMapTest : public cvtest::ArrayTest 968 { 969 public: 970 CV_UndistortMapTest(); 971 972 protected: 973 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 974 void run_func(); 975 int prepare_test_case( int test_case_idx ); 976 void prepare_to_validation( int /*test_case_idx*/ ); 977 double get_success_error_level( int test_case_idx, int i, int j ); 978 void fill_array( int test_case_idx, int i, int j, Mat& arr ); 979 980 private: 981 bool dualChannel; 982 }; 983 984 985 CV_UndistortMapTest::CV_UndistortMapTest() 986 { 987 test_array[INPUT].push_back(NULL); 988 test_array[INPUT].push_back(NULL); 989 test_array[OUTPUT].push_back(NULL); 990 test_array[OUTPUT].push_back(NULL); 991 test_array[REF_OUTPUT].push_back(NULL); 992 test_array[REF_OUTPUT].push_back(NULL); 993 994 element_wise_relative_error = false; 995 } 996 997 998 void CV_UndistortMapTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 999 { 1000 RNG& rng = ts->get_rng(); 1001 cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1002 int depth = cvtest::randInt(rng)%2 ? CV_64F : CV_32F; 1003 1004 CvSize sz = sizes[OUTPUT][0]; 1005 types[INPUT][0] = types[INPUT][1] = depth; 1006 dualChannel = cvtest::randInt(rng)%2 == 0; 1007 types[OUTPUT][0] = types[OUTPUT][1] = 1008 types[REF_OUTPUT][0] = types[REF_OUTPUT][1] = dualChannel ? CV_32FC2 : CV_32F; 1009 sizes[INPUT][0] = cvSize(3,3); 1010 sizes[INPUT][1] = cvtest::randInt(rng)%2 ? cvSize(4,1) : cvSize(1,4); 1011 1012 sz.width = MAX(sz.width,16); 1013 sz.height = MAX(sz.height,16); 1014 sizes[OUTPUT][0] = sizes[OUTPUT][1] = 1015 sizes[REF_OUTPUT][0] = sizes[REF_OUTPUT][1] = sz; 1016 } 1017 1018 1019 void CV_UndistortMapTest::fill_array( int test_case_idx, int i, int j, Mat& arr ) 1020 { 1021 if( i != INPUT ) 1022 cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr ); 1023 } 1024 1025 1026 void CV_UndistortMapTest::run_func() 1027 { 1028 CvMat a = test_mat[INPUT][0], k = test_mat[INPUT][1]; 1029 1030 if (!dualChannel ) 1031 cvInitUndistortMap( &a, &k, test_array[OUTPUT][0], test_array[OUTPUT][1] ); 1032 else 1033 cvInitUndistortMap( &a, &k, test_array[OUTPUT][0], 0 ); 1034 } 1035 1036 1037 double CV_UndistortMapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 1038 { 1039 return 1e-3; 1040 } 1041 1042 1043 int CV_UndistortMapTest::prepare_test_case( int test_case_idx ) 1044 { 1045 RNG& rng = ts->get_rng(); 1046 int code = cvtest::ArrayTest::prepare_test_case( test_case_idx ); 1047 const Mat& mapx = test_mat[OUTPUT][0]; 1048 double k[4], a[9] = {0,0,0,0,0,0,0,0,1}; 1049 double sz = MAX(mapx.rows, mapx.cols); 1050 Mat& _a0 = test_mat[INPUT][0], &_k0 = test_mat[INPUT][1]; 1051 Mat _a(3,3,CV_64F,a); 1052 Mat _k(_k0.rows,_k0.cols, CV_MAKETYPE(CV_64F,_k0.channels()),k); 1053 1054 if( code <= 0 ) 1055 return code; 1056 1057 double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7; 1058 a[2] = (mapx.cols - 1)*0.5 + cvtest::randReal(rng)*10 - 5; 1059 a[5] = (mapx.rows - 1)*0.5 + cvtest::randReal(rng)*10 - 5; 1060 a[0] = sz/(0.9 - cvtest::randReal(rng)*0.6); 1061 a[4] = aspect_ratio*a[0]; 1062 k[0] = cvtest::randReal(rng)*0.06 - 0.03; 1063 k[1] = cvtest::randReal(rng)*0.06 - 0.03; 1064 if( k[0]*k[1] > 0 ) 1065 k[1] = -k[1]; 1066 k[2] = cvtest::randReal(rng)*0.004 - 0.002; 1067 k[3] = cvtest::randReal(rng)*0.004 - 0.002; 1068 1069 _a.convertTo(_a0, _a0.depth()); 1070 _k.convertTo(_k0, _k0.depth()); 1071 1072 if (dualChannel) 1073 { 1074 test_mat[REF_OUTPUT][1] = Scalar::all(0); 1075 test_mat[OUTPUT][1] = Scalar::all(0); 1076 } 1077 1078 return code; 1079 } 1080 1081 1082 void CV_UndistortMapTest::prepare_to_validation( int ) 1083 { 1084 Mat mapx, mapy; 1085 cvtest::initUndistortMap( test_mat[INPUT][0], test_mat[INPUT][1], test_mat[REF_OUTPUT][0].size(), mapx, mapy ); 1086 if( !dualChannel ) 1087 { 1088 mapx.copyTo(test_mat[REF_OUTPUT][0]); 1089 mapy.copyTo(test_mat[REF_OUTPUT][1]); 1090 } 1091 else 1092 { 1093 Mat p[2] = {mapx, mapy}; 1094 cv::merge(p, 2, test_mat[REF_OUTPUT][0]); 1095 } 1096 } 1097 1098 ////////////////////////////// GetRectSubPix ///////////////////////////////// 1099 1100 static void 1101 test_getQuadrangeSubPix( const Mat& src, Mat& dst, double* a ) 1102 { 1103 int sstep = (int)(src.step / sizeof(float)); 1104 int scols = src.cols, srows = src.rows; 1105 1106 CV_Assert( src.depth() == CV_32F && src.type() == dst.type() ); 1107 1108 int cn = dst.channels(); 1109 1110 for( int y = 0; y < dst.rows; y++ ) 1111 for( int x = 0; x < dst.cols; x++ ) 1112 { 1113 float* d = dst.ptr<float>(y) + x*cn; 1114 float sx = (float)(a[0]*x + a[1]*y + a[2]); 1115 float sy = (float)(a[3]*x + a[4]*y + a[5]); 1116 int ix = cvFloor(sx), iy = cvFloor(sy); 1117 int dx = cn, dy = sstep; 1118 const float* s; 1119 sx -= ix; sy -= iy; 1120 1121 if( (unsigned)ix >= (unsigned)(scols-1) ) 1122 ix = ix < 0 ? 0 : scols - 1, sx = 0, dx = 0; 1123 if( (unsigned)iy >= (unsigned)(srows-1) ) 1124 iy = iy < 0 ? 0 : srows - 1, sy = 0, dy = 0; 1125 1126 s = src.ptr<float>(iy) + ix*cn; 1127 for( int k = 0; k < cn; k++, s++ ) 1128 { 1129 float t0 = s[0] + sx*(s[dx] - s[0]); 1130 float t1 = s[dy] + sx*(s[dy + dx] - s[dy]); 1131 d[k] = t0 + sy*(t1 - t0); 1132 } 1133 } 1134 } 1135 1136 1137 class CV_GetRectSubPixTest : public CV_ImgWarpBaseTest 1138 { 1139 public: 1140 CV_GetRectSubPixTest(); 1141 1142 protected: 1143 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 1144 void run_func(); 1145 int prepare_test_case( int test_case_idx ); 1146 void prepare_to_validation( int /*test_case_idx*/ ); 1147 double get_success_error_level( int test_case_idx, int i, int j ); 1148 void fill_array( int test_case_idx, int i, int j, Mat& arr ); 1149 1150 CvPoint2D32f center; 1151 bool test_cpp; 1152 }; 1153 1154 1155 CV_GetRectSubPixTest::CV_GetRectSubPixTest() : CV_ImgWarpBaseTest( false ) 1156 { 1157 //spatial_scale_zoom = spatial_scale_decimate; 1158 spatial_scale_decimate = spatial_scale_zoom; 1159 test_cpp = false; 1160 } 1161 1162 1163 void CV_GetRectSubPixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 1164 { 1165 RNG& rng = ts->get_rng(); 1166 CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1167 int src_depth = cvtest::randInt(rng) % 2, dst_depth; 1168 int cn = cvtest::randInt(rng) % 2 ? 3 : 1; 1169 CvSize src_size, dst_size; 1170 1171 dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F; 1172 if( src_depth < CV_32F && cvtest::randInt(rng) % 2 ) 1173 dst_depth = CV_32F; 1174 1175 types[INPUT][0] = CV_MAKETYPE(src_depth,cn); 1176 types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn); 1177 1178 src_size = sizes[INPUT][0]; 1179 dst_size.width = cvRound(sqrt(cvtest::randReal(rng)*src_size.width) + 1); 1180 dst_size.height = cvRound(sqrt(cvtest::randReal(rng)*src_size.height) + 1); 1181 dst_size.width = MIN(dst_size.width,src_size.width); 1182 dst_size.height = MIN(dst_size.width,src_size.height); 1183 sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dst_size; 1184 1185 center.x = (float)(cvtest::randReal(rng)*src_size.width); 1186 center.y = (float)(cvtest::randReal(rng)*src_size.height); 1187 interpolation = CV_INTER_LINEAR; 1188 1189 test_cpp = (cvtest::randInt(rng) & 256) == 0; 1190 } 1191 1192 1193 void CV_GetRectSubPixTest::fill_array( int test_case_idx, int i, int j, Mat& arr ) 1194 { 1195 if( i != INPUT ) 1196 CV_ImgWarpBaseTest::fill_array( test_case_idx, i, j, arr ); 1197 } 1198 1199 1200 void CV_GetRectSubPixTest::run_func() 1201 { 1202 if(!test_cpp) 1203 cvGetRectSubPix( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], center ); 1204 else 1205 { 1206 cv::Mat _out = cv::cvarrToMat(test_array[INPUT_OUTPUT][0]); 1207 cv::getRectSubPix( cv::cvarrToMat(test_array[INPUT][0]), _out.size(), center, _out, _out.type()); 1208 } 1209 } 1210 1211 1212 double CV_GetRectSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 1213 { 1214 int in_depth = test_mat[INPUT][0].depth(); 1215 int out_depth = test_mat[INPUT_OUTPUT][0].depth(); 1216 1217 return in_depth >= CV_32F ? 1e-3 : out_depth >= CV_32F ? 1e-2 : 1; 1218 } 1219 1220 1221 int CV_GetRectSubPixTest::prepare_test_case( int test_case_idx ) 1222 { 1223 return CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); 1224 } 1225 1226 1227 void CV_GetRectSubPixTest::prepare_to_validation( int /*test_case_idx*/ ) 1228 { 1229 Mat& src0 = test_mat[INPUT][0]; 1230 Mat& dst0 = test_mat[REF_INPUT_OUTPUT][0]; 1231 Mat src = src0, dst = dst0; 1232 int ftype = CV_MAKETYPE(CV_32F,src0.channels()); 1233 double a[] = { 1, 0, center.x - dst.cols*0.5 + 0.5, 1234 0, 1, center.y - dst.rows*0.5 + 0.5 }; 1235 if( src.depth() != CV_32F ) 1236 src0.convertTo(src, CV_32F); 1237 1238 if( dst.depth() != CV_32F ) 1239 dst.create(dst0.size(), ftype); 1240 1241 test_getQuadrangeSubPix( src, dst, a ); 1242 1243 if( dst.data != dst0.data ) 1244 dst.convertTo(dst0, dst0.depth()); 1245 } 1246 1247 1248 class CV_GetQuadSubPixTest : public CV_ImgWarpBaseTest 1249 { 1250 public: 1251 CV_GetQuadSubPixTest(); 1252 1253 protected: 1254 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); 1255 void run_func(); 1256 int prepare_test_case( int test_case_idx ); 1257 void prepare_to_validation( int /*test_case_idx*/ ); 1258 double get_success_error_level( int test_case_idx, int i, int j ); 1259 }; 1260 1261 1262 CV_GetQuadSubPixTest::CV_GetQuadSubPixTest() : CV_ImgWarpBaseTest( true ) 1263 { 1264 //spatial_scale_zoom = spatial_scale_decimate; 1265 spatial_scale_decimate = spatial_scale_zoom; 1266 } 1267 1268 1269 void CV_GetQuadSubPixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ) 1270 { 1271 int min_size = 4; 1272 CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); 1273 CvSize sz = sizes[INPUT][0], dsz; 1274 RNG& rng = ts->get_rng(); 1275 int msz, src_depth = cvtest::randInt(rng) % 2, dst_depth; 1276 int cn = cvtest::randInt(rng) % 2 ? 3 : 1; 1277 1278 dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F; 1279 if( src_depth < CV_32F && cvtest::randInt(rng) % 2 ) 1280 dst_depth = CV_32F; 1281 1282 types[INPUT][0] = CV_MAKETYPE(src_depth,cn); 1283 types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn); 1284 1285 sz.width = MAX(sz.width,min_size); 1286 sz.height = MAX(sz.height,min_size); 1287 sizes[INPUT][0] = sz; 1288 msz = MIN( sz.width, sz.height ); 1289 1290 dsz.width = cvRound(sqrt(cvtest::randReal(rng)*msz) + 1); 1291 dsz.height = cvRound(sqrt(cvtest::randReal(rng)*msz) + 1); 1292 dsz.width = MIN(dsz.width,msz); 1293 dsz.height = MIN(dsz.width,msz); 1294 dsz.width = MAX(dsz.width,min_size); 1295 dsz.height = MAX(dsz.height,min_size); 1296 sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dsz; 1297 sizes[INPUT][1] = cvSize( 3, 2 ); 1298 } 1299 1300 1301 void CV_GetQuadSubPixTest::run_func() 1302 { 1303 CvMat mtx = test_mat[INPUT][1]; 1304 cvGetQuadrangleSubPix( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &mtx ); 1305 } 1306 1307 1308 double CV_GetQuadSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) 1309 { 1310 int in_depth = test_mat[INPUT][0].depth(); 1311 //int out_depth = test_mat[INPUT_OUTPUT][0].depth(); 1312 1313 return in_depth >= CV_32F ? 1e-2 : 4; 1314 } 1315 1316 1317 int CV_GetQuadSubPixTest::prepare_test_case( int test_case_idx ) 1318 { 1319 RNG& rng = ts->get_rng(); 1320 int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); 1321 const Mat& src = test_mat[INPUT][0]; 1322 Mat& mat = test_mat[INPUT][1]; 1323 CvPoint2D32f center; 1324 double scale, angle; 1325 1326 if( code <= 0 ) 1327 return code; 1328 1329 double a[6]; 1330 Mat A( 2, 3, CV_64FC1, a ); 1331 1332 center.x = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.cols); 1333 center.y = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.rows); 1334 angle = cvtest::randReal(rng)*360; 1335 scale = cvtest::randReal(rng)*0.2 + 0.9; 1336 1337 // y = Ax + b -> x = A^-1(y - b) = A^-1*y - A^-1*b 1338 scale = 1./scale; 1339 angle = angle*(CV_PI/180.); 1340 a[0] = a[4] = cos(angle)*scale; 1341 a[1] = sin(angle)*scale; 1342 a[3] = -a[1]; 1343 a[2] = center.x - a[0]*center.x - a[1]*center.y; 1344 a[5] = center.y - a[3]*center.x - a[4]*center.y; 1345 A.convertTo( mat, mat.depth() ); 1346 1347 return code; 1348 } 1349 1350 1351 void CV_GetQuadSubPixTest::prepare_to_validation( int /*test_case_idx*/ ) 1352 { 1353 Mat& src0 = test_mat[INPUT][0]; 1354 Mat& dst0 = test_mat[REF_INPUT_OUTPUT][0]; 1355 Mat src = src0, dst = dst0; 1356 int ftype = CV_MAKETYPE(CV_32F,src0.channels()); 1357 double a[6], dx = (dst0.cols - 1)*0.5, dy = (dst0.rows - 1)*0.5; 1358 Mat A( 2, 3, CV_64F, a ); 1359 1360 if( src.depth() != CV_32F ) 1361 src0.convertTo(src, CV_32F); 1362 1363 if( dst.depth() != CV_32F ) 1364 dst.create(dst0.size(), ftype); 1365 1366 test_mat[INPUT][1].convertTo( A, CV_64F ); 1367 a[2] -= a[0]*dx + a[1]*dy; 1368 a[5] -= a[3]*dx + a[4]*dy; 1369 test_getQuadrangeSubPix( src, dst, a ); 1370 1371 if( dst.data != dst0.data ) 1372 dst.convertTo(dst0, dst0.depth()); 1373 } 1374 1375 TEST(Imgproc_cvWarpAffine, regression) 1376 { 1377 IplImage* src = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1); 1378 IplImage* dst = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1); 1379 1380 float m[6]; 1381 CvMat M = cvMat( 2, 3, CV_32F, m ); 1382 int w = src->width; 1383 int h = src->height; 1384 cv2DRotationMatrix(cvPoint2D32f(w*0.5f, h*0.5f), 45.0, 1.0, &M); 1385 cvWarpAffine(src, dst, &M); 1386 } 1387 1388 TEST(Imgproc_fitLine_vector_3d, regression) 1389 { 1390 std::vector<Point3f> points_vector; 1391 1392 Point3f p21(4,4,4); 1393 Point3f p22(8,8,8); 1394 1395 points_vector.push_back(p21); 1396 points_vector.push_back(p22); 1397 1398 std::vector<float> line; 1399 1400 cv::fitLine(points_vector, line, CV_DIST_L2, 0 ,0 ,0); 1401 1402 ASSERT_EQ(line.size(), (size_t)6); 1403 1404 } 1405 1406 TEST(Imgproc_fitLine_vector_2d, regression) 1407 { 1408 std::vector<Point2f> points_vector; 1409 1410 Point2f p21(4,4); 1411 Point2f p22(8,8); 1412 Point2f p23(16,16); 1413 1414 points_vector.push_back(p21); 1415 points_vector.push_back(p22); 1416 points_vector.push_back(p23); 1417 1418 std::vector<float> line; 1419 1420 cv::fitLine(points_vector, line, CV_DIST_L2, 0 ,0 ,0); 1421 1422 ASSERT_EQ(line.size(), (size_t)4); 1423 } 1424 1425 TEST(Imgproc_fitLine_Mat_2dC2, regression) 1426 { 1427 cv::Mat mat1 = Mat::zeros(3, 1, CV_32SC2); 1428 std::vector<float> line1; 1429 1430 cv::fitLine(mat1, line1, CV_DIST_L2, 0 ,0 ,0); 1431 1432 ASSERT_EQ(line1.size(), (size_t)4); 1433 } 1434 1435 TEST(Imgproc_fitLine_Mat_2dC1, regression) 1436 { 1437 cv::Matx<int, 3, 2> mat2; 1438 std::vector<float> line2; 1439 1440 cv::fitLine(mat2, line2, CV_DIST_L2, 0 ,0 ,0); 1441 1442 ASSERT_EQ(line2.size(), (size_t)4); 1443 } 1444 1445 TEST(Imgproc_fitLine_Mat_3dC3, regression) 1446 { 1447 cv::Mat mat1 = Mat::zeros(2, 1, CV_32SC3); 1448 std::vector<float> line1; 1449 1450 cv::fitLine(mat1, line1, CV_DIST_L2, 0 ,0 ,0); 1451 1452 ASSERT_EQ(line1.size(), (size_t)6); 1453 } 1454 1455 TEST(Imgproc_fitLine_Mat_3dC1, regression) 1456 { 1457 cv::Mat mat2 = Mat::zeros(2, 3, CV_32SC1); 1458 std::vector<float> line2; 1459 1460 cv::fitLine(mat2, line2, CV_DIST_L2, 0 ,0 ,0); 1461 1462 ASSERT_EQ(line2.size(), (size_t)6); 1463 } 1464 1465 TEST(Imgproc_resize_area, regression) 1466 { 1467 static ushort input_data[16 * 16] = { 1468 90, 94, 80, 3, 231, 2, 186, 245, 188, 165, 10, 19, 201, 169, 8, 228, 1469 86, 5, 203, 120, 136, 185, 24, 94, 81, 150, 163, 137, 88, 105, 132, 132, 1470 236, 48, 250, 218, 19, 52, 54, 221, 159, 112, 45, 11, 152, 153, 112, 134, 1471 78, 133, 136, 83, 65, 76, 82, 250, 9, 235, 148, 26, 236, 179, 200, 50, 1472 99, 51, 103, 142, 201, 65, 176, 33, 49, 226, 177, 109, 46, 21, 67, 130, 1473 54, 125, 107, 154, 145, 51, 199, 189, 161, 142, 231, 240, 139, 162, 240, 22, 1474 231, 86, 79, 106, 92, 47, 146, 156, 36, 207, 71, 33, 2, 244, 221, 71, 1475 44, 127, 71, 177, 75, 126, 68, 119, 200, 129, 191, 251, 6, 236, 247, 6, 1476 133, 175, 56, 239, 147, 221, 243, 154, 242, 82, 106, 99, 77, 158, 60, 229, 1477 2, 42, 24, 174, 27, 198, 14, 204, 246, 251, 141, 31, 114, 163, 29, 147, 1478 121, 53, 74, 31, 147, 189, 42, 98, 202, 17, 228, 123, 209, 40, 77, 49, 1479 112, 203, 30, 12, 205, 25, 19, 106, 145, 185, 163, 201, 237, 223, 247, 38, 1480 33, 105, 243, 117, 92, 179, 204, 248, 160, 90, 73, 126, 2, 41, 213, 204, 1481 6, 124, 195, 201, 230, 187, 210, 167, 48, 79, 123, 159, 145, 218, 105, 209, 1482 240, 152, 136, 235, 235, 164, 157, 9, 152, 38, 27, 209, 120, 77, 238, 196, 1483 240, 233, 10, 241, 90, 67, 12, 79, 0, 43, 58, 27, 83, 199, 190, 182}; 1484 1485 static ushort expected_data[5 * 5] = { 1486 120, 100, 151, 101, 130, 1487 106, 115, 141, 130, 127, 1488 91, 136, 170, 114, 140, 1489 104, 122, 131, 147, 133, 1490 161, 163, 70, 107, 182 1491 }; 1492 1493 cv::Mat src(16, 16, CV_16UC1, input_data); 1494 cv::Mat expected(5, 5, CV_16UC1, expected_data); 1495 cv::Mat actual(expected.size(), expected.type()); 1496 1497 cv::resize(src, actual, cv::Size(), 0.3, 0.3, INTER_AREA); 1498 1499 ASSERT_EQ(actual.type(), expected.type()); 1500 ASSERT_EQ(actual.size(), expected.size()); 1501 1502 Mat diff; 1503 absdiff(actual, expected, diff); 1504 1505 Mat one_channel_diff = diff; //.reshape(1); 1506 1507 float elem_diff = 1.0f; 1508 Size dsize = actual.size(); 1509 bool next = true; 1510 for (int dy = 0; dy < dsize.height && next; ++dy) 1511 { 1512 ushort* eD = expected.ptr<ushort>(dy); 1513 ushort* aD = actual.ptr<ushort>(dy); 1514 1515 for (int dx = 0; dx < dsize.width && next; ++dx) 1516 if (fabs(static_cast<float>(aD[dx] - eD[dx])) > elem_diff) 1517 { 1518 cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Inf norm: %f\n", static_cast<float>(norm(actual, expected, NORM_INF))); 1519 cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Error in : (%d, %d)\n", dx, dy); 1520 1521 const int radius = 3; 1522 int rmin = MAX(dy - radius, 0), rmax = MIN(dy + radius, dsize.height); 1523 int cmin = MAX(dx - radius, 0), cmax = MIN(dx + radius, dsize.width); 1524 1525 std::cout << "Abs diff:" << std::endl << diff << std::endl; 1526 std::cout << "actual result:\n" << actual(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; 1527 std::cout << "expected result:\n" << expected(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; 1528 1529 next = false; 1530 } 1531 } 1532 1533 ASSERT_EQ(cvtest::norm(one_channel_diff, cv::NORM_INF), 0); 1534 } 1535 1536 1537 ////////////////////////////////////////////////////////////////////////// 1538 1539 TEST(Imgproc_Resize, accuracy) { CV_ResizeTest test; test.safe_run(); } 1540 TEST(Imgproc_WarpAffine, accuracy) { CV_WarpAffineTest test; test.safe_run(); } 1541 TEST(Imgproc_WarpPerspective, accuracy) { CV_WarpPerspectiveTest test; test.safe_run(); } 1542 TEST(Imgproc_Remap, accuracy) { CV_RemapTest test; test.safe_run(); } 1543 TEST(Imgproc_Undistort, accuracy) { CV_UndistortTest test; test.safe_run(); } 1544 TEST(Imgproc_InitUndistortMap, accuracy) { CV_UndistortMapTest test; test.safe_run(); } 1545 TEST(Imgproc_GetRectSubPix, accuracy) { CV_GetRectSubPixTest test; test.safe_run(); } 1546 TEST(Imgproc_GetQuadSubPix, accuracy) { CV_GetQuadSubPixTest test; test.safe_run(); } 1547 1548 ////////////////////////////////////////////////////////////////////////// 1549 1550 template <typename T, typename WT> 1551 struct IntCast 1552 { 1553 T operator() (WT val) const 1554 { 1555 return cv::saturate_cast<T>(val >> 2); 1556 } 1557 }; 1558 1559 template <typename T, typename WT> 1560 struct FltCast 1561 { 1562 T operator() (WT val) const 1563 { 1564 return cv::saturate_cast<T>(val * 0.25); 1565 } 1566 }; 1567 1568 template <typename T, typename WT, int one, typename CastOp> 1569 void resizeArea(const cv::Mat & src, cv::Mat & dst) 1570 { 1571 int cn = src.channels(); 1572 CastOp castOp; 1573 1574 for (int y = 0; y < dst.rows; ++y) 1575 { 1576 const T * sptr0 = src.ptr<T>(y << 1); 1577 const T * sptr1 = src.ptr<T>((y << 1) + 1); 1578 T * dptr = dst.ptr<T>(y); 1579 1580 for (int x = 0; x < dst.cols * cn; x += cn) 1581 { 1582 int x1 = x << 1; 1583 1584 for (int c = 0; c < cn; ++c) 1585 { 1586 WT sum = WT(sptr0[x1 + c]) + WT(sptr0[x1 + c + cn]); 1587 sum += WT(sptr1[x1 + c]) + WT(sptr1[x1 + c + cn]) + (WT)(one); 1588 1589 dptr[x + c] = castOp(sum); 1590 } 1591 } 1592 } 1593 } 1594 1595 TEST(Resize, Area_half) 1596 { 1597 const int size = 1000; 1598 int types[] = { CV_8UC1, CV_8UC4, 1599 CV_16UC1, CV_16UC4, 1600 CV_16SC1, CV_16SC3, CV_16SC4, 1601 CV_32FC1, CV_32FC4 }; 1602 1603 cv::RNG rng(17); 1604 1605 for (int i = 0, _size = sizeof(types) / sizeof(types[0]); i < _size; ++i) 1606 { 1607 int type = types[i], depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); 1608 const float eps = depth <= CV_32S ? 0 : 7e-5f; 1609 1610 SCOPED_TRACE(depth); 1611 SCOPED_TRACE(cn); 1612 1613 cv::Mat src(size, size, type), dst_actual(size >> 1, size >> 1, type), 1614 dst_reference(size >> 1, size >> 1, type); 1615 1616 rng.fill(src, cv::RNG::UNIFORM, -1000, 1000, true); 1617 1618 if (depth == CV_8U) 1619 resizeArea<uchar, ushort, 2, IntCast<uchar, ushort> >(src, dst_reference); 1620 else if (depth == CV_16U) 1621 resizeArea<ushort, uint, 2, IntCast<ushort, uint> >(src, dst_reference); 1622 else if (depth == CV_16S) 1623 resizeArea<short, int, 2, IntCast<short, int> >(src, dst_reference); 1624 else if (depth == CV_32F) 1625 resizeArea<float, float, 0, FltCast<float, float> >(src, dst_reference); 1626 else 1627 CV_Assert(0); 1628 1629 cv::resize(src, dst_actual, dst_actual.size(), 0, 0, cv::INTER_AREA); 1630 1631 ASSERT_GE(eps, cvtest::norm(dst_reference, dst_actual, cv::NORM_INF)); 1632 } 1633 } 1634 1635 TEST(Imgproc_Warp, multichannel) 1636 { 1637 RNG& rng = theRNG(); 1638 for( int iter = 0; iter < 30; iter++ ) 1639 { 1640 int width = rng.uniform(3, 333); 1641 int height = rng.uniform(3, 333); 1642 int cn = rng.uniform(1, 10); 1643 Mat src(height, width, CV_8UC(cn)), dst; 1644 //randu(src, 0, 256); 1645 src.setTo(0.); 1646 1647 Mat rot = getRotationMatrix2D(Point2f(0.f, 0.f), 1, 1); 1648 warpAffine(src, dst, rot, src.size()); 1649 ASSERT_EQ(0.0, norm(dst, NORM_INF)); 1650 Mat rot2 = Mat::eye(3, 3, rot.type()); 1651 rot.copyTo(rot2.rowRange(0, 2)); 1652 warpPerspective(src, dst, rot2, src.size()); 1653 ASSERT_EQ(0.0, norm(dst, NORM_INF)); 1654 } 1655 } 1656 1657 TEST(Imgproc_GetAffineTransform, singularity) 1658 { 1659 Point2f A_sample[3]; 1660 A_sample[0] = Point2f(8.f, 9.f); 1661 A_sample[1] = Point2f(40.f, 41.f); 1662 A_sample[2] = Point2f(47.f, 48.f); 1663 Point2f B_sample[3]; 1664 B_sample[0] = Point2f(7.37465f, 11.8295f); 1665 B_sample[1] = Point2f(15.0113f, 12.8994f); 1666 B_sample[2] = Point2f(38.9943f, 9.56297f); 1667 Mat trans = getAffineTransform(A_sample, B_sample); 1668 ASSERT_EQ(0.0, norm(trans, NORM_INF)); 1669 } 1670 1671 TEST(Imgproc_Remap, DISABLED_memleak) 1672 { 1673 Mat src; 1674 const int N = 400; 1675 src.create(N, N, CV_8U); 1676 randu(src, 0, 256); 1677 Mat map_x, map_y, dst; 1678 dst.create( src.size(), src.type() ); 1679 map_x.create( src.size(), CV_32FC1 ); 1680 map_y.create( src.size(), CV_32FC1 ); 1681 randu(map_x, 0., N+0.); 1682 randu(map_y, 0., N+0.); 1683 1684 for( int iter = 0; iter < 10000; iter++ ) 1685 { 1686 if(iter % 100 == 0) 1687 { 1688 putchar('.'); 1689 fflush(stdout); 1690 } 1691 remap(src, dst, map_x, map_y, CV_INTER_LINEAR); 1692 } 1693 } 1694 1695 /* End of file. */ 1696