/*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // // By downloading, copying, installing or using the software you agree to this license. // If you do not agree to this license, do not download, install, // copy or use the software. // // // Intel License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000, Intel Corporation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistribution's of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistribution's in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // * The name of Intel Corporation may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and // any express or implied warranties, including, but not limited to, the implied // warranties of merchantability and fitness for a particular purpose are disclaimed. // In no event shall the Intel Corporation or contributors be liable for any direct, // indirect, incidental, special, exemplary, or consequential damages // (including, but not limited to, procurement of substitute goods or services; // loss of use, data, or profits; or business interruption) however caused // and on any theory of liability, whether in contract, strict liability, // or tort (including negligence or otherwise) arising in any way out of // the use of this software, even if advised of the possibility of such damage. // //M*/ #include "cvtest.h" static const int imgwarp_depths[] = { CV_8U, CV_16U, CV_32F, -1 }; static const int imgwarp_channels[] = { 1, 3, 4, -1 }; static const CvSize imgwarp_sizes[] = {{320, 240}, {1024,768}, {-1,-1}}; static const double imgwarp_resize_coeffs[] = { 0.5, 0.333, 2, 2.9 }; static const char* imgwarp_resize_methods[] = { "nearest", "linear", "cubic", "area", 0 }; static const char* imgwarp_resize_param_names[] = { "method", "coeff", "size", "channels", "depth", 0 }; static const double imgwarp_affine_rotate_scale[][4] = { {0.5,0.5,30.,1.4}, {0.5,0.5,-130,0.4}, {-1,-1,-1,-1} }; static const char* imgwarp_affine_param_names[] = { "rotate_scale", "size", "channels", "depth", 0 }; static const double imgwarp_perspective_shift_vtx[][8] = { {0.03,0.01,0.04,0.02,0.01,0.01,0.01,0.02}, {-1} }; static const char* imgwarp_perspective_param_names[] = { "shift_vtx", "size", "channels", "depth", 0 }; class CV_ImgWarpBaseTestImpl : public CvArrTest { public: CV_ImgWarpBaseTestImpl( const char* test_name, const char* test_funcs, bool warp_matrix ); protected: int read_params( CvFileStorage* fs ); int prepare_test_case( int test_case_idx ); void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ); void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high ); void fill_array( int test_case_idx, int i, int j, CvMat* arr ); int interpolation; int max_interpolation; double spatial_scale_zoom, spatial_scale_decimate; }; CV_ImgWarpBaseTestImpl::CV_ImgWarpBaseTestImpl( const char* test_name, const char* test_funcs, bool warp_matrix ) : CvArrTest( test_name, test_funcs, "" ) { test_array[INPUT].push(NULL); if( warp_matrix ) test_array[INPUT].push(NULL); test_array[INPUT_OUTPUT].push(NULL); test_array[REF_INPUT_OUTPUT].push(NULL); max_interpolation = 5; interpolation = 0; element_wise_relative_error = false; spatial_scale_zoom = 0.01; spatial_scale_decimate = 0.005; size_list = whole_size_list = imgwarp_sizes; depth_list = imgwarp_depths; cn_list = imgwarp_channels; default_timing_param_names = 0; } int CV_ImgWarpBaseTestImpl::read_params( CvFileStorage* fs ) { int code = CvArrTest::read_params( fs ); return code; } void CV_ImgWarpBaseTestImpl::get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high ) { CvArrTest::get_minmax_bounds( i, j, type, low, high ); if( CV_MAT_DEPTH(type) == CV_32F ) { *low = cvScalarAll(-10.); *high = cvScalarAll(10); } } void CV_ImgWarpBaseTestImpl::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ) { CvRNG* rng = ts->get_rng(); int depth = cvTsRandInt(rng) % 3; int cn = cvTsRandInt(rng) % 3 + 1; CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : CV_32F; cn += cn == 2; types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn); if( test_array[INPUT].size() > 1 ) types[INPUT][1] = cvTsRandInt(rng) & 1 ? CV_32FC1 : CV_64FC1; interpolation = cvTsRandInt(rng) % max_interpolation; } void CV_ImgWarpBaseTestImpl::fill_array( int test_case_idx, int i, int j, CvMat* arr ) { if( i != INPUT || j != 0 ) CvArrTest::fill_array( test_case_idx, i, j, arr ); } int CV_ImgWarpBaseTestImpl::prepare_test_case( int test_case_idx ) { int code = CvArrTest::prepare_test_case( test_case_idx ); CvMat* img = &test_mat[INPUT][0]; int i, j, cols = img->cols; int type = CV_MAT_TYPE(img->type), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); double scale = depth == CV_16U ? 1000. : 255.*0.5; double space_scale = spatial_scale_decimate; float* buffer; if( code <= 0 ) return code; if( test_mat[INPUT_OUTPUT][0].cols >= img->cols && test_mat[INPUT_OUTPUT][0].rows >= img->rows ) space_scale = spatial_scale_zoom; buffer = (float*)cvAlloc( img->cols*cn*sizeof(buffer[0]) ); for( i = 0; i < img->rows; i++ ) { uchar* ptr = img->data.ptr + i*img->step; switch( cn ) { case 1: for( j = 0; j < cols; j++ ) buffer[j] = (float)((sin((i+1)*space_scale)*sin((j+1)*space_scale)+1.)*scale); break; case 2: for( j = 0; j < cols; j++ ) { buffer[j*2] = (float)((sin((i+1)*space_scale)+1.)*scale); buffer[j*2+1] = (float)((sin((i+j)*space_scale)+1.)*scale); } break; case 3: for( j = 0; j < cols; j++ ) { buffer[j*3] = (float)((sin((i+1)*space_scale)+1.)*scale); buffer[j*3+1] = (float)((sin(j*space_scale)+1.)*scale); buffer[j*3+2] = (float)((sin((i+j)*space_scale)+1.)*scale); } break; case 4: for( j = 0; j < cols; j++ ) { buffer[j*4] = (float)((sin((i+1)*space_scale)+1.)*scale); buffer[j*4+1] = (float)((sin(j*space_scale)+1.)*scale); buffer[j*4+2] = (float)((sin((i+j)*space_scale)+1.)*scale); buffer[j*4+3] = (float)((sin((i-j)*space_scale)+1.)*scale); } break; default: assert(0); } switch( depth ) { case CV_8U: for( j = 0; j < cols*cn; j++ ) ptr[j] = (uchar)cvRound(buffer[j]); break; case CV_16U: for( j = 0; j < cols*cn; j++ ) ((ushort*)ptr)[j] = (ushort)cvRound(buffer[j]); break; case CV_32F: for( j = 0; j < cols*cn; j++ ) ((float*)ptr)[j] = (float)buffer[j]; break; default: assert(0); } } cvFree( &buffer ); return code; } CV_ImgWarpBaseTestImpl imgwarp_base( "warp", "", false ); class CV_ImgWarpBaseTest : public CV_ImgWarpBaseTestImpl { public: CV_ImgWarpBaseTest( const char* test_name, const char* test_funcs, bool warp_matrix ); }; CV_ImgWarpBaseTest::CV_ImgWarpBaseTest( const char* test_name, const char* test_funcs, bool warp_matrix ) : CV_ImgWarpBaseTestImpl( test_name, test_funcs, warp_matrix ) { size_list = whole_size_list = 0; depth_list = 0; cn_list = 0; } ///////////////////////// class CV_ResizeTest : public CV_ImgWarpBaseTest { public: CV_ResizeTest(); protected: void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ); void run_func(); void prepare_to_validation( int /*test_case_idx*/ ); double get_success_error_level( int test_case_idx, int i, int j ); int write_default_params(CvFileStorage* fs); void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ); void print_timing_params( int test_case_idx, char* ptr, int params_left ); }; CV_ResizeTest::CV_ResizeTest() : CV_ImgWarpBaseTest( "warp-resize", "cvResize", false ) { default_timing_param_names = imgwarp_resize_param_names; } int CV_ResizeTest::write_default_params( CvFileStorage* fs ) { int code = CV_ImgWarpBaseTest::write_default_params( fs ); if( code < 0 ) return code; if( ts->get_testing_mode() == CvTS::TIMING_MODE ) { start_write_param( fs ); write_real_list( fs, "coeff", imgwarp_resize_coeffs, CV_DIM(imgwarp_resize_coeffs) ); write_string_list( fs, "method", imgwarp_resize_methods ); } return code; } void CV_ResizeTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ) { CvRNG* rng = ts->get_rng(); CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); CvSize sz; sz.width = (cvTsRandInt(rng) % sizes[INPUT][0].width) + 1; sz.height = (cvTsRandInt(rng) % sizes[INPUT][0].height) + 1; if( cvTsRandInt(rng) & 1 ) { int xfactor = cvTsRandInt(rng) % 10 + 1; int yfactor = cvTsRandInt(rng) % 10 + 1; if( cvTsRandInt(rng) & 1 ) yfactor = xfactor; sz.width = sizes[INPUT][0].width / xfactor; sz.width = MAX(sz.width,1); sz.height = sizes[INPUT][0].height / yfactor; sz.height = MAX(sz.height,1); sizes[INPUT][0].width = sz.width * xfactor; sizes[INPUT][0].height = sz.height * yfactor; } if( cvTsRandInt(rng) & 1 ) sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = sz; else { sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = sizes[INPUT][0]; sizes[INPUT][0] = sz; } if( interpolation == 4 && (MIN(sizes[INPUT][0].width,sizes[INPUT_OUTPUT][0].width) < 4 || MIN(sizes[INPUT][0].height,sizes[INPUT_OUTPUT][0].height) < 4)) interpolation = 2; } void CV_ResizeTest::get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ) { CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types, whole_sizes, are_images ); const char* method_str = cvReadString( find_timing_param( "method" ), "linear" ); double coeff = cvReadReal( find_timing_param( "coeff" ), 1. ); CvSize size = sizes[INPUT][0]; size.width = cvRound(size.width*coeff); size.height = cvRound(size.height*coeff); sizes[INPUT_OUTPUT][0] = whole_sizes[INPUT_OUTPUT][0] = size; interpolation = strcmp( method_str, "nearest" ) == 0 ? CV_INTER_NN : strcmp( method_str, "linear" ) == 0 ? CV_INTER_LINEAR : strcmp( method_str, "cubic" ) == 0 ? CV_INTER_CUBIC : CV_INTER_AREA; } void CV_ResizeTest::print_timing_params( int test_case_idx, char* ptr, int params_left ) { sprintf( ptr, "coeff=%.3f,", cvReadReal( find_timing_param( "coeff" ), 1. ) ); ptr += strlen(ptr); sprintf( ptr, "method=%s,", cvReadString( find_timing_param( "method" ), "linear" ) ); ptr += strlen(ptr); params_left -= 2; CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left ); } void CV_ResizeTest::run_func() { cvResize( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], interpolation ); } double CV_ResizeTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) { int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type); return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 1e-1; } void CV_ResizeTest::prepare_to_validation( int /*test_case_idx*/ ) { CvMat* src = &test_mat[INPUT][0]; CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0]; int i, j, k; CvMat* x_idx = cvCreateMat( 1, dst->cols, CV_32SC1 ); CvMat* y_idx = cvCreateMat( 1, dst->rows, CV_32SC1 ); int* x_tab = x_idx->data.i; int elem_size = CV_ELEM_SIZE(src->type); int drows = dst->rows, dcols = dst->cols; if( interpolation == CV_INTER_NN ) { for( j = 0; j < dcols; j++ ) { int t = (j*src->cols*2 + MIN(src->cols,dcols) - 1)/(dcols*2); t -= t >= src->cols; x_idx->data.i[j] = t*elem_size; } for( j = 0; j < drows; j++ ) { int t = (j*src->rows*2 + MIN(src->rows,drows) - 1)/(drows*2); t -= t >= src->rows; y_idx->data.i[j] = t; } } else { double scale_x = (double)src->cols/dcols; double scale_y = (double)src->rows/drows; for( j = 0; j < dcols; j++ ) { double f = ((j+0.5)*scale_x - 0.5); i = cvRound(f); x_idx->data.i[j] = (i < 0 ? 0 : i >= src->cols ? src->cols - 1 : i)*elem_size; } for( j = 0; j < drows; j++ ) { double f = ((j+0.5)*scale_y - 0.5); i = cvRound(f); y_idx->data.i[j] = i < 0 ? 0 : i >= src->rows ? src->rows - 1 : i; } } for( i = 0; i < drows; i++ ) { uchar* dptr = dst->data.ptr + dst->step*i; const uchar* sptr0 = src->data.ptr + src->step*y_idx->data.i[i]; for( j = 0; j < dcols; j++, dptr += elem_size ) { const uchar* sptr = sptr0 + x_tab[j]; for( k = 0; k < elem_size; k++ ) dptr[k] = sptr[k]; } } cvReleaseMat( &x_idx ); cvReleaseMat( &y_idx ); } //CV_ResizeTest warp_resize_test; ///////////////////////// void cvTsRemap( const CvMat* src, CvMat* dst, const CvMat* mapx, const CvMat* mapy, CvMat* mask, int interpolation=CV_INTER_LINEAR ) { int x, y, k; int drows = dst->rows, dcols = dst->cols; int srows = src->rows, scols = src->cols; uchar* sptr0 = src->data.ptr; int depth = CV_MAT_DEPTH(src->type), cn = CV_MAT_CN(src->type); int elem_size = CV_ELEM_SIZE(src->type); int step = src->step / CV_ELEM_SIZE(depth); int delta; if( interpolation != CV_INTER_CUBIC ) { delta = 0; scols -= 1; srows -= 1; } else { delta = 1; scols = MAX(scols - 3, 0); srows = MAX(srows - 3, 0); } int scols1 = MAX(scols - 2, 0); int srows1 = MAX(srows - 2, 0); if( mask ) cvTsZero(mask); for( y = 0; y < drows; y++ ) { uchar* dptr = dst->data.ptr + dst->step*y; const float* mx = (const float*)(mapx->data.ptr + mapx->step*y); const float* my = (const float*)(mapy->data.ptr + mapy->step*y); uchar* m = mask ? mask->data.ptr + mask->step*y : 0; for( x = 0; x < dcols; x++, dptr += elem_size ) { float xs = mx[x]; float ys = my[x]; int ixs = cvFloor(xs); int iys = cvFloor(ys); if( (unsigned)(ixs - delta - 1) >= (unsigned)scols1 || (unsigned)(iys - delta - 1) >= (unsigned)srows1 ) { if( m ) m[x] = 1; if( (unsigned)(ixs - delta) >= (unsigned)scols || (unsigned)(iys - delta) >= (unsigned)srows ) continue; } xs -= ixs; ys -= iys; switch( depth ) { case CV_8U: { const uchar* sptr = sptr0 + iys*step + ixs*cn; for( k = 0; k < cn; k++ ) { float v00 = sptr[k]; float v01 = sptr[cn + k]; float v10 = sptr[step + k]; float v11 = sptr[step + cn + k]; v00 = v00 + xs*(v01 - v00); v10 = v10 + xs*(v11 - v10); v00 = v00 + ys*(v10 - v00); dptr[k] = (uchar)cvRound(v00); } } break; case CV_16U: { const ushort* sptr = (const ushort*)sptr0 + iys*step + ixs*cn; for( k = 0; k < cn; k++ ) { float v00 = sptr[k]; float v01 = sptr[cn + k]; float v10 = sptr[step + k]; float v11 = sptr[step + cn + k]; v00 = v00 + xs*(v01 - v00); v10 = v10 + xs*(v11 - v10); v00 = v00 + ys*(v10 - v00); ((ushort*)dptr)[k] = (ushort)cvRound(v00); } } break; case CV_32F: { const float* sptr = (const float*)sptr0 + iys*step + ixs*cn; for( k = 0; k < cn; k++ ) { float v00 = sptr[k]; float v01 = sptr[cn + k]; float v10 = sptr[step + k]; float v11 = sptr[step + cn + k]; v00 = v00 + xs*(v01 - v00); v10 = v10 + xs*(v11 - v10); v00 = v00 + ys*(v10 - v00); ((float*)dptr)[k] = (float)v00; } } break; default: assert(0); } } } } ///////////////////////// class CV_WarpAffineTest : public CV_ImgWarpBaseTest { public: CV_WarpAffineTest(); protected: void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ); void run_func(); int prepare_test_case( int test_case_idx ); void prepare_to_validation( int /*test_case_idx*/ ); double get_success_error_level( int test_case_idx, int i, int j ); int write_default_params(CvFileStorage* fs); void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ); void print_timing_params( int test_case_idx, char* ptr, int params_left ); }; CV_WarpAffineTest::CV_WarpAffineTest() : CV_ImgWarpBaseTest( "warp-affine", "cvWarpAffine", true ) { //spatial_scale_zoom = spatial_scale_decimate; test_array[TEMP].push(NULL); test_array[TEMP].push(NULL); spatial_scale_decimate = spatial_scale_zoom; default_timing_param_names = imgwarp_affine_param_names; } int CV_WarpAffineTest::write_default_params( CvFileStorage* fs ) { int code = CV_ImgWarpBaseTest::write_default_params( fs ); if( code < 0 ) return code; if( ts->get_testing_mode() == CvTS::TIMING_MODE ) { int i; start_write_param( fs ); cvStartWriteStruct( fs, "rotate_scale", CV_NODE_SEQ+CV_NODE_FLOW ); for( i = 0; imgwarp_affine_rotate_scale[i][0] >= 0; i++ ) { cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW ); cvWriteRawData( fs, imgwarp_affine_rotate_scale[i], 4, "d" ); cvEndWriteStruct(fs); } cvEndWriteStruct(fs); } return code; } void CV_WarpAffineTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ) { CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); CvSize sz = sizes[INPUT][0]; // run for the second time to get output of a different size CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); sizes[INPUT][0] = sz; sizes[INPUT][1] = cvSize( 3, 2 ); sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT_OUTPUT][0]; types[TEMP][0] = types[TEMP][1] = CV_32FC1; } void CV_WarpAffineTest::get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ) { CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types, whole_sizes, are_images ); sizes[INPUT][1] = whole_sizes[INPUT][1] = cvSize(3,2); sizes[TEMP][0] = whole_sizes[TEMP][0] = sizes[TEMP][1] = whole_sizes[TEMP][1] = cvSize(0,0); types[INPUT][1] = CV_64FC1; interpolation = CV_INTER_LINEAR; } void CV_WarpAffineTest::print_timing_params( int test_case_idx, char* ptr, int params_left ) { double coeffs[4]; const CvFileNode* node = find_timing_param( "rotate_scale" ); assert( node && CV_NODE_IS_SEQ(node->tag) ); cvReadRawData( ts->get_file_storage(), node, coeffs, "4d" ); sprintf( ptr, "fx=%.2f,fy=%.2f,angle=%.1fdeg,scale=%.1f,", coeffs[0], coeffs[1], coeffs[2], coeffs[3] ); ptr += strlen(ptr); params_left -= 4; CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left ); } void CV_WarpAffineTest::run_func() { cvWarpAffine( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &test_mat[INPUT][1], interpolation ); } double CV_WarpAffineTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) { int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type); return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2; } int CV_WarpAffineTest::prepare_test_case( int test_case_idx ) { CvRNG* rng = ts->get_rng(); int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); const CvMat* src = &test_mat[INPUT][0]; const CvMat* dst = &test_mat[INPUT_OUTPUT][0]; CvMat* mat = &test_mat[INPUT][1]; CvPoint2D32f center; double scale, angle; if( code <= 0 ) return code; if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE ) { double buf[6]; CvMat tmp = cvMat( 2, 3, mat->type, buf ); center.x = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->cols); center.y = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->rows); angle = cvTsRandReal(rng)*360; scale = ((double)dst->rows/src->rows + (double)dst->cols/src->cols)*0.5; cv2DRotationMatrix( center, angle, scale, mat ); cvRandArr( rng, &tmp, CV_RAND_NORMAL, cvScalarAll(1.), cvScalarAll(0.01) ); cvMaxS( &tmp, 0.9, &tmp ); cvMinS( &tmp, 1.1, &tmp ); cvMul( &tmp, mat, mat, 1. ); } else { double coeffs[4]; const CvFileNode* node = find_timing_param( "rotate_scale" ); assert( node && CV_NODE_IS_SEQ(node->tag) ); cvReadRawData( ts->get_file_storage(), node, coeffs, "4d" ); center.x = (float)(coeffs[0]*src->cols); center.y = (float)(coeffs[1]*src->rows); angle = coeffs[2]; scale = coeffs[3]; cv2DRotationMatrix( center, angle, scale, mat ); } return code; } void CV_WarpAffineTest::prepare_to_validation( int /*test_case_idx*/ ) { CvMat* src = &test_mat[INPUT][0]; CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0]; CvMat* dst0 = &test_mat[INPUT_OUTPUT][0]; CvMat* mapx = &test_mat[TEMP][0]; CvMat* mapy = &test_mat[TEMP][1]; int x, y; double m[6], tm[6]; CvMat srcAb = cvMat(2, 3, CV_64FC1, tm ), A, b, invA, invAb, dstAb = cvMat( 2, 3, CV_64FC1, m ); //cvInvert( &tM, &M, CV_LU ); // [R|t] -> [R^-1 | -(R^-1)*t] cvTsConvert( &test_mat[INPUT][1], &srcAb ); cvGetCols( &srcAb, &A, 0, 2 ); cvGetCol( &srcAb, &b, 2 ); cvGetCols( &dstAb, &invA, 0, 2 ); cvGetCol( &dstAb, &invAb, 2 ); cvInvert( &A, &invA, CV_SVD ); cvGEMM( &invA, &b, -1, 0, 0, &invAb ); for( y = 0; y < dst->rows; y++ ) { float* mx = (float*)(mapx->data.ptr + y*mapx->step); float* my = (float*)(mapy->data.ptr + y*mapy->step); for( x = 0; x < dst->cols; x++ ) { mx[x] = (float)(x*m[0] + y*m[1] + m[2]); my[x] = (float)(x*m[3] + y*m[4] + m[5]); } } CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U ); cvTsRemap( src, dst, mapx, mapy, mask ); cvTsZero( dst, mask ); cvTsZero( dst0, mask ); cvReleaseMat( &mask ); } //CV_WarpAffineTest warp_affine_test; ///////////////////////// class CV_WarpPerspectiveTest : public CV_ImgWarpBaseTest { public: CV_WarpPerspectiveTest(); protected: void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ); void run_func(); int prepare_test_case( int test_case_idx ); void prepare_to_validation( int /*test_case_idx*/ ); double get_success_error_level( int test_case_idx, int i, int j ); int write_default_params(CvFileStorage* fs); void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ); void print_timing_params( int test_case_idx, char* ptr, int params_left ); }; CV_WarpPerspectiveTest::CV_WarpPerspectiveTest() : CV_ImgWarpBaseTest( "warp-perspective", "cvWarpPerspective", true ) { //spatial_scale_zoom = spatial_scale_decimate; test_array[TEMP].push(NULL); test_array[TEMP].push(NULL); spatial_scale_decimate = spatial_scale_zoom; default_timing_param_names = imgwarp_perspective_param_names; } int CV_WarpPerspectiveTest::write_default_params( CvFileStorage* fs ) { int code = CV_ImgWarpBaseTest::write_default_params( fs ); if( code < 0 ) return code; if( ts->get_testing_mode() == CvTS::TIMING_MODE ) { int i; start_write_param( fs ); cvStartWriteStruct( fs, "shift_vtx", CV_NODE_SEQ+CV_NODE_FLOW ); for( i = 0; imgwarp_perspective_shift_vtx[i][0] >= 0; i++ ) { cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW ); cvWriteRawData( fs, imgwarp_perspective_shift_vtx[i], 8, "d" ); cvEndWriteStruct(fs); } cvEndWriteStruct(fs); } return code; } void CV_WarpPerspectiveTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ) { CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); CvSize sz = sizes[INPUT][0]; // run for the second time to get output of a different size CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); sizes[INPUT][0] = sz; sizes[INPUT][1] = cvSize( 3, 3 ); sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT_OUTPUT][0]; types[TEMP][0] = types[TEMP][1] = CV_32FC1; } void CV_WarpPerspectiveTest::get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ) { CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types, whole_sizes, are_images ); sizes[INPUT][1] = whole_sizes[INPUT][1] = cvSize(3,3); sizes[TEMP][0] = whole_sizes[TEMP][0] = sizes[TEMP][1] = whole_sizes[TEMP][1] = cvSize(0,0); types[INPUT][1] = CV_64FC1; interpolation = CV_INTER_LINEAR; } void CV_WarpPerspectiveTest::print_timing_params( int test_case_idx, char* ptr, int params_left ) { CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left ); } void CV_WarpPerspectiveTest::run_func() { cvWarpPerspective( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &test_mat[INPUT][1], interpolation ); } double CV_WarpPerspectiveTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) { int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type); return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2; } int CV_WarpPerspectiveTest::prepare_test_case( int test_case_idx ) { CvRNG* rng = ts->get_rng(); int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); const CvMat* src = &test_mat[INPUT][0]; const CvMat* dst = &test_mat[INPUT_OUTPUT][0]; CvMat* mat = &test_mat[INPUT][1]; CvPoint2D32f s[4], d[4]; int i; if( code <= 0 ) return code; s[0] = cvPoint2D32f(0,0); d[0] = cvPoint2D32f(0,0); s[1] = cvPoint2D32f(src->cols-1,0); d[1] = cvPoint2D32f(dst->cols-1,0); s[2] = cvPoint2D32f(src->cols-1,src->rows-1); d[2] = cvPoint2D32f(dst->cols-1,dst->rows-1); s[3] = cvPoint2D32f(0,src->rows-1); d[3] = cvPoint2D32f(0,dst->rows-1); if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE ) { float buf[16]; CvMat tmp = cvMat( 1, 16, CV_32FC1, buf ); cvRandArr( rng, &tmp, CV_RAND_NORMAL, cvScalarAll(0.), cvScalarAll(0.1) ); for( i = 0; i < 4; i++ ) { s[i].x += buf[i*4]*src->cols/2; s[i].y += buf[i*4+1]*src->rows/2; d[i].x += buf[i*4+2]*dst->cols/2; d[i].y += buf[i*4+3]*dst->rows/2; } } else { double coeffs[8]; const CvFileNode* node = find_timing_param( "shift_vtx" ); assert( node && CV_NODE_IS_SEQ(node->tag) ); cvReadRawData( ts->get_file_storage(), node, coeffs, "8d" ); for( i = 0; i < 4; i++ ) { d[i].x += (float)(coeffs[i*2]*src->cols*(i == 0 || i == 3 ? 1 : -1)); d[i].y += (float)(coeffs[i*2+1]*src->rows*(i == 0 || i == 1 ? 1 : -1)); } } cvWarpPerspectiveQMatrix( s, d, mat ); return code; } void CV_WarpPerspectiveTest::prepare_to_validation( int /*test_case_idx*/ ) { CvMat* src = &test_mat[INPUT][0]; CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0]; CvMat* dst0 = &test_mat[INPUT_OUTPUT][0]; CvMat* mapx = &test_mat[TEMP][0]; CvMat* mapy = &test_mat[TEMP][1]; int x, y; double m[9], tm[9]; CvMat srcM = cvMat(3, 3, CV_64FC1, tm ), dstM = cvMat( 3, 3, CV_64FC1, m ); //cvInvert( &tM, &M, CV_LU ); // [R|t] -> [R^-1 | -(R^-1)*t] cvTsConvert( &test_mat[INPUT][1], &srcM ); cvInvert( &srcM, &dstM, CV_SVD ); for( y = 0; y < dst->rows; y++ ) { float* mx = (float*)(mapx->data.ptr + y*mapx->step); float* my = (float*)(mapy->data.ptr + y*mapy->step); for( x = 0; x < dst->cols; x++ ) { double xs = x*m[0] + y*m[1] + m[2]; double ys = x*m[3] + y*m[4] + m[5]; double ds = x*m[6] + y*m[7] + m[8]; ds = ds ? 1./ds : 0; xs *= ds; ys *= ds; mx[x] = (float)xs; my[x] = (float)ys; } } CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U ); cvTsRemap( src, dst, mapx, mapy, mask ); cvTsZero( dst, mask ); cvTsZero( dst0, mask ); cvReleaseMat( &mask ); } //CV_WarpPerspectiveTest warp_perspective_test; ///////////////////////// void cvTsInitUndistortMap( const CvMat* _a0, const CvMat* _k0, CvMat* _mapx, CvMat* _mapy ) { CvMat* mapx = cvCreateMat(_mapx->rows,_mapx->cols,CV_32F); CvMat* mapy = cvCreateMat(_mapx->rows,_mapx->cols,CV_32F); int u, v; double a[9], k[5]={0,0,0,0,0}; CvMat _a = cvMat(3, 3, CV_64F, a); CvMat _k = cvMat(_k0->rows,_k0->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(_k0->type)),k); double fx, fy, cx, cy, ifx, ify, cxn, cyn; cvTsConvert( _a0, &_a ); cvTsConvert( _k0, &_k ); fx = a[0]; fy = a[4]; cx = a[2]; cy = a[5]; ifx = 1./fx; ify = 1./fy; cxn = cx;//(mapy->cols - 1)*0.5; cyn = cy;//(mapy->rows - 1)*0.5; for( v = 0; v < mapy->rows; v++ ) { float* mx = (float*)(mapx->data.ptr + v*mapx->step); float* my = (float*)(mapy->data.ptr + v*mapy->step); for( u = 0; u < mapy->cols; u++ ) { double x = (u - cxn)*ifx; double y = (v - cyn)*ify; double x2 = x*x, y2 = y*y; double r2 = x2 + y2; double cdist = 1 + (k[0] + (k[1] + k[4]*r2)*r2)*r2; double x1 = x*cdist + k[2]*2*x*y + k[3]*(r2 + 2*x2); double y1 = y*cdist + k[3]*2*x*y + k[2]*(r2 + 2*y2); my[u] = (float)(y1*fy + cy); mx[u] = (float)(x1*fx + cx); } } if (_mapy) { cvCopy(mapy,_mapy); cvCopy(mapx,_mapx); } else { for (int i=0;i<mapx->rows;i++) { float* _mx = (float*)(_mapx->data.ptr + _mapx->step*i); float* _my = (float*)(_mapx->data.ptr + _mapx->step*i); for (int j=0;j<mapx->cols;j++) { _mx[2*j] = mapx->data.fl[j+i*mapx->cols]; _my[2*j+1] = mapy->data.fl[j+i*mapy->cols]; } } } cvReleaseMat(&mapx); cvReleaseMat(&mapy); } static double remap_undistort_params[] = { 0.5, 0.5, 0.5, 0.5, 0.01, -0.01, 0.001, -0.001 }; class CV_RemapTest : public CV_ImgWarpBaseTest { public: CV_RemapTest(); protected: void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ); void run_func(); int prepare_test_case( int test_case_idx ); void prepare_to_validation( int /*test_case_idx*/ ); double get_success_error_level( int test_case_idx, int i, int j ); void fill_array( int test_case_idx, int i, int j, CvMat* arr ); int write_default_params(CvFileStorage* fs); void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ); void print_timing_params( int test_case_idx, char* ptr, int params_left ); }; CV_RemapTest::CV_RemapTest() : CV_ImgWarpBaseTest( "warp-remap", "cvRemap", false ) { //spatial_scale_zoom = spatial_scale_decimate; test_array[INPUT].push(NULL); test_array[INPUT].push(NULL); spatial_scale_decimate = spatial_scale_zoom; //default_timing_param_names = imgwarp_perspective_param_names; support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE; default_timing_param_names = 0; } int CV_RemapTest::write_default_params( CvFileStorage* fs ) { int code = CV_ImgWarpBaseTest::write_default_params( fs ); if( code < 0 ) return code; if( ts->get_testing_mode() == CvTS::TIMING_MODE ) { int i; start_write_param( fs ); cvStartWriteStruct( fs, "params", CV_NODE_SEQ+CV_NODE_FLOW ); for( i = 0; i < 8; i++ ) cvWriteReal( fs, 0, remap_undistort_params[i] ); cvEndWriteStruct(fs); } return code; } void CV_RemapTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ) { CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); types[INPUT][1] = types[INPUT][2] = CV_32FC1; interpolation = CV_INTER_LINEAR; } void CV_RemapTest::fill_array( int test_case_idx, int i, int j, CvMat* arr ) { if( i != INPUT ) CV_ImgWarpBaseTestImpl::fill_array( test_case_idx, i, j, arr ); } void CV_RemapTest::get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ) { CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types, whole_sizes, are_images ); types[INPUT][1] = types[INPUT][2] = CV_32FC1; interpolation = CV_INTER_LINEAR; } void CV_RemapTest::print_timing_params( int test_case_idx, char* ptr, int params_left ) { CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left ); } void CV_RemapTest::run_func() { cvRemap( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], test_array[INPUT][1], test_array[INPUT][2], interpolation ); } double CV_RemapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) { int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type); return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2; } int CV_RemapTest::prepare_test_case( int test_case_idx ) { CvRNG* rng = ts->get_rng(); int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); const CvMat* src = &test_mat[INPUT][0]; double a[9] = {0,0,0,0,0,0,0,0,1}, k[4]; CvMat _a = cvMat( 3, 3, CV_64F, a ); CvMat _k = cvMat( 4, 1, CV_64F, k ); double sz = MAX(src->rows, src->cols); if( code <= 0 ) return code; if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE ) { double aspect_ratio = cvTsRandReal(rng)*0.6 + 0.7; a[2] = (src->cols - 1)*0.5 + cvTsRandReal(rng)*10 - 5; a[5] = (src->rows - 1)*0.5 + cvTsRandReal(rng)*10 - 5; a[0] = sz/(0.9 - cvTsRandReal(rng)*0.6); a[4] = aspect_ratio*a[0]; k[0] = cvTsRandReal(rng)*0.06 - 0.03; k[1] = cvTsRandReal(rng)*0.06 - 0.03; if( k[0]*k[1] > 0 ) k[1] = -k[1]; k[2] = cvTsRandReal(rng)*0.004 - 0.002; k[3] = cvTsRandReal(rng)*0.004 - 0.002; } else { int i; a[2] = (src->cols - 1)*remap_undistort_params[0]; a[5] = (src->rows - 1)*remap_undistort_params[1]; a[0] = sz/remap_undistort_params[2]; a[4] = sz/remap_undistort_params[3]; for( i = 0; i < 4; i++ ) k[i] = remap_undistort_params[i+4]; } cvTsInitUndistortMap( &_a, &_k, &test_mat[INPUT][1], &test_mat[INPUT][2] ); return code; } void CV_RemapTest::prepare_to_validation( int /*test_case_idx*/ ) { CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0]; CvMat* dst0 = &test_mat[INPUT_OUTPUT][0]; CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U ); cvTsRemap( &test_mat[INPUT][0], dst, &test_mat[INPUT][1], &test_mat[INPUT][2], mask, interpolation ); cvTsZero( dst, mask ); cvTsZero( dst0, mask ); cvReleaseMat( &mask ); } //CV_RemapTest remap_test; ////////////////////////////// undistort ///////////////////////////////// class CV_UndistortTest : public CV_ImgWarpBaseTest { public: CV_UndistortTest(); protected: void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ); void run_func(); int prepare_test_case( int test_case_idx ); void prepare_to_validation( int /*test_case_idx*/ ); double get_success_error_level( int test_case_idx, int i, int j ); void fill_array( int test_case_idx, int i, int j, CvMat* arr ); int write_default_params(CvFileStorage* fs); void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ); void print_timing_params( int test_case_idx, char* ptr, int params_left ); private: bool useCPlus; cv::Mat input0; cv::Mat input1; cv::Mat input2; cv::Mat input_new_cam; cv::Mat input_output; bool zero_new_cam; bool zero_distortion; }; CV_UndistortTest::CV_UndistortTest() : CV_ImgWarpBaseTest( "warp-undistort", "cvUndistort2", false ) { //spatial_scale_zoom = spatial_scale_decimate; test_array[INPUT].push(NULL); test_array[INPUT].push(NULL); test_array[INPUT].push(NULL); spatial_scale_decimate = spatial_scale_zoom; //default_timing_param_names = imgwarp_perspective_param_names; support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE; default_timing_param_names = 0; } int CV_UndistortTest::write_default_params( CvFileStorage* fs ) { int code = CV_ImgWarpBaseTest::write_default_params( fs ); if( code < 0 ) return code; if( ts->get_testing_mode() == CvTS::TIMING_MODE ) { int i; start_write_param( fs ); cvStartWriteStruct( fs, "params", CV_NODE_SEQ+CV_NODE_FLOW ); for( i = 0; i < 8; i++ ) cvWriteReal( fs, 0, remap_undistort_params[i] ); cvEndWriteStruct(fs); } return code; } void CV_UndistortTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ) { CvRNG* rng = ts->get_rng(); CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); int type = types[INPUT][0]; type = CV_MAKETYPE( CV_8U, CV_MAT_CN(type) ); types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = type; types[INPUT][1] = cvTsRandInt(rng)%2 ? CV_64F : CV_32F; types[INPUT][2] = cvTsRandInt(rng)%2 ? CV_64F : CV_32F; sizes[INPUT][1] = cvSize(3,3); sizes[INPUT][2] = cvTsRandInt(rng)%2 ? cvSize(4,1) : cvSize(1,4); types[INPUT][3] = types[INPUT][1]; sizes[INPUT][3] = sizes[INPUT][1]; interpolation = CV_INTER_LINEAR; } void CV_UndistortTest::fill_array( int test_case_idx, int i, int j, CvMat* arr ) { if( i != INPUT ) CV_ImgWarpBaseTestImpl::fill_array( test_case_idx, i, j, arr ); } void CV_UndistortTest::get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ) { CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types, whole_sizes, are_images ); types[INPUT][1] = types[INPUT][2] = CV_32FC1; interpolation = CV_INTER_LINEAR; } void CV_UndistortTest::print_timing_params( int test_case_idx, char* ptr, int params_left ) { CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left ); } void CV_UndistortTest::run_func() { if (!useCPlus) { cvUndistort2( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &test_mat[INPUT][1], &test_mat[INPUT][2] ); } else { if (zero_distortion) { cv::undistort(input0,input_output,input1,cv::Mat()); } else { cv::undistort(input0,input_output,input1,input2); } } } double CV_UndistortTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) { int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type); return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2; } int CV_UndistortTest::prepare_test_case( int test_case_idx ) { CvRNG* rng = ts->get_rng(); int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); const CvMat* src = &test_mat[INPUT][0]; double k[4], a[9] = {0,0,0,0,0,0,0,0,1}; double sz = MAX(src->rows, src->cols); double new_cam[9] = {0,0,0,0,0,0,0,0,1}; CvMat _new_cam = cvMat(test_mat[INPUT][3].rows,test_mat[INPUT][3].cols,CV_64F,new_cam); CvMat* _new_cam0 = &test_mat[INPUT][3]; CvMat* _a0 = &test_mat[INPUT][1], *_k0 = &test_mat[INPUT][2]; CvMat _a = cvMat(3,3,CV_64F,a); CvMat _k = cvMat(_k0->rows,_k0->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(_k0->type)),k); if( code <= 0 ) return code; if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE ) { double aspect_ratio = cvTsRandReal(rng)*0.6 + 0.7; a[2] = (src->cols - 1)*0.5 + cvTsRandReal(rng)*10 - 5; a[5] = (src->rows - 1)*0.5 + cvTsRandReal(rng)*10 - 5; a[0] = sz/(0.9 - cvTsRandReal(rng)*0.6); a[4] = aspect_ratio*a[0]; k[0] = cvTsRandReal(rng)*0.06 - 0.03; k[1] = cvTsRandReal(rng)*0.06 - 0.03; if( k[0]*k[1] > 0 ) k[1] = -k[1]; if( cvTsRandInt(rng)%4 != 0 ) { k[2] = cvTsRandReal(rng)*0.004 - 0.002; k[3] = cvTsRandReal(rng)*0.004 - 0.002; } else k[2] = k[3] = 0; new_cam[0] = a[0] + (cvTsRandReal(rng) - (double)0.5)*0.2*a[0]; //10% new_cam[4] = a[4] + (cvTsRandReal(rng) - (double)0.5)*0.2*a[4]; //10% new_cam[2] = a[2] + (cvTsRandReal(rng) - (double)0.5)*0.3*test_mat[INPUT][0].rows; //15% new_cam[5] = a[5] + (cvTsRandReal(rng) - (double)0.5)*0.3*test_mat[INPUT][0].cols; //15% } else { int i; a[2] = (src->cols - 1)*remap_undistort_params[0]; a[5] = (src->rows - 1)*remap_undistort_params[1]; a[0] = sz/remap_undistort_params[2]; a[4] = sz/remap_undistort_params[3]; for( i = 0; i < 4; i++ ) k[i] = remap_undistort_params[i+4]; } cvTsConvert( &_a, _a0 ); zero_distortion = (cvRandInt(rng)%2) == 0 ? false : true; cvTsConvert( &_k, _k0 ); zero_new_cam = (cvRandInt(rng)%2) == 0 ? false : true; cvTsConvert( &_new_cam, _new_cam0 ); //Testing C++ code useCPlus = ((cvTsRandInt(rng) % 2)!=0); if (useCPlus) { input0 = &test_mat[INPUT][0]; input1 = &test_mat[INPUT][1]; input2 = &test_mat[INPUT][2]; input_new_cam = &test_mat[INPUT][3]; } return code; } void CV_UndistortTest::prepare_to_validation( int /*test_case_idx*/ ) { if (useCPlus) { CvMat result = input_output; CvMat* test_input_output = &test_mat[INPUT_OUTPUT][0]; cvTsConvert(&result,test_input_output); } CvMat* src = &test_mat[INPUT][0]; CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0]; CvMat* dst0 = &test_mat[INPUT_OUTPUT][0]; CvMat* mapx = cvCreateMat( dst->rows, dst->cols, CV_32FC1 ); CvMat* mapy = cvCreateMat( dst->rows, dst->cols, CV_32FC1 ); cvTsInitUndistortMap( &test_mat[INPUT][1], &test_mat[INPUT][2], mapx, mapy ); CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U ); cvTsRemap( src, dst, mapx, mapy, mask, interpolation ); cvTsZero( dst, mask ); cvTsZero( dst0, mask ); cvReleaseMat( &mapx ); cvReleaseMat( &mapy ); cvReleaseMat( &mask ); } //CV_UndistortTest undistort_test; class CV_UndistortMapTest : public CvArrTest { public: CV_UndistortMapTest(); protected: void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ); void run_func(); int prepare_test_case( int test_case_idx ); void prepare_to_validation( int /*test_case_idx*/ ); double get_success_error_level( int test_case_idx, int i, int j ); void fill_array( int test_case_idx, int i, int j, CvMat* arr ); int write_default_params(CvFileStorage* fs); void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ); void print_timing_params( int test_case_idx, char* ptr, int params_left ); private: bool dualChannel; }; CV_UndistortMapTest::CV_UndistortMapTest() : CvArrTest( "warp-undistort-map", "cvInitUndistortMap", "" ) { test_array[INPUT].push(NULL); test_array[INPUT].push(NULL); test_array[OUTPUT].push(NULL); test_array[OUTPUT].push(NULL); test_array[REF_OUTPUT].push(NULL); test_array[REF_OUTPUT].push(NULL); element_wise_relative_error = false; support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE; default_timing_param_names = 0; } int CV_UndistortMapTest::write_default_params( CvFileStorage* fs ) { int code = CvArrTest::write_default_params( fs ); if( code < 0 ) return code; if( ts->get_testing_mode() == CvTS::TIMING_MODE ) { int i; start_write_param( fs ); cvStartWriteStruct( fs, "params", CV_NODE_SEQ+CV_NODE_FLOW ); for( i = 0; i < 8; i++ ) cvWriteReal( fs, 0, remap_undistort_params[i] ); cvEndWriteStruct(fs); } return code; } void CV_UndistortMapTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ) { CvRNG* rng = ts->get_rng(); CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); int depth = cvTsRandInt(rng)%2 ? CV_64F : CV_32F; CvSize sz = sizes[OUTPUT][0]; types[INPUT][0] = types[INPUT][1] = depth; dualChannel = cvTsRandInt(rng)%2 == 0; types[OUTPUT][0] = types[OUTPUT][1] = types[REF_OUTPUT][0] = types[REF_OUTPUT][1] = dualChannel ? CV_32FC2 : CV_32F; sizes[INPUT][0] = cvSize(3,3); sizes[INPUT][1] = cvTsRandInt(rng)%2 ? cvSize(4,1) : cvSize(1,4); sz.width = MAX(sz.width,16); sz.height = MAX(sz.height,16); sizes[OUTPUT][0] = sizes[OUTPUT][1] = sizes[REF_OUTPUT][0] = sizes[REF_OUTPUT][1] = sz; } void CV_UndistortMapTest::fill_array( int test_case_idx, int i, int j, CvMat* arr ) { if( i != INPUT ) CvArrTest::fill_array( test_case_idx, i, j, arr ); } void CV_UndistortMapTest::get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ) { CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types, whole_sizes, are_images ); } void CV_UndistortMapTest::print_timing_params( int test_case_idx, char* ptr, int params_left ) { CvArrTest::print_timing_params( test_case_idx, ptr, params_left ); } void CV_UndistortMapTest::run_func() { if (!dualChannel ) cvInitUndistortMap( &test_mat[INPUT][0], &test_mat[INPUT][1], test_array[OUTPUT][0], test_array[OUTPUT][1] ); else cvInitUndistortMap( &test_mat[INPUT][0], &test_mat[INPUT][1], test_array[OUTPUT][0], 0 ); } double CV_UndistortMapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) { return 1e-3; } int CV_UndistortMapTest::prepare_test_case( int test_case_idx ) { CvRNG* rng = ts->get_rng(); int code = CvArrTest::prepare_test_case( test_case_idx ); const CvMat* mapx = &test_mat[OUTPUT][0]; double k[4], a[9] = {0,0,0,0,0,0,0,0,1}; double sz = MAX(mapx->rows, mapx->cols); CvMat* _a0 = &test_mat[INPUT][0], *_k0 = &test_mat[INPUT][1]; CvMat _a = cvMat(3,3,CV_64F,a); CvMat _k = cvMat(_k0->rows,_k0->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(_k0->type)),k); if( code <= 0 ) return code; if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE ) { double aspect_ratio = cvTsRandReal(rng)*0.6 + 0.7; a[2] = (mapx->cols - 1)*0.5 + cvTsRandReal(rng)*10 - 5; a[5] = (mapx->rows - 1)*0.5 + cvTsRandReal(rng)*10 - 5; a[0] = sz/(0.9 - cvTsRandReal(rng)*0.6); a[4] = aspect_ratio*a[0]; k[0] = cvTsRandReal(rng)*0.06 - 0.03; k[1] = cvTsRandReal(rng)*0.06 - 0.03; if( k[0]*k[1] > 0 ) k[1] = -k[1]; k[2] = cvTsRandReal(rng)*0.004 - 0.002; k[3] = cvTsRandReal(rng)*0.004 - 0.002; } else { int i; a[2] = (mapx->cols - 1)*remap_undistort_params[0]; a[5] = (mapx->rows - 1)*remap_undistort_params[1]; a[0] = sz/remap_undistort_params[2]; a[4] = sz/remap_undistort_params[3]; for( i = 0; i < 4; i++ ) k[i] = remap_undistort_params[i+4]; } cvTsConvert( &_a, _a0 ); cvTsConvert( &_k, _k0 ); if (dualChannel) { cvZero(&test_mat[REF_OUTPUT][1]); cvZero(&test_mat[OUTPUT][1]); } return code; } void CV_UndistortMapTest::prepare_to_validation( int ) { if (!dualChannel ) cvTsInitUndistortMap( &test_mat[INPUT][0], &test_mat[INPUT][1], &test_mat[REF_OUTPUT][0], &test_mat[REF_OUTPUT][1] ); else cvTsInitUndistortMap( &test_mat[INPUT][0], &test_mat[INPUT][1], &test_mat[REF_OUTPUT][0], 0 ); } CV_UndistortMapTest undistortmap_test; ////////////////////////////// GetRectSubPix ///////////////////////////////// static const CvSize rectsubpix_sizes[] = {{11, 11}, {21,21}, {41,41},{-1,-1}}; static void cvTsGetQuadrangeSubPix( const CvMat* src, CvMat* dst, double* a ) { int y, x, k, cn; int sstep = src->step / sizeof(float); int scols = src->cols, srows = src->rows; assert( CV_MAT_DEPTH(src->type) == CV_32F && CV_ARE_TYPES_EQ(src, dst)); cn = CV_MAT_CN(dst->type); for( y = 0; y < dst->rows; y++ ) for( x = 0; x < dst->cols; x++ ) { float* d = (float*)(dst->data.ptr + y*dst->step) + x*cn; float sx = (float)(a[0]*x + a[1]*y + a[2]); float sy = (float)(a[3]*x + a[4]*y + a[5]); int ix = cvFloor(sx), iy = cvFloor(sy); int dx = cn, dy = sstep; const float* s; sx -= ix; sy -= iy; if( (unsigned)ix >= (unsigned)(scols-1) ) ix = ix < 0 ? 0 : scols - 1, sx = 0, dx = 0; if( (unsigned)iy >= (unsigned)(srows-1) ) iy = iy < 0 ? 0 : srows - 1, sy = 0, dy = 0; s = src->data.fl + sstep*iy + ix*cn; for( k = 0; k < cn; k++, s++ ) { float t0 = s[0] + sx*(s[dx] - s[0]); float t1 = s[dy] + sx*(s[dy + dx] - s[dy]); d[k] = t0 + sy*(t1 - t0); } } } class CV_GetRectSubPixTest : public CV_ImgWarpBaseTest { public: CV_GetRectSubPixTest(); protected: void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ); void run_func(); int prepare_test_case( int test_case_idx ); void prepare_to_validation( int /*test_case_idx*/ ); double get_success_error_level( int test_case_idx, int i, int j ); void fill_array( int test_case_idx, int i, int j, CvMat* arr ); int write_default_params(CvFileStorage* fs); void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ); void print_timing_params( int test_case_idx, char* ptr, int params_left ); CvPoint2D32f center; bool test_cpp; }; CV_GetRectSubPixTest::CV_GetRectSubPixTest() : CV_ImgWarpBaseTest( "warp-subpix-rect", "cvGetRectSubPix", false ) { //spatial_scale_zoom = spatial_scale_decimate; spatial_scale_decimate = spatial_scale_zoom; //default_timing_param_names = imgwarp_perspective_param_names; support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE; default_timing_param_names = 0; test_cpp = false; } int CV_GetRectSubPixTest::write_default_params( CvFileStorage* fs ) { int code = CV_ImgWarpBaseTest::write_default_params( fs ); if( code < 0 ) return code; if( ts->get_testing_mode() == CvTS::TIMING_MODE ) { int i; start_write_param( fs ); cvStartWriteStruct( fs, "rect_size", CV_NODE_SEQ+CV_NODE_FLOW ); for( i = 0; rectsubpix_sizes[i].width > 0; i++ ) { cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW ); cvWriteInt( fs, 0, rectsubpix_sizes[i].width ); cvWriteInt( fs, 0, rectsubpix_sizes[i].height ); cvEndWriteStruct(fs); } cvEndWriteStruct(fs); } return code; } void CV_GetRectSubPixTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ) { CvRNG* rng = ts->get_rng(); CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); int src_depth = cvTsRandInt(rng) % 2, dst_depth; int cn = cvTsRandInt(rng) % 2 ? 3 : 1; CvSize src_size, dst_size; dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F; if( src_depth < CV_32F && cvTsRandInt(rng) % 2 ) dst_depth = CV_32F; types[INPUT][0] = CV_MAKETYPE(src_depth,cn); types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn); src_size = sizes[INPUT][0]; dst_size.width = cvRound(sqrt(cvTsRandReal(rng)*src_size.width) + 1); dst_size.height = cvRound(sqrt(cvTsRandReal(rng)*src_size.height) + 1); dst_size.width = MIN(dst_size.width,src_size.width); dst_size.height = MIN(dst_size.width,src_size.height); sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dst_size; center.x = (float)(cvTsRandReal(rng)*src_size.width); center.y = (float)(cvTsRandReal(rng)*src_size.height); interpolation = CV_INTER_LINEAR; test_cpp = (cvTsRandInt(rng) & 256) == 0; } void CV_GetRectSubPixTest::fill_array( int test_case_idx, int i, int j, CvMat* arr ) { if( i != INPUT ) CV_ImgWarpBaseTestImpl::fill_array( test_case_idx, i, j, arr ); } void CV_GetRectSubPixTest::get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ) { CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types, whole_sizes, are_images ); interpolation = CV_INTER_LINEAR; } void CV_GetRectSubPixTest::print_timing_params( int test_case_idx, char* ptr, int params_left ) { CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left ); } void CV_GetRectSubPixTest::run_func() { if(!test_cpp) cvGetRectSubPix( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], center ); else { cv::Mat _out = cv::cvarrToMat(test_array[INPUT_OUTPUT][0]); cv::getRectSubPix( cv::cvarrToMat(test_array[INPUT][0]), _out.size(), center, _out, _out.type()); } } double CV_GetRectSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) { int in_depth = CV_MAT_DEPTH(test_mat[INPUT][0].type); int out_depth = CV_MAT_DEPTH(test_mat[INPUT_OUTPUT][0].type); return in_depth >= CV_32F ? 1e-3 : out_depth >= CV_32F ? 1e-2 : 1; } int CV_GetRectSubPixTest::prepare_test_case( int test_case_idx ) { return CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); } void CV_GetRectSubPixTest::prepare_to_validation( int /*test_case_idx*/ ) { CvMat* src0 = &test_mat[INPUT][0]; CvMat* dst0 = &test_mat[REF_INPUT_OUTPUT][0]; CvMat* src = src0, *dst = dst0; int ftype = CV_MAKETYPE(CV_32F,CV_MAT_CN(src0->type)); double a[] = { 1, 0, center.x - dst->cols*0.5 + 0.5, 0, 1, center.y - dst->rows*0.5 + 0.5 }; if( CV_MAT_DEPTH(src->type) != CV_32F ) { src = cvCreateMat( src0->rows, src0->cols, ftype ); cvTsConvert( src0, src ); } if( CV_MAT_DEPTH(dst->type) != CV_32F ) dst = cvCreateMat( dst0->rows, dst0->cols, ftype ); cvTsGetQuadrangeSubPix( src, dst, a ); if( dst != dst0 ) { cvTsConvert( dst, dst0 ); cvReleaseMat( &dst ); } if( src != src0 ) cvReleaseMat( &src ); } CV_GetRectSubPixTest subpix_rect_test; class CV_GetQuadSubPixTest : public CV_ImgWarpBaseTest { public: CV_GetQuadSubPixTest(); protected: void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ); void run_func(); int prepare_test_case( int test_case_idx ); void prepare_to_validation( int /*test_case_idx*/ ); double get_success_error_level( int test_case_idx, int i, int j ); int write_default_params(CvFileStorage* fs); void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ); void print_timing_params( int test_case_idx, char* ptr, int params_left ); }; CV_GetQuadSubPixTest::CV_GetQuadSubPixTest() : CV_ImgWarpBaseTest( "warp-subpix-quad", "cvGetQuadSubPix", true ) { //spatial_scale_zoom = spatial_scale_decimate; spatial_scale_decimate = spatial_scale_zoom; //default_timing_param_names = imgwarp_affine_param_names; support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE; default_timing_param_names = 0; } int CV_GetQuadSubPixTest::write_default_params( CvFileStorage* fs ) { int code = CV_ImgWarpBaseTest::write_default_params( fs ); if( code < 0 ) return code; if( ts->get_testing_mode() == CvTS::TIMING_MODE ) { int i; start_write_param( fs ); cvStartWriteStruct( fs, "rotate_scale", CV_NODE_SEQ+CV_NODE_FLOW ); for( i = 0; imgwarp_affine_rotate_scale[i][0] >= 0; i++ ) { cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW ); cvWriteRawData( fs, imgwarp_affine_rotate_scale[i], 4, "d" ); cvEndWriteStruct(fs); } cvEndWriteStruct(fs); } return code; } void CV_GetQuadSubPixTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types ) { int min_size = 4; CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); CvSize sz = sizes[INPUT][0], dsz; CvRNG* rng = ts->get_rng(); int msz, src_depth = cvTsRandInt(rng) % 2, dst_depth; int cn = cvTsRandInt(rng) % 2 ? 3 : 1; dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F; if( src_depth < CV_32F && cvTsRandInt(rng) % 2 ) dst_depth = CV_32F; types[INPUT][0] = CV_MAKETYPE(src_depth,cn); types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn); sz.width = MAX(sz.width,min_size); sz.height = MAX(sz.height,min_size); sizes[INPUT][0] = sz; msz = MIN( sz.width, sz.height ); dsz.width = cvRound(sqrt(cvTsRandReal(rng)*msz) + 1); dsz.height = cvRound(sqrt(cvTsRandReal(rng)*msz) + 1); dsz.width = MIN(dsz.width,msz); dsz.height = MIN(dsz.width,msz); dsz.width = MAX(dsz.width,min_size); dsz.height = MAX(dsz.height,min_size); sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dsz; sizes[INPUT][1] = cvSize( 3, 2 ); } void CV_GetQuadSubPixTest::get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images ) { CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types, whole_sizes, are_images ); sizes[INPUT][1] = whole_sizes[INPUT][1] = cvSize(3,2); sizes[TEMP][0] = whole_sizes[TEMP][0] = sizes[TEMP][1] = whole_sizes[TEMP][1] = cvSize(0,0); types[INPUT][1] = CV_64FC1; interpolation = CV_INTER_LINEAR; } void CV_GetQuadSubPixTest::print_timing_params( int test_case_idx, char* ptr, int params_left ) { double coeffs[4]; const CvFileNode* node = find_timing_param( "rotate_scale" ); assert( node && CV_NODE_IS_SEQ(node->tag) ); cvReadRawData( ts->get_file_storage(), node, coeffs, "4d" ); sprintf( ptr, "fx=%.2f,fy=%.2f,angle=%.1fdeg,scale=%.1f,", coeffs[0], coeffs[1], coeffs[2], coeffs[3] ); ptr += strlen(ptr); params_left -= 4; CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left ); } void CV_GetQuadSubPixTest::run_func() { cvGetQuadrangleSubPix( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &test_mat[INPUT][1] ); } double CV_GetQuadSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) { int in_depth = CV_MAT_DEPTH(test_mat[INPUT][0].type); //int out_depth = CV_MAT_DEPTH(test_mat[INPUT_OUTPUT][0].type); return in_depth >= CV_32F ? 1e-2 : 4; } int CV_GetQuadSubPixTest::prepare_test_case( int test_case_idx ) { CvRNG* rng = ts->get_rng(); int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx ); const CvMat* src = &test_mat[INPUT][0]; CvMat* mat = &test_mat[INPUT][1]; CvPoint2D32f center; double scale, angle; if( code <= 0 ) return code; if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE ) { double a[6]; CvMat A = cvMat( 2, 3, CV_64FC1, a ); center.x = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->cols); center.y = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->rows); angle = cvTsRandReal(rng)*360; scale = cvTsRandReal(rng)*0.2 + 0.9; // y = Ax + b -> x = A^-1(y - b) = A^-1*y - A^-1*b scale = 1./scale; angle = angle*(CV_PI/180.); a[0] = a[4] = cos(angle)*scale; a[1] = sin(angle)*scale; a[3] = -a[1]; a[2] = center.x - a[0]*center.x - a[1]*center.y; a[5] = center.y - a[3]*center.x - a[4]*center.y; cvTsConvert( &A, mat ); } return code; } void CV_GetQuadSubPixTest::prepare_to_validation( int /*test_case_idx*/ ) { CvMat* src0 = &test_mat[INPUT][0]; CvMat* dst0 = &test_mat[REF_INPUT_OUTPUT][0]; CvMat* src = src0, *dst = dst0; int ftype = CV_MAKETYPE(CV_32F,CV_MAT_CN(src0->type)); double a[6], dx = (dst0->cols - 1)*0.5, dy = (dst0->rows - 1)*0.5; CvMat A = cvMat( 2, 3, CV_64F, a ); if( CV_MAT_DEPTH(src->type) != CV_32F ) { src = cvCreateMat( src0->rows, src0->cols, ftype ); cvTsConvert( src0, src ); } if( CV_MAT_DEPTH(dst->type) != CV_32F ) dst = cvCreateMat( dst0->rows, dst0->cols, ftype ); cvTsConvert( &test_mat[INPUT][1], &A ); a[2] -= a[0]*dx + a[1]*dy; a[5] -= a[3]*dx + a[4]*dy; cvTsGetQuadrangeSubPix( src, dst, a ); if( dst != dst0 ) { cvTsConvert( dst, dst0 ); cvReleaseMat( &dst ); } if( src != src0 ) cvReleaseMat( &src ); } CV_GetQuadSubPixTest warp_subpix_quad_test; /* End of file. */