Path: blob/master/modules/imgproc/test/test_imgwarp.cpp
16339 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// Intel License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000, Intel Corporation, all rights reserved.13// Third party copyrights are property of their respective owners.14//15// Redistribution and use in source and binary forms, with or without modification,16// are permitted provided that the following conditions are met:17//18// * Redistribution's of source code must retain the above copyright notice,19// this list of conditions and the following disclaimer.20//21// * Redistribution's in binary form must reproduce the above copyright notice,22// this list of conditions and the following disclaimer in the documentation23// and/or other materials provided with the distribution.24//25// * The name of Intel Corporation may not be used to endorse or promote products26// derived from this software without specific prior written permission.27//28// This software is provided by the copyright holders and contributors "as is" and29// any express or implied warranties, including, but not limited to, the implied30// warranties of merchantability and fitness for a particular purpose are disclaimed.31// In no event shall the Intel Corporation or contributors be liable for any direct,32// indirect, incidental, special, exemplary, or consequential damages33// (including, but not limited to, procurement of substitute goods or services;34// loss of use, data, or profits; or business interruption) however caused35// and on any theory of liability, whether in contract, strict liability,36// or tort (including negligence or otherwise) arising in any way out of37// the use of this software, even if advised of the possibility of such damage.38//39//M*/4041#include "test_precomp.hpp"4243namespace opencv_test { namespace {4445class CV_ImgWarpBaseTest : public cvtest::ArrayTest46{47public:48CV_ImgWarpBaseTest( bool warp_matrix );4950protected:51int read_params( CvFileStorage* fs );52int prepare_test_case( int test_case_idx );53void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );54void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );55void fill_array( int test_case_idx, int i, int j, Mat& arr );5657int interpolation;58int max_interpolation;59double spatial_scale_zoom, spatial_scale_decimate;60};616263CV_ImgWarpBaseTest::CV_ImgWarpBaseTest( bool warp_matrix )64{65test_array[INPUT].push_back(NULL);66if( warp_matrix )67test_array[INPUT].push_back(NULL);68test_array[INPUT_OUTPUT].push_back(NULL);69test_array[REF_INPUT_OUTPUT].push_back(NULL);70max_interpolation = 5;71interpolation = 0;72element_wise_relative_error = false;73spatial_scale_zoom = 0.01;74spatial_scale_decimate = 0.005;75}767778int CV_ImgWarpBaseTest::read_params( CvFileStorage* fs )79{80int code = cvtest::ArrayTest::read_params( fs );81return code;82}838485void CV_ImgWarpBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )86{87cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );88if( CV_MAT_DEPTH(type) == CV_32F )89{90low = Scalar::all(-10.);91high = Scalar::all(10);92}93}949596void CV_ImgWarpBaseTest::get_test_array_types_and_sizes( int test_case_idx,97vector<vector<Size> >& sizes, vector<vector<int> >& types )98{99RNG& rng = ts->get_rng();100int depth = cvtest::randInt(rng) % 3;101int cn = cvtest::randInt(rng) % 3 + 1;102cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );103depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : CV_32F;104cn += cn == 2;105106types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn);107if( test_array[INPUT].size() > 1 )108types[INPUT][1] = cvtest::randInt(rng) & 1 ? CV_32FC1 : CV_64FC1;109110interpolation = cvtest::randInt(rng) % max_interpolation;111}112113114void CV_ImgWarpBaseTest::fill_array( int test_case_idx, int i, int j, Mat& arr )115{116if( i != INPUT || j != 0 )117cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );118}119120int CV_ImgWarpBaseTest::prepare_test_case( int test_case_idx )121{122int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );123Mat& img = test_mat[INPUT][0];124int i, j, cols = img.cols;125int type = img.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);126double scale = depth == CV_16U ? 1000. : 255.*0.5;127double space_scale = spatial_scale_decimate;128vector<float> buffer(img.cols*cn);129130if( code <= 0 )131return code;132133if( test_mat[INPUT_OUTPUT][0].cols >= img.cols &&134test_mat[INPUT_OUTPUT][0].rows >= img.rows )135space_scale = spatial_scale_zoom;136137for( i = 0; i < img.rows; i++ )138{139uchar* ptr = img.ptr(i);140switch( cn )141{142case 1:143for( j = 0; j < cols; j++ )144buffer[j] = (float)((sin((i+1)*space_scale)*sin((j+1)*space_scale)+1.)*scale);145break;146case 2:147for( j = 0; j < cols; j++ )148{149buffer[j*2] = (float)((sin((i+1)*space_scale)+1.)*scale);150buffer[j*2+1] = (float)((sin((i+j)*space_scale)+1.)*scale);151}152break;153case 3:154for( j = 0; j < cols; j++ )155{156buffer[j*3] = (float)((sin((i+1)*space_scale)+1.)*scale);157buffer[j*3+1] = (float)((sin(j*space_scale)+1.)*scale);158buffer[j*3+2] = (float)((sin((i+j)*space_scale)+1.)*scale);159}160break;161case 4:162for( j = 0; j < cols; j++ )163{164buffer[j*4] = (float)((sin((i+1)*space_scale)+1.)*scale);165buffer[j*4+1] = (float)((sin(j*space_scale)+1.)*scale);166buffer[j*4+2] = (float)((sin((i+j)*space_scale)+1.)*scale);167buffer[j*4+3] = (float)((sin((i-j)*space_scale)+1.)*scale);168}169break;170default:171assert(0);172}173174/*switch( depth )175{176case CV_8U:177for( j = 0; j < cols*cn; j++ )178ptr[j] = (uchar)cvRound(buffer[j]);179break;180case CV_16U:181for( j = 0; j < cols*cn; j++ )182((ushort*)ptr)[j] = (ushort)cvRound(buffer[j]);183break;184case CV_32F:185for( j = 0; j < cols*cn; j++ )186((float*)ptr)[j] = (float)buffer[j];187break;188default:189assert(0);190}*/191cv::Mat src(1, cols*cn, CV_32F, &buffer[0]);192cv::Mat dst(1, cols*cn, depth, ptr);193src.convertTo(dst, dst.type());194}195196return code;197}198199200/////////////////////////201202class CV_ResizeTest : public CV_ImgWarpBaseTest203{204public:205CV_ResizeTest();206207protected:208void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );209void run_func();210void prepare_to_validation( int /*test_case_idx*/ );211double get_success_error_level( int test_case_idx, int i, int j );212};213214215CV_ResizeTest::CV_ResizeTest() : CV_ImgWarpBaseTest( false )216{217}218219220void CV_ResizeTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )221{222RNG& rng = ts->get_rng();223CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );224Size sz;225226sz.width = (cvtest::randInt(rng) % sizes[INPUT][0].width) + 1;227sz.height = (cvtest::randInt(rng) % sizes[INPUT][0].height) + 1;228229if( cvtest::randInt(rng) & 1 )230{231int xfactor = cvtest::randInt(rng) % 10 + 1;232int yfactor = cvtest::randInt(rng) % 10 + 1;233234if( cvtest::randInt(rng) & 1 )235yfactor = xfactor;236237sz.width = sizes[INPUT][0].width / xfactor;238sz.width = MAX(sz.width,1);239sz.height = sizes[INPUT][0].height / yfactor;240sz.height = MAX(sz.height,1);241sizes[INPUT][0].width = sz.width * xfactor;242sizes[INPUT][0].height = sz.height * yfactor;243}244245if( cvtest::randInt(rng) & 1 )246sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = sz;247else248{249sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = sizes[INPUT][0];250sizes[INPUT][0] = sz;251}252if( interpolation == 4 &&253(MIN(sizes[INPUT][0].width,sizes[INPUT_OUTPUT][0].width) < 4 ||254MIN(sizes[INPUT][0].height,sizes[INPUT_OUTPUT][0].height) < 4))255interpolation = 2;256}257258259void CV_ResizeTest::run_func()260{261cvResize( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], interpolation );262}263264265double CV_ResizeTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )266{267int depth = test_mat[INPUT][0].depth();268return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 1e-1;269}270271272void CV_ResizeTest::prepare_to_validation( int /*test_case_idx*/ )273{274CvMat _src = cvMat(test_mat[INPUT][0]), _dst = cvMat(test_mat[REF_INPUT_OUTPUT][0]);275CvMat *src = &_src, *dst = &_dst;276int i, j, k;277CvMat* x_idx = cvCreateMat( 1, dst->cols, CV_32SC1 );278CvMat* y_idx = cvCreateMat( 1, dst->rows, CV_32SC1 );279int* x_tab = x_idx->data.i;280int elem_size = CV_ELEM_SIZE(src->type);281int drows = dst->rows, dcols = dst->cols;282283if( interpolation == CV_INTER_NN )284{285for( j = 0; j < dcols; j++ )286{287int t = (j*src->cols*2 + MIN(src->cols,dcols) - 1)/(dcols*2);288t -= t >= src->cols;289x_idx->data.i[j] = t*elem_size;290}291292for( j = 0; j < drows; j++ )293{294int t = (j*src->rows*2 + MIN(src->rows,drows) - 1)/(drows*2);295t -= t >= src->rows;296y_idx->data.i[j] = t;297}298}299else300{301double scale_x = (double)src->cols/dcols;302double scale_y = (double)src->rows/drows;303304for( j = 0; j < dcols; j++ )305{306double f = ((j+0.5)*scale_x - 0.5);307i = cvRound(f);308x_idx->data.i[j] = (i < 0 ? 0 : i >= src->cols ? src->cols - 1 : i)*elem_size;309}310311for( j = 0; j < drows; j++ )312{313double f = ((j+0.5)*scale_y - 0.5);314i = cvRound(f);315y_idx->data.i[j] = i < 0 ? 0 : i >= src->rows ? src->rows - 1 : i;316}317}318319for( i = 0; i < drows; i++ )320{321uchar* dptr = dst->data.ptr + dst->step*i;322const uchar* sptr0 = src->data.ptr + src->step*y_idx->data.i[i];323324for( j = 0; j < dcols; j++, dptr += elem_size )325{326const uchar* sptr = sptr0 + x_tab[j];327for( k = 0; k < elem_size; k++ )328dptr[k] = sptr[k];329}330}331332cvReleaseMat( &x_idx );333cvReleaseMat( &y_idx );334}335336class CV_ResizeExactTest : public CV_ResizeTest337{338public:339CV_ResizeExactTest();340341protected:342void get_test_array_types_and_sizes(int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types);343};344345346CV_ResizeExactTest::CV_ResizeExactTest() : CV_ResizeTest()347{348max_interpolation = 1;349}350351352void CV_ResizeExactTest::get_test_array_types_and_sizes(int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types)353{354CV_ResizeTest::get_test_array_types_and_sizes(test_case_idx, sizes, types);355interpolation = INTER_LINEAR_EXACT;356if (CV_MAT_DEPTH(types[INPUT][0]) == CV_32F ||357CV_MAT_DEPTH(types[INPUT][0]) == CV_64F)358types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(CV_8U, CV_MAT_CN(types[INPUT][0]));359}360361/////////////////////////362363static void test_remap( const Mat& src, Mat& dst, const Mat& mapx, const Mat& mapy,364Mat* mask=0, int interpolation=CV_INTER_LINEAR )365{366int x, y, k;367int drows = dst.rows, dcols = dst.cols;368int srows = src.rows, scols = src.cols;369const uchar* sptr0 = src.ptr();370int depth = src.depth(), cn = src.channels();371int elem_size = (int)src.elemSize();372int step = (int)(src.step / CV_ELEM_SIZE(depth));373int delta;374375if( interpolation != CV_INTER_CUBIC )376{377delta = 0;378scols -= 1; srows -= 1;379}380else381{382delta = 1;383scols = MAX(scols - 3, 0);384srows = MAX(srows - 3, 0);385}386387int scols1 = MAX(scols - 2, 0);388int srows1 = MAX(srows - 2, 0);389390if( mask )391*mask = Scalar::all(0);392393for( y = 0; y < drows; y++ )394{395uchar* dptr = dst.ptr(y);396const float* mx = mapx.ptr<float>(y);397const float* my = mapy.ptr<float>(y);398uchar* m = mask ? mask->ptr(y) : 0;399400for( x = 0; x < dcols; x++, dptr += elem_size )401{402float xs = mx[x];403float ys = my[x];404int ixs = cvFloor(xs);405int iys = cvFloor(ys);406407if( (unsigned)(ixs - delta - 1) >= (unsigned)scols1 ||408(unsigned)(iys - delta - 1) >= (unsigned)srows1 )409{410if( m )411m[x] = 1;412if( (unsigned)(ixs - delta) >= (unsigned)scols ||413(unsigned)(iys - delta) >= (unsigned)srows )414continue;415}416417xs -= ixs;418ys -= iys;419420switch( depth )421{422case CV_8U:423{424const uchar* sptr = sptr0 + iys*step + ixs*cn;425for( k = 0; k < cn; k++ )426{427float v00 = sptr[k];428float v01 = sptr[cn + k];429float v10 = sptr[step + k];430float v11 = sptr[step + cn + k];431432v00 = v00 + xs*(v01 - v00);433v10 = v10 + xs*(v11 - v10);434v00 = v00 + ys*(v10 - v00);435dptr[k] = (uchar)cvRound(v00);436}437}438break;439case CV_16U:440{441const ushort* sptr = (const ushort*)sptr0 + iys*step + ixs*cn;442for( k = 0; k < cn; k++ )443{444float v00 = sptr[k];445float v01 = sptr[cn + k];446float v10 = sptr[step + k];447float v11 = sptr[step + cn + k];448449v00 = v00 + xs*(v01 - v00);450v10 = v10 + xs*(v11 - v10);451v00 = v00 + ys*(v10 - v00);452((ushort*)dptr)[k] = (ushort)cvRound(v00);453}454}455break;456case CV_32F:457{458const float* sptr = (const float*)sptr0 + iys*step + ixs*cn;459for( k = 0; k < cn; k++ )460{461float v00 = sptr[k];462float v01 = sptr[cn + k];463float v10 = sptr[step + k];464float v11 = sptr[step + cn + k];465466v00 = v00 + xs*(v01 - v00);467v10 = v10 + xs*(v11 - v10);468v00 = v00 + ys*(v10 - v00);469((float*)dptr)[k] = (float)v00;470}471}472break;473default:474assert(0);475}476}477}478}479480/////////////////////////481482class CV_WarpAffineTest : public CV_ImgWarpBaseTest483{484public:485CV_WarpAffineTest();486487protected:488void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );489void run_func();490int prepare_test_case( int test_case_idx );491void prepare_to_validation( int /*test_case_idx*/ );492double get_success_error_level( int test_case_idx, int i, int j );493};494495496CV_WarpAffineTest::CV_WarpAffineTest() : CV_ImgWarpBaseTest( true )497{498//spatial_scale_zoom = spatial_scale_decimate;499spatial_scale_decimate = spatial_scale_zoom;500}501502503void CV_WarpAffineTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )504{505CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );506Size sz = sizes[INPUT][0];507// run for the second time to get output of a different size508CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );509sizes[INPUT][0] = sz;510sizes[INPUT][1] = Size( 3, 2 );511}512513514void CV_WarpAffineTest::run_func()515{516CvMat mtx = cvMat(test_mat[INPUT][1]);517cvWarpAffine( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &mtx, interpolation );518}519520521double CV_WarpAffineTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )522{523int depth = test_mat[INPUT][0].depth();524return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;525}526527528int CV_WarpAffineTest::prepare_test_case( int test_case_idx )529{530RNG& rng = ts->get_rng();531int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );532const Mat& src = test_mat[INPUT][0];533const Mat& dst = test_mat[INPUT_OUTPUT][0];534Mat& mat = test_mat[INPUT][1];535Point2f center;536double scale, angle;537538if( code <= 0 )539return code;540541double buffer[6];542Mat tmp( 2, 3, mat.type(), buffer );543544center.x = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.cols);545center.y = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.rows);546angle = cvtest::randReal(rng)*360;547scale = ((double)dst.rows/src.rows + (double)dst.cols/src.cols)*0.5;548getRotationMatrix2D(center, angle, scale).convertTo(mat, mat.depth());549rng.fill( tmp, CV_RAND_NORMAL, Scalar::all(1.), Scalar::all(0.01) );550cv::max(tmp, 0.9, tmp);551cv::min(tmp, 1.1, tmp);552cv::multiply(tmp, mat, mat, 1.);553554return code;555}556557558void CV_WarpAffineTest::prepare_to_validation( int /*test_case_idx*/ )559{560const Mat& src = test_mat[INPUT][0];561Mat& dst = test_mat[REF_INPUT_OUTPUT][0];562Mat& dst0 = test_mat[INPUT_OUTPUT][0];563Mat mapx(dst.size(), CV_32F), mapy(dst.size(), CV_32F);564double m[6];565Mat srcAb, dstAb( 2, 3, CV_64FC1, m );566567//cvInvert( &tM, &M, CV_LU );568// [R|t] -> [R^-1 | -(R^-1)*t]569test_mat[INPUT][1].convertTo( srcAb, CV_64F );570Mat A = srcAb.colRange(0, 2);571Mat b = srcAb.col(2);572Mat invA = dstAb.colRange(0, 2);573Mat invAb = dstAb.col(2);574cv::invert(A, invA, CV_SVD);575cv::gemm(invA, b, -1, Mat(), 0, invAb);576577for( int y = 0; y < dst.rows; y++ )578for( int x = 0; x < dst.cols; x++ )579{580mapx.at<float>(y, x) = (float)(x*m[0] + y*m[1] + m[2]);581mapy.at<float>(y, x) = (float)(x*m[3] + y*m[4] + m[5]);582}583584Mat mask( dst.size(), CV_8U );585test_remap( src, dst, mapx, mapy, &mask );586dst.setTo(Scalar::all(0), mask);587dst0.setTo(Scalar::all(0), mask);588}589590591/////////////////////////592593class CV_WarpPerspectiveTest : public CV_ImgWarpBaseTest594{595public:596CV_WarpPerspectiveTest();597598protected:599void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );600void run_func();601int prepare_test_case( int test_case_idx );602void prepare_to_validation( int /*test_case_idx*/ );603double get_success_error_level( int test_case_idx, int i, int j );604};605606607CV_WarpPerspectiveTest::CV_WarpPerspectiveTest() : CV_ImgWarpBaseTest( true )608{609//spatial_scale_zoom = spatial_scale_decimate;610spatial_scale_decimate = spatial_scale_zoom;611}612613614void CV_WarpPerspectiveTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )615{616CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );617Size sz = sizes[INPUT][0];618// run for the second time to get output of a different size619CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );620sizes[INPUT][0] = sz;621sizes[INPUT][1] = Size( 3, 3 );622}623624625void CV_WarpPerspectiveTest::run_func()626{627CvMat mtx = cvMat(test_mat[INPUT][1]);628cvWarpPerspective( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &mtx, interpolation );629}630631632double CV_WarpPerspectiveTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )633{634int depth = test_mat[INPUT][0].depth();635return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;636}637638639int CV_WarpPerspectiveTest::prepare_test_case( int test_case_idx )640{641RNG& rng = ts->get_rng();642int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );643const CvMat src = cvMat(test_mat[INPUT][0]);644const CvMat dst = cvMat(test_mat[INPUT_OUTPUT][0]);645Mat& mat = test_mat[INPUT][1];646Point2f s[4], d[4];647int i;648649if( code <= 0 )650return code;651652s[0] = Point2f(0,0);653d[0] = Point2f(0,0);654s[1] = Point2f(src.cols-1.f,0);655d[1] = Point2f(dst.cols-1.f,0);656s[2] = Point2f(src.cols-1.f,src.rows-1.f);657d[2] = Point2f(dst.cols-1.f,dst.rows-1.f);658s[3] = Point2f(0,src.rows-1.f);659d[3] = Point2f(0,dst.rows-1.f);660661float bufer[16];662Mat tmp( 1, 16, CV_32FC1, bufer );663664rng.fill( tmp, CV_RAND_NORMAL, Scalar::all(0.), Scalar::all(0.1) );665666for( i = 0; i < 4; i++ )667{668s[i].x += bufer[i*4]*src.cols/2;669s[i].y += bufer[i*4+1]*src.rows/2;670d[i].x += bufer[i*4+2]*dst.cols/2;671d[i].y += bufer[i*4+3]*dst.rows/2;672}673674cv::getPerspectiveTransform( s, d ).convertTo( mat, mat.depth() );675return code;676}677678679void CV_WarpPerspectiveTest::prepare_to_validation( int /*test_case_idx*/ )680{681Mat& src = test_mat[INPUT][0];682Mat& dst = test_mat[REF_INPUT_OUTPUT][0];683Mat& dst0 = test_mat[INPUT_OUTPUT][0];684Mat mapx(dst.size(), CV_32F), mapy(dst.size(), CV_32F);685double m[9];686Mat srcM, dstM(3, 3, CV_64F, m);687688//cvInvert( &tM, &M, CV_LU );689// [R|t] -> [R^-1 | -(R^-1)*t]690test_mat[INPUT][1].convertTo( srcM, CV_64F );691cv::invert(srcM, dstM, CV_SVD);692693for( int y = 0; y < dst.rows; y++ )694{695for( int x = 0; x < dst.cols; x++ )696{697double xs = x*m[0] + y*m[1] + m[2];698double ys = x*m[3] + y*m[4] + m[5];699double ds = x*m[6] + y*m[7] + m[8];700701ds = ds ? 1./ds : 0;702xs *= ds;703ys *= ds;704705mapx.at<float>(y, x) = (float)xs;706mapy.at<float>(y, x) = (float)ys;707}708}709710Mat mask( dst.size(), CV_8U );711test_remap( src, dst, mapx, mapy, &mask );712dst.setTo(Scalar::all(0), mask);713dst0.setTo(Scalar::all(0), mask);714}715716717/////////////////////////718719class CV_RemapTest : public CV_ImgWarpBaseTest720{721public:722CV_RemapTest();723724protected:725void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );726void run_func();727int prepare_test_case( int test_case_idx );728void prepare_to_validation( int /*test_case_idx*/ );729double get_success_error_level( int test_case_idx, int i, int j );730void fill_array( int test_case_idx, int i, int j, Mat& arr );731};732733734CV_RemapTest::CV_RemapTest() : CV_ImgWarpBaseTest( false )735{736//spatial_scale_zoom = spatial_scale_decimate;737test_array[INPUT].push_back(NULL);738test_array[INPUT].push_back(NULL);739740spatial_scale_decimate = spatial_scale_zoom;741}742743744void CV_RemapTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )745{746CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );747types[INPUT][1] = types[INPUT][2] = CV_32FC1;748interpolation = CV_INTER_LINEAR;749}750751752void CV_RemapTest::fill_array( int test_case_idx, int i, int j, Mat& arr )753{754if( i != INPUT )755CV_ImgWarpBaseTest::fill_array( test_case_idx, i, j, arr );756}757758759void CV_RemapTest::run_func()760{761cvRemap( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],762test_array[INPUT][1], test_array[INPUT][2], interpolation );763}764765766double CV_RemapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )767{768int depth = test_mat[INPUT][0].depth();769return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;770}771772773int CV_RemapTest::prepare_test_case( int test_case_idx )774{775RNG& rng = ts->get_rng();776int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );777const Mat& src = test_mat[INPUT][0];778double a[9] = {0,0,0,0,0,0,0,0,1}, k[4];779Mat _a( 3, 3, CV_64F, a );780Mat _k( 4, 1, CV_64F, k );781double sz = MAX(src.rows, src.cols);782783if( code <= 0 )784return code;785786double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7;787a[2] = (src.cols - 1)*0.5 + cvtest::randReal(rng)*10 - 5;788a[5] = (src.rows - 1)*0.5 + cvtest::randReal(rng)*10 - 5;789a[0] = sz/(0.9 - cvtest::randReal(rng)*0.6);790a[4] = aspect_ratio*a[0];791k[0] = cvtest::randReal(rng)*0.06 - 0.03;792k[1] = cvtest::randReal(rng)*0.06 - 0.03;793if( k[0]*k[1] > 0 )794k[1] = -k[1];795k[2] = cvtest::randReal(rng)*0.004 - 0.002;796k[3] = cvtest::randReal(rng)*0.004 - 0.002;797798cvtest::initUndistortMap( _a, _k, test_mat[INPUT][1].size(), test_mat[INPUT][1], test_mat[INPUT][2] );799return code;800}801802803void CV_RemapTest::prepare_to_validation( int /*test_case_idx*/ )804{805Mat& dst = test_mat[REF_INPUT_OUTPUT][0];806Mat& dst0 = test_mat[INPUT_OUTPUT][0];807Mat mask( dst.size(), CV_8U );808test_remap(test_mat[INPUT][0], dst, test_mat[INPUT][1],809test_mat[INPUT][2], &mask, interpolation );810dst.setTo(Scalar::all(0), mask);811dst0.setTo(Scalar::all(0), mask);812}813814////////////////////////////// GetRectSubPix /////////////////////////////////815816static void817test_getQuadrangeSubPix( const Mat& src, Mat& dst, double* a )818{819int sstep = (int)(src.step / sizeof(float));820int scols = src.cols, srows = src.rows;821822CV_Assert( src.depth() == CV_32F && src.type() == dst.type() );823824int cn = dst.channels();825826for( int y = 0; y < dst.rows; y++ )827for( int x = 0; x < dst.cols; x++ )828{829float* d = dst.ptr<float>(y) + x*cn;830float sx = (float)(a[0]*x + a[1]*y + a[2]);831float sy = (float)(a[3]*x + a[4]*y + a[5]);832int ix = cvFloor(sx), iy = cvFloor(sy);833int dx = cn, dy = sstep;834const float* s;835sx -= ix; sy -= iy;836837if( (unsigned)ix >= (unsigned)(scols-1) )838ix = ix < 0 ? 0 : scols - 1, sx = 0, dx = 0;839if( (unsigned)iy >= (unsigned)(srows-1) )840iy = iy < 0 ? 0 : srows - 1, sy = 0, dy = 0;841842s = src.ptr<float>(iy) + ix*cn;843for( int k = 0; k < cn; k++, s++ )844{845float t0 = s[0] + sx*(s[dx] - s[0]);846float t1 = s[dy] + sx*(s[dy + dx] - s[dy]);847d[k] = t0 + sy*(t1 - t0);848}849}850}851852853class CV_GetRectSubPixTest : public CV_ImgWarpBaseTest854{855public:856CV_GetRectSubPixTest();857858protected:859void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );860void run_func();861int prepare_test_case( int test_case_idx );862void prepare_to_validation( int /*test_case_idx*/ );863double get_success_error_level( int test_case_idx, int i, int j );864void fill_array( int test_case_idx, int i, int j, Mat& arr );865866CvPoint2D32f center;867bool test_cpp;868};869870871CV_GetRectSubPixTest::CV_GetRectSubPixTest() : CV_ImgWarpBaseTest( false )872{873//spatial_scale_zoom = spatial_scale_decimate;874spatial_scale_decimate = spatial_scale_zoom;875test_cpp = false;876}877878879void CV_GetRectSubPixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )880{881RNG& rng = ts->get_rng();882CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );883int src_depth = cvtest::randInt(rng) % 2, dst_depth;884int cn = cvtest::randInt(rng) % 2 ? 3 : 1;885Size src_size, dst_size;886887dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F;888if( src_depth < CV_32F && cvtest::randInt(rng) % 2 )889dst_depth = CV_32F;890891types[INPUT][0] = CV_MAKETYPE(src_depth,cn);892types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn);893894src_size = sizes[INPUT][0];895dst_size.width = cvRound(sqrt(cvtest::randReal(rng)*src_size.width) + 1);896dst_size.height = cvRound(sqrt(cvtest::randReal(rng)*src_size.height) + 1);897dst_size.width = MIN(dst_size.width,src_size.width);898dst_size.height = MIN(dst_size.width,src_size.height);899sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dst_size;900901center.x = (float)(cvtest::randReal(rng)*src_size.width);902center.y = (float)(cvtest::randReal(rng)*src_size.height);903interpolation = CV_INTER_LINEAR;904905test_cpp = (cvtest::randInt(rng) & 256) == 0;906}907908909void CV_GetRectSubPixTest::fill_array( int test_case_idx, int i, int j, Mat& arr )910{911if( i != INPUT )912CV_ImgWarpBaseTest::fill_array( test_case_idx, i, j, arr );913}914915916void CV_GetRectSubPixTest::run_func()917{918if(!test_cpp)919cvGetRectSubPix( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], center );920else921{922cv::Mat _out = cv::cvarrToMat(test_array[INPUT_OUTPUT][0]);923cv::getRectSubPix( cv::cvarrToMat(test_array[INPUT][0]), _out.size(), center, _out, _out.type());924}925}926927928double CV_GetRectSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )929{930int in_depth = test_mat[INPUT][0].depth();931int out_depth = test_mat[INPUT_OUTPUT][0].depth();932933return in_depth >= CV_32F ? 1e-3 : out_depth >= CV_32F ? 1e-2 : 1;934}935936937int CV_GetRectSubPixTest::prepare_test_case( int test_case_idx )938{939return CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );940}941942943void CV_GetRectSubPixTest::prepare_to_validation( int /*test_case_idx*/ )944{945Mat& src0 = test_mat[INPUT][0];946Mat& dst0 = test_mat[REF_INPUT_OUTPUT][0];947Mat src = src0, dst = dst0;948int ftype = CV_MAKETYPE(CV_32F,src0.channels());949double a[] = { 1, 0, center.x - dst.cols*0.5 + 0.5,9500, 1, center.y - dst.rows*0.5 + 0.5 };951if( src.depth() != CV_32F )952src0.convertTo(src, CV_32F);953954if( dst.depth() != CV_32F )955dst.create(dst0.size(), ftype);956957test_getQuadrangeSubPix( src, dst, a );958959if( dst.data != dst0.data )960dst.convertTo(dst0, dst0.depth());961}962963964class CV_GetQuadSubPixTest : public CV_ImgWarpBaseTest965{966public:967CV_GetQuadSubPixTest();968969protected:970void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );971void run_func();972int prepare_test_case( int test_case_idx );973void prepare_to_validation( int /*test_case_idx*/ );974double get_success_error_level( int test_case_idx, int i, int j );975};976977978CV_GetQuadSubPixTest::CV_GetQuadSubPixTest() : CV_ImgWarpBaseTest( true )979{980//spatial_scale_zoom = spatial_scale_decimate;981spatial_scale_decimate = spatial_scale_zoom;982}983984985void CV_GetQuadSubPixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )986{987int min_size = 4;988CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );989Size sz = sizes[INPUT][0], dsz;990RNG& rng = ts->get_rng();991int msz, src_depth = cvtest::randInt(rng) % 2, dst_depth;992int cn = cvtest::randInt(rng) % 2 ? 3 : 1;993994dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F;995if( src_depth < CV_32F && cvtest::randInt(rng) % 2 )996dst_depth = CV_32F;997998types[INPUT][0] = CV_MAKETYPE(src_depth,cn);999types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn);10001001sz.width = MAX(sz.width,min_size);1002sz.height = MAX(sz.height,min_size);1003sizes[INPUT][0] = sz;1004msz = MIN( sz.width, sz.height );10051006dsz.width = cvRound(sqrt(cvtest::randReal(rng)*msz) + 1);1007dsz.height = cvRound(sqrt(cvtest::randReal(rng)*msz) + 1);1008dsz.width = MIN(dsz.width,msz);1009dsz.height = MIN(dsz.width,msz);1010dsz.width = MAX(dsz.width,min_size);1011dsz.height = MAX(dsz.height,min_size);1012sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dsz;1013sizes[INPUT][1] = cvSize( 3, 2 );1014}101510161017void CV_GetQuadSubPixTest::run_func()1018{1019CvMat mtx = cvMat(test_mat[INPUT][1]);1020cvGetQuadrangleSubPix( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &mtx );1021}102210231024double CV_GetQuadSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )1025{1026int in_depth = test_mat[INPUT][0].depth();1027//int out_depth = test_mat[INPUT_OUTPUT][0].depth();10281029return in_depth >= CV_32F ? 1e-2 : 4;1030}103110321033int CV_GetQuadSubPixTest::prepare_test_case( int test_case_idx )1034{1035RNG& rng = ts->get_rng();1036int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );1037const Mat& src = test_mat[INPUT][0];1038Mat& mat = test_mat[INPUT][1];1039Point2f center;1040double scale, angle;10411042if( code <= 0 )1043return code;10441045double a[6];1046Mat A( 2, 3, CV_64FC1, a );10471048center.x = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.cols);1049center.y = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.rows);1050angle = cvtest::randReal(rng)*360;1051scale = cvtest::randReal(rng)*0.2 + 0.9;10521053// y = Ax + b -> x = A^-1(y - b) = A^-1*y - A^-1*b1054scale = 1./scale;1055angle = angle*(CV_PI/180.);1056a[0] = a[4] = cos(angle)*scale;1057a[1] = sin(angle)*scale;1058a[3] = -a[1];1059a[2] = center.x - a[0]*center.x - a[1]*center.y;1060a[5] = center.y - a[3]*center.x - a[4]*center.y;1061A.convertTo( mat, mat.depth() );10621063return code;1064}106510661067void CV_GetQuadSubPixTest::prepare_to_validation( int /*test_case_idx*/ )1068{1069Mat& src0 = test_mat[INPUT][0];1070Mat& dst0 = test_mat[REF_INPUT_OUTPUT][0];1071Mat src = src0, dst = dst0;1072int ftype = CV_MAKETYPE(CV_32F,src0.channels());1073double a[6], dx = (dst0.cols - 1)*0.5, dy = (dst0.rows - 1)*0.5;1074Mat A( 2, 3, CV_64F, a );10751076if( src.depth() != CV_32F )1077src0.convertTo(src, CV_32F);10781079if( dst.depth() != CV_32F )1080dst.create(dst0.size(), ftype);10811082test_mat[INPUT][1].convertTo( A, CV_64F );1083a[2] -= a[0]*dx + a[1]*dy;1084a[5] -= a[3]*dx + a[4]*dy;1085test_getQuadrangeSubPix( src, dst, a );10861087if( dst.data != dst0.data )1088dst.convertTo(dst0, dst0.depth());1089}10901091////////////////////////////// resizeArea /////////////////////////////////10921093template <typename T>1094static void check_resize_area(const Mat& expected, const Mat& actual, double tolerance = 1.0)1095{1096ASSERT_EQ(actual.type(), expected.type());1097ASSERT_EQ(actual.size(), expected.size());10981099Mat diff;1100absdiff(actual, expected, diff);11011102Mat one_channel_diff = diff; //.reshape(1);11031104Size dsize = actual.size();1105bool next = true;1106for (int dy = 0; dy < dsize.height && next; ++dy)1107{1108const T* eD = expected.ptr<T>(dy);1109const T* aD = actual.ptr<T>(dy);11101111for (int dx = 0; dx < dsize.width && next; ++dx)1112if (fabs(static_cast<double>(aD[dx] - eD[dx])) > tolerance)1113{1114cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Inf norm: %f\n", static_cast<float>(cvtest::norm(actual, expected, NORM_INF)));1115cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Error in : (%d, %d)\n", dx, dy);11161117const int radius = 3;1118int rmin = MAX(dy - radius, 0), rmax = MIN(dy + radius, dsize.height);1119int cmin = MAX(dx - radius, 0), cmax = MIN(dx + radius, dsize.width);11201121std::cout << "Abs diff:" << std::endl << diff << std::endl;1122std::cout << "actual result:\n" << actual(Range(rmin, rmax), Range(cmin, cmax)) << std::endl;1123std::cout << "expected result:\n" << expected(Range(rmin, rmax), Range(cmin, cmax)) << std::endl;11241125next = false;1126}1127}11281129ASSERT_EQ(0, cvtest::norm(one_channel_diff, cv::NORM_INF));1130}11311132///////////////////////////////////////////////////////////////////////////11331134TEST(Imgproc_cvWarpAffine, regression)1135{1136IplImage* src = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1);1137IplImage* dst = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1);11381139cvZero(src);11401141float m[6];1142CvMat M = cvMat( 2, 3, CV_32F, m );1143int w = src->width;1144int h = src->height;1145cv2DRotationMatrix(cvPoint2D32f(w*0.5f, h*0.5f), 45.0, 1.0, &M);1146cvWarpAffine(src, dst, &M);11471148cvReleaseImage(&src);1149cvReleaseImage(&dst);1150}11511152TEST(Imgproc_fitLine_vector_3d, regression)1153{1154std::vector<Point3f> points_vector;11551156Point3f p21(4,4,4);1157Point3f p22(8,8,8);11581159points_vector.push_back(p21);1160points_vector.push_back(p22);11611162std::vector<float> line;11631164cv::fitLine(points_vector, line, CV_DIST_L2, 0 ,0 ,0);11651166ASSERT_EQ(line.size(), (size_t)6);11671168}11691170TEST(Imgproc_fitLine_vector_2d, regression)1171{1172std::vector<Point2f> points_vector;11731174Point2f p21(4,4);1175Point2f p22(8,8);1176Point2f p23(16,16);11771178points_vector.push_back(p21);1179points_vector.push_back(p22);1180points_vector.push_back(p23);11811182std::vector<float> line;11831184cv::fitLine(points_vector, line, CV_DIST_L2, 0 ,0 ,0);11851186ASSERT_EQ(line.size(), (size_t)4);1187}11881189TEST(Imgproc_fitLine_Mat_2dC2, regression)1190{1191cv::Mat mat1 = Mat::zeros(3, 1, CV_32SC2);1192std::vector<float> line1;11931194cv::fitLine(mat1, line1, CV_DIST_L2, 0 ,0 ,0);11951196ASSERT_EQ(line1.size(), (size_t)4);1197}11981199TEST(Imgproc_fitLine_Mat_2dC1, regression)1200{1201cv::Matx<int, 3, 2> mat2;1202std::vector<float> line2;12031204cv::fitLine(mat2, line2, CV_DIST_L2, 0 ,0 ,0);12051206ASSERT_EQ(line2.size(), (size_t)4);1207}12081209TEST(Imgproc_fitLine_Mat_3dC3, regression)1210{1211cv::Mat mat1 = Mat::zeros(2, 1, CV_32SC3);1212std::vector<float> line1;12131214cv::fitLine(mat1, line1, CV_DIST_L2, 0 ,0 ,0);12151216ASSERT_EQ(line1.size(), (size_t)6);1217}12181219TEST(Imgproc_fitLine_Mat_3dC1, regression)1220{1221cv::Mat mat2 = Mat::zeros(2, 3, CV_32SC1);1222std::vector<float> line2;12231224cv::fitLine(mat2, line2, CV_DIST_L2, 0 ,0 ,0);12251226ASSERT_EQ(line2.size(), (size_t)6);1227}12281229TEST(Imgproc_resize_area, regression)1230{1231static ushort input_data[16 * 16] = {123290, 94, 80, 3, 231, 2, 186, 245, 188, 165, 10, 19, 201, 169, 8, 228,123386, 5, 203, 120, 136, 185, 24, 94, 81, 150, 163, 137, 88, 105, 132, 132,1234236, 48, 250, 218, 19, 52, 54, 221, 159, 112, 45, 11, 152, 153, 112, 134,123578, 133, 136, 83, 65, 76, 82, 250, 9, 235, 148, 26, 236, 179, 200, 50,123699, 51, 103, 142, 201, 65, 176, 33, 49, 226, 177, 109, 46, 21, 67, 130,123754, 125, 107, 154, 145, 51, 199, 189, 161, 142, 231, 240, 139, 162, 240, 22,1238231, 86, 79, 106, 92, 47, 146, 156, 36, 207, 71, 33, 2, 244, 221, 71,123944, 127, 71, 177, 75, 126, 68, 119, 200, 129, 191, 251, 6, 236, 247, 6,1240133, 175, 56, 239, 147, 221, 243, 154, 242, 82, 106, 99, 77, 158, 60, 229,12412, 42, 24, 174, 27, 198, 14, 204, 246, 251, 141, 31, 114, 163, 29, 147,1242121, 53, 74, 31, 147, 189, 42, 98, 202, 17, 228, 123, 209, 40, 77, 49,1243112, 203, 30, 12, 205, 25, 19, 106, 145, 185, 163, 201, 237, 223, 247, 38,124433, 105, 243, 117, 92, 179, 204, 248, 160, 90, 73, 126, 2, 41, 213, 204,12456, 124, 195, 201, 230, 187, 210, 167, 48, 79, 123, 159, 145, 218, 105, 209,1246240, 152, 136, 235, 235, 164, 157, 9, 152, 38, 27, 209, 120, 77, 238, 196,1247240, 233, 10, 241, 90, 67, 12, 79, 0, 43, 58, 27, 83, 199, 190, 182};12481249static ushort expected_data[5 * 5] = {1250120, 100, 151, 101, 130,1251106, 115, 141, 130, 127,125291, 136, 170, 114, 140,1253104, 122, 131, 147, 133,1254161, 163, 70, 107, 1821255};12561257cv::Mat src(16, 16, CV_16UC1, input_data);1258cv::Mat expected(5, 5, CV_16UC1, expected_data);1259cv::Mat actual(expected.size(), expected.type());12601261cv::resize(src, actual, cv::Size(), 0.3, 0.3, INTER_AREA);12621263check_resize_area<ushort>(expected, actual, 1.0);1264}12651266TEST(Imgproc_resize_area, regression_half_round)1267{1268static uchar input_data[32 * 32];1269for(int i = 0; i < 32 * 32; ++i)1270input_data[i] = (uchar)(i % 2 + 253 + i / (16 * 32));12711272static uchar expected_data[16 * 16];1273for(int i = 0; i < 16 * 16; ++i)1274expected_data[i] = (uchar)(254 + i / (16 * 8));12751276cv::Mat src(32, 32, CV_8UC1, input_data);1277cv::Mat expected(16, 16, CV_8UC1, expected_data);1278cv::Mat actual(expected.size(), expected.type());12791280cv::resize(src, actual, cv::Size(), 0.5, 0.5, INTER_AREA);12811282check_resize_area<uchar>(expected, actual, 0.5);1283}12841285TEST(Imgproc_resize_area, regression_quarter_round)1286{1287static uchar input_data[32 * 32];1288for(int i = 0; i < 32 * 32; ++i)1289input_data[i] = (uchar)(i % 2 + 253 + i / (16 * 32));12901291static uchar expected_data[8 * 8];1292for(int i = 0; i < 8 * 8; ++i)1293expected_data[i] = 254;12941295cv::Mat src(32, 32, CV_8UC1, input_data);1296cv::Mat expected(8, 8, CV_8UC1, expected_data);1297cv::Mat actual(expected.size(), expected.type());12981299cv::resize(src, actual, cv::Size(), 0.25, 0.25, INTER_AREA);13001301check_resize_area<uchar>(expected, actual, 0.5);1302}130313041305//////////////////////////////////////////////////////////////////////////13061307TEST(Imgproc_Resize, accuracy) { CV_ResizeTest test; test.safe_run(); }1308TEST(Imgproc_ResizeExact, accuracy) { CV_ResizeExactTest test; test.safe_run(); }1309TEST(Imgproc_WarpAffine, accuracy) { CV_WarpAffineTest test; test.safe_run(); }1310TEST(Imgproc_WarpPerspective, accuracy) { CV_WarpPerspectiveTest test; test.safe_run(); }1311TEST(Imgproc_Remap, accuracy) { CV_RemapTest test; test.safe_run(); }1312TEST(Imgproc_GetRectSubPix, accuracy) { CV_GetRectSubPixTest test; test.safe_run(); }1313TEST(Imgproc_GetQuadSubPix, accuracy) { CV_GetQuadSubPixTest test; test.safe_run(); }13141315//////////////////////////////////////////////////////////////////////////13161317template <typename T, typename WT>1318struct IntCast1319{1320T operator() (WT val) const1321{1322return cv::saturate_cast<T>(val >> 2);1323}1324};13251326template <typename T, typename WT>1327struct FltCast1328{1329T operator() (WT val) const1330{1331return cv::saturate_cast<T>(val * 0.25);1332}1333};13341335template <typename T, typename WT, int one, typename CastOp>1336void resizeArea(const cv::Mat & src, cv::Mat & dst)1337{1338int cn = src.channels();1339CastOp castOp;13401341for (int y = 0; y < dst.rows; ++y)1342{1343const T * sptr0 = src.ptr<T>(y << 1);1344const T * sptr1 = src.ptr<T>((y << 1) + 1);1345T * dptr = dst.ptr<T>(y);13461347for (int x = 0; x < dst.cols * cn; x += cn)1348{1349int x1 = x << 1;13501351for (int c = 0; c < cn; ++c)1352{1353WT sum = WT(sptr0[x1 + c]) + WT(sptr0[x1 + c + cn]);1354sum += WT(sptr1[x1 + c]) + WT(sptr1[x1 + c + cn]) + (WT)(one);13551356dptr[x + c] = castOp(sum);1357}1358}1359}1360}13611362TEST(Resize, Area_half)1363{1364const int size = 1000;1365int types[] = { CV_8UC1, CV_8UC4,1366CV_16UC1, CV_16UC4,1367CV_16SC1, CV_16SC3, CV_16SC4,1368CV_32FC1, CV_32FC4 };13691370cv::RNG rng(17);13711372for (int i = 0, _size = sizeof(types) / sizeof(types[0]); i < _size; ++i)1373{1374int type = types[i], depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);1375const float eps = depth <= CV_32S ? 0 : 7e-5f;13761377SCOPED_TRACE(depth);1378SCOPED_TRACE(cn);13791380cv::Mat src(size, size, type), dst_actual(size >> 1, size >> 1, type),1381dst_reference(size >> 1, size >> 1, type);13821383rng.fill(src, cv::RNG::UNIFORM, -1000, 1000, true);13841385if (depth == CV_8U)1386resizeArea<uchar, ushort, 2, IntCast<uchar, ushort> >(src, dst_reference);1387else if (depth == CV_16U)1388resizeArea<ushort, uint, 2, IntCast<ushort, uint> >(src, dst_reference);1389else if (depth == CV_16S)1390resizeArea<short, int, 2, IntCast<short, int> >(src, dst_reference);1391else if (depth == CV_32F)1392resizeArea<float, float, 0, FltCast<float, float> >(src, dst_reference);1393else1394CV_Assert(0);13951396cv::resize(src, dst_actual, dst_actual.size(), 0, 0, cv::INTER_AREA);13971398ASSERT_GE(eps, cvtest::norm(dst_reference, dst_actual, cv::NORM_INF));1399}1400}14011402TEST(Imgproc_Warp, multichannel)1403{1404static const int inter_types[] = {INTER_NEAREST, INTER_AREA, INTER_CUBIC,1405INTER_LANCZOS4, INTER_LINEAR};1406static const int inter_n = sizeof(inter_types) / sizeof(int);14071408static const int border_types[] = {BORDER_CONSTANT, BORDER_DEFAULT,1409BORDER_REFLECT, BORDER_REPLICATE,1410BORDER_WRAP, BORDER_WRAP};1411static const int border_n = sizeof(border_types) / sizeof(int);14121413RNG& rng = theRNG();1414for( int iter = 0; iter < 100; iter++ )1415{1416int inter = inter_types[rng.uniform(0, inter_n)];1417int border = border_types[rng.uniform(0, border_n)];1418int width = rng.uniform(3, 333);1419int height = rng.uniform(3, 333);1420int cn = rng.uniform(1, 15);1421if(inter == INTER_CUBIC || inter == INTER_LANCZOS4)1422cn = rng.uniform(1, 5);1423Mat src(height, width, CV_8UC(cn)), dst;1424//randu(src, 0, 256);1425src.setTo(0.);14261427Mat rot = getRotationMatrix2D(Point2f(0.f, 0.f), 1.0, 1.0);1428warpAffine(src, dst, rot, src.size(), inter, border);1429ASSERT_EQ(0.0, cvtest::norm(dst, NORM_INF));1430Mat rot2 = Mat::eye(3, 3, rot.type());1431rot.copyTo(rot2.rowRange(0, 2));1432warpPerspective(src, dst, rot2, src.size(), inter, border);1433ASSERT_EQ(0.0, cvtest::norm(dst, NORM_INF));1434}1435}14361437TEST(Imgproc_GetAffineTransform, singularity)1438{1439Point2f A_sample[3];1440A_sample[0] = Point2f(8.f, 9.f);1441A_sample[1] = Point2f(40.f, 41.f);1442A_sample[2] = Point2f(47.f, 48.f);1443Point2f B_sample[3];1444B_sample[0] = Point2f(7.37465f, 11.8295f);1445B_sample[1] = Point2f(15.0113f, 12.8994f);1446B_sample[2] = Point2f(38.9943f, 9.56297f);1447Mat trans = getAffineTransform(A_sample, B_sample);1448ASSERT_EQ(0.0, cvtest::norm(trans, NORM_INF));1449}14501451TEST(Imgproc_Remap, DISABLED_memleak)1452{1453Mat src;1454const int N = 400;1455src.create(N, N, CV_8U);1456randu(src, 0, 256);1457Mat map_x, map_y, dst;1458dst.create( src.size(), src.type() );1459map_x.create( src.size(), CV_32FC1 );1460map_y.create( src.size(), CV_32FC1 );1461randu(map_x, 0., N+0.);1462randu(map_y, 0., N+0.);14631464for( int iter = 0; iter < 10000; iter++ )1465{1466if(iter % 100 == 0)1467{1468putchar('.');1469fflush(stdout);1470}1471remap(src, dst, map_x, map_y, CV_INTER_LINEAR);1472}1473}14741475//** @deprecated */1476TEST(Imgproc_linearPolar, identity)1477{1478const int N = 33;1479Mat in(N, N, CV_8UC3, Scalar(255, 0, 0));1480in(cv::Rect(N/3, N/3, N/3, N/3)).setTo(Scalar::all(255));1481cv::blur(in, in, Size(5, 5));1482cv::blur(in, in, Size(5, 5));14831484Mat src = in.clone();1485Mat dst;14861487Rect roi = Rect(0, 0, in.cols - ((N+19)/20), in.rows);14881489for (int i = 1; i <= 5; i++)1490{1491linearPolar(src, dst,1492Point2f((N-1) * 0.5f, (N-1) * 0.5f), N * 0.5f,1493CV_WARP_FILL_OUTLIERS | CV_INTER_LINEAR | CV_WARP_INVERSE_MAP);14941495linearPolar(dst, src,1496Point2f((N-1) * 0.5f, (N-1) * 0.5f), N * 0.5f,1497CV_WARP_FILL_OUTLIERS | CV_INTER_LINEAR);14981499double psnr = cvtest::PSNR(in(roi), src(roi));1500EXPECT_LE(25, psnr) << "iteration=" << i;1501}15021503#if 01504Mat all(N*2+2,N*2+2, src.type(), Scalar(0,0,255));1505in.copyTo(all(Rect(0,0,N,N)));1506src.copyTo(all(Rect(0,N+1,N,N)));1507src.copyTo(all(Rect(N+1,0,N,N)));1508dst.copyTo(all(Rect(N+1,N+1,N,N)));1509imwrite("linearPolar.png", all);1510imshow("input", in); imshow("result", dst); imshow("restore", src); imshow("all", all);1511cv::waitKey();1512#endif1513}15141515//** @deprecated */1516TEST(Imgproc_logPolar, identity)1517{1518const int N = 33;1519Mat in(N, N, CV_8UC3, Scalar(255, 0, 0));1520in(cv::Rect(N/3, N/3, N/3, N/3)).setTo(Scalar::all(255));1521cv::blur(in, in, Size(5, 5));1522cv::blur(in, in, Size(5, 5));15231524Mat src = in.clone();1525Mat dst;15261527Rect roi = Rect(0, 0, in.cols - ((N+19)/20), in.rows);15281529double M = N/log(N * 0.5f);1530for (int i = 1; i <= 5; i++)1531{1532logPolar(src, dst,1533Point2f((N-1) * 0.5f, (N-1) * 0.5f), M,1534CV_WARP_FILL_OUTLIERS | CV_INTER_LINEAR | CV_WARP_INVERSE_MAP);15351536logPolar(dst, src,1537Point2f((N-1) * 0.5f, (N-1) * 0.5f), M,1538CV_WARP_FILL_OUTLIERS | CV_INTER_LINEAR);15391540double psnr = cvtest::PSNR(in(roi), src(roi));1541EXPECT_LE(25, psnr) << "iteration=" << i;1542}15431544#if 01545Mat all(N*2+2,N*2+2, src.type(), Scalar(0,0,255));1546in.copyTo(all(Rect(0,0,N,N)));1547src.copyTo(all(Rect(0,N+1,N,N)));1548src.copyTo(all(Rect(N+1,0,N,N)));1549dst.copyTo(all(Rect(N+1,N+1,N,N)));1550imwrite("logPolar.png", all);1551imshow("input", in); imshow("result", dst); imshow("restore", src); imshow("all", all);1552cv::waitKey();1553#endif1554}15551556TEST(Imgproc_warpPolar, identity)1557{1558const int N = 33;1559Mat in(N, N, CV_8UC3, Scalar(255, 0, 0));1560in(cv::Rect(N / 3, N / 3, N / 3, N / 3)).setTo(Scalar::all(255));1561cv::blur(in, in, Size(5, 5));1562cv::blur(in, in, Size(5, 5));15631564Mat src = in.clone();1565Mat dst;15661567Rect roi = Rect(0, 0, in.cols - ((N + 19) / 20), in.rows);1568Point2f center = Point2f((N - 1) * 0.5f, (N - 1) * 0.5f);1569double radius = N * 0.5;1570int flags = CV_WARP_FILL_OUTLIERS | CV_INTER_LINEAR;1571// test linearPolar1572for (int ki = 1; ki <= 5; ki++)1573{1574warpPolar(src, dst, src.size(), center, radius, flags + WARP_POLAR_LINEAR + CV_WARP_INVERSE_MAP);1575warpPolar(dst, src, src.size(), center, radius, flags + WARP_POLAR_LINEAR);15761577double psnr = cv::PSNR(in(roi), src(roi));1578EXPECT_LE(25, psnr) << "iteration=" << ki;1579}1580// test logPolar1581src = in.clone();1582for (int ki = 1; ki <= 5; ki++)1583{1584warpPolar(src, dst, src.size(),center, radius, flags + WARP_POLAR_LOG + CV_WARP_INVERSE_MAP );1585warpPolar(dst, src, src.size(),center, radius, flags + WARP_POLAR_LOG);15861587double psnr = cv::PSNR(in(roi), src(roi));1588EXPECT_LE(25, psnr) << "iteration=" << ki;1589}15901591#if 01592Mat all(N*2+2,N*2+2, src.type(), Scalar(0,0,255));1593in.copyTo(all(Rect(0,0,N,N)));1594src.copyTo(all(Rect(0,N+1,N,N)));1595src.copyTo(all(Rect(N+1,0,N,N)));1596dst.copyTo(all(Rect(N+1,N+1,N,N)));1597imwrite("linearPolar.png", all);1598imshow("input", in); imshow("result", dst); imshow("restore", src); imshow("all", all);1599cv::waitKey();1600#endif1601}16021603}} // namespace1604/* End of file. */160516061607