]> rtime.felk.cvut.cz Git - opencv.git/blob - opencv/tests/cv/src/aimgwarp.cpp
c36360a94c54ea683cfd36ddf7c1bc69ebc014b3
[opencv.git] / opencv / tests / cv / src / aimgwarp.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "cvtest.h"
43
44 static const int imgwarp_depths[] = { CV_8U, CV_16U, CV_32F, -1 };
45 static const int imgwarp_channels[] = { 1, 3, 4, -1 };
46 static const CvSize imgwarp_sizes[] = {{320, 240}, {1024,768}, {-1,-1}};
47
48 static const double imgwarp_resize_coeffs[] = { 0.5, 0.333, 2, 2.9 };
49 static const char* imgwarp_resize_methods[] = { "nearest", "linear", "cubic", "area", 0 };
50 static const char* imgwarp_resize_param_names[] = { "method", "coeff", "size", "channels", "depth", 0 };
51
52 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} };
53 static const char* imgwarp_affine_param_names[] = { "rotate_scale", "size", "channels", "depth", 0 };
54
55 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} };
56 static const char* imgwarp_perspective_param_names[] = { "shift_vtx", "size", "channels", "depth", 0 };
57
58 class CV_ImgWarpBaseTestImpl : public CvArrTest
59 {
60 public:
61     CV_ImgWarpBaseTestImpl( const char* test_name, const char* test_funcs, bool warp_matrix );
62
63 protected:
64     int read_params( CvFileStorage* fs );
65     int prepare_test_case( int test_case_idx );
66     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
67     void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
68     void fill_array( int test_case_idx, int i, int j, CvMat* arr );
69
70     int interpolation;
71     int max_interpolation;
72     double spatial_scale_zoom, spatial_scale_decimate;
73 };
74
75
76 CV_ImgWarpBaseTestImpl::CV_ImgWarpBaseTestImpl( const char* test_name, const char* test_funcs, bool warp_matrix )
77     : CvArrTest( test_name, test_funcs, "" )
78 {
79     test_array[INPUT].push(NULL);
80     if( warp_matrix )
81         test_array[INPUT].push(NULL);
82     test_array[INPUT_OUTPUT].push(NULL);
83     test_array[REF_INPUT_OUTPUT].push(NULL);
84     max_interpolation = 5;
85     interpolation = 0;
86     element_wise_relative_error = false;
87     spatial_scale_zoom = 0.01;
88     spatial_scale_decimate = 0.005;
89
90     size_list = whole_size_list = imgwarp_sizes;
91     depth_list = imgwarp_depths;
92     cn_list = imgwarp_channels;
93     default_timing_param_names = 0;
94 }
95
96
97 int CV_ImgWarpBaseTestImpl::read_params( CvFileStorage* fs )
98 {
99     int code = CvArrTest::read_params( fs );
100     return code;
101 }
102
103
104 void CV_ImgWarpBaseTestImpl::get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high )
105 {
106     CvArrTest::get_minmax_bounds( i, j, type, low, high );
107     if( CV_MAT_DEPTH(type) == CV_32F )
108     {
109         *low = cvScalarAll(-10.);
110         *high = cvScalarAll(10);
111     }
112 }
113
114
115 void CV_ImgWarpBaseTestImpl::get_test_array_types_and_sizes( int test_case_idx,
116                                                 CvSize** sizes, int** types )
117 {
118     CvRNG* rng = ts->get_rng();
119     int depth = cvTsRandInt(rng) % 3;
120     int cn = cvTsRandInt(rng) % 3 + 1;
121     CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
122     depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : CV_32F;
123     cn += cn == 2;
124
125     types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn);
126     if( test_array[INPUT].size() > 1 )
127         types[INPUT][1] = cvTsRandInt(rng) & 1 ? CV_32FC1 : CV_64FC1;
128
129     interpolation = cvTsRandInt(rng) % max_interpolation;
130 }
131
132
133 void CV_ImgWarpBaseTestImpl::fill_array( int test_case_idx, int i, int j, CvMat* arr )
134 {
135     if( i != INPUT || j != 0 )
136         CvArrTest::fill_array( test_case_idx, i, j, arr );
137 }
138
139 int CV_ImgWarpBaseTestImpl::prepare_test_case( int test_case_idx )
140 {
141     int code = CvArrTest::prepare_test_case( test_case_idx );
142     CvMat* img = &test_mat[INPUT][0];
143     int i, j, cols = img->cols;
144     int type = CV_MAT_TYPE(img->type), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
145     double scale = depth == CV_16U ? 1000. : 255.*0.5;
146     double space_scale = spatial_scale_decimate;
147     float* buffer;
148
149     if( code <= 0 )
150         return code;
151
152     if( test_mat[INPUT_OUTPUT][0].cols >= img->cols &&
153         test_mat[INPUT_OUTPUT][0].rows >= img->rows )
154         space_scale = spatial_scale_zoom;
155
156     buffer = (float*)cvAlloc( img->cols*cn*sizeof(buffer[0]) );
157     
158     for( i = 0; i < img->rows; i++ )
159     {
160         uchar* ptr = img->data.ptr + i*img->step;
161         switch( cn )
162         {
163         case 1:
164             for( j = 0; j < cols; j++ )
165                 buffer[j] = (float)((sin((i+1)*space_scale)*sin((j+1)*space_scale)+1.)*scale);
166             break;
167         case 2:
168             for( j = 0; j < cols; j++ )
169             {
170                 buffer[j*2] = (float)((sin((i+1)*space_scale)+1.)*scale);
171                 buffer[j*2+1] = (float)((sin((i+j)*space_scale)+1.)*scale);
172             }
173             break;
174         case 3:
175             for( j = 0; j < cols; j++ )
176             {
177                 buffer[j*3] = (float)((sin((i+1)*space_scale)+1.)*scale);
178                 buffer[j*3+1] = (float)((sin(j*space_scale)+1.)*scale);
179                 buffer[j*3+2] = (float)((sin((i+j)*space_scale)+1.)*scale);
180             }
181             break;
182         case 4:
183             for( j = 0; j < cols; j++ )
184             {
185                 buffer[j*4] = (float)((sin((i+1)*space_scale)+1.)*scale);
186                 buffer[j*4+1] = (float)((sin(j*space_scale)+1.)*scale);
187                 buffer[j*4+2] = (float)((sin((i+j)*space_scale)+1.)*scale);
188                 buffer[j*4+3] = (float)((sin((i-j)*space_scale)+1.)*scale);
189             }
190             break;
191         default:
192             assert(0);
193         }
194
195         switch( depth )
196         {
197         case CV_8U:
198             for( j = 0; j < cols*cn; j++ )
199                 ptr[j] = (uchar)cvRound(buffer[j]);
200             break;
201         case CV_16U:
202             for( j = 0; j < cols*cn; j++ )
203                 ((ushort*)ptr)[j] = (ushort)cvRound(buffer[j]);
204             break;
205         case CV_32F:
206             for( j = 0; j < cols*cn; j++ )
207                 ((float*)ptr)[j] = (float)buffer[j];
208             break;
209         default:
210             assert(0);
211         }
212     }
213
214     cvFree( &buffer );
215
216     return code;
217 }
218
219 CV_ImgWarpBaseTestImpl imgwarp_base( "warp", "", false );
220
221
222 class CV_ImgWarpBaseTest : public CV_ImgWarpBaseTestImpl
223 {
224 public:
225     CV_ImgWarpBaseTest( const char* test_name, const char* test_funcs, bool warp_matrix );
226 };
227
228
229 CV_ImgWarpBaseTest::CV_ImgWarpBaseTest( const char* test_name, const char* test_funcs, bool warp_matrix )
230     : CV_ImgWarpBaseTestImpl( test_name, test_funcs, warp_matrix )
231 {
232     size_list = whole_size_list = 0;
233     depth_list = 0;
234     cn_list = 0;
235 }
236
237
238 /////////////////////////
239
240 class CV_ResizeTest : public CV_ImgWarpBaseTest
241 {
242 public:
243     CV_ResizeTest();
244
245 protected:
246     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
247     void run_func();
248     void prepare_to_validation( int /*test_case_idx*/ );
249     double get_success_error_level( int test_case_idx, int i, int j );
250
251     int write_default_params(CvFileStorage* fs);
252     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
253                                                 CvSize** whole_sizes, bool *are_images );
254     void print_timing_params( int test_case_idx, char* ptr, int params_left );
255 };
256
257
258 CV_ResizeTest::CV_ResizeTest()
259     : CV_ImgWarpBaseTest( "warp-resize", "cvResize", false )
260 {
261     default_timing_param_names = imgwarp_resize_param_names;
262 }
263
264
265 int CV_ResizeTest::write_default_params( CvFileStorage* fs )
266 {
267     int code = CV_ImgWarpBaseTest::write_default_params( fs );
268     if( code < 0 )
269         return code;
270     
271     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
272     {
273         start_write_param( fs );
274         write_real_list( fs, "coeff", imgwarp_resize_coeffs, CV_DIM(imgwarp_resize_coeffs) );
275         write_string_list( fs, "method", imgwarp_resize_methods );
276     }
277
278     return code;
279 }
280
281
282 void CV_ResizeTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
283 {
284     CvRNG* rng = ts->get_rng();
285     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
286     CvSize sz;
287
288     sz.width = (cvTsRandInt(rng) % sizes[INPUT][0].width) + 1;
289     sz.height = (cvTsRandInt(rng) % sizes[INPUT][0].height) + 1;
290
291     if( cvTsRandInt(rng) & 1 )
292     {
293         int xfactor = cvTsRandInt(rng) % 10 + 1;
294         int yfactor = cvTsRandInt(rng) % 10 + 1;
295
296         if( cvTsRandInt(rng) & 1 )
297             yfactor = xfactor;
298
299         sz.width = sizes[INPUT][0].width / xfactor;
300         sz.width = MAX(sz.width,1);
301         sz.height = sizes[INPUT][0].height / yfactor;
302         sz.height = MAX(sz.height,1);
303         sizes[INPUT][0].width = sz.width * xfactor;
304         sizes[INPUT][0].height = sz.height * yfactor;
305     }
306
307     if( cvTsRandInt(rng) & 1 )
308         sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = sz;
309     else
310     {
311         sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = sizes[INPUT][0];
312         sizes[INPUT][0] = sz;
313     }
314     if( interpolation == 4 &&
315        (MIN(sizes[INPUT][0].width,sizes[INPUT_OUTPUT][0].width) < 4 ||
316         MIN(sizes[INPUT][0].height,sizes[INPUT_OUTPUT][0].height) < 4))
317         interpolation = 2;
318 }
319
320
321 void CV_ResizeTest::get_timing_test_array_types_and_sizes( int test_case_idx,
322                 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
323 {
324     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
325                                                                whole_sizes, are_images );
326     const char* method_str = cvReadString( find_timing_param( "method" ), "linear" );
327     double coeff = cvReadReal( find_timing_param( "coeff" ), 1. );
328     CvSize size = sizes[INPUT][0];
329
330     size.width = cvRound(size.width*coeff);
331     size.height = cvRound(size.height*coeff);
332     sizes[INPUT_OUTPUT][0] = whole_sizes[INPUT_OUTPUT][0] = size;
333
334     interpolation = strcmp( method_str, "nearest" ) == 0 ? CV_INTER_NN :
335                     strcmp( method_str, "linear" ) == 0 ? CV_INTER_LINEAR :
336                     strcmp( method_str, "cubic" ) == 0 ? CV_INTER_CUBIC : CV_INTER_AREA;
337 }
338
339
340 void CV_ResizeTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
341 {
342     sprintf( ptr, "coeff=%.3f,", cvReadReal( find_timing_param( "coeff" ), 1. ) );
343     ptr += strlen(ptr);
344     sprintf( ptr, "method=%s,", cvReadString( find_timing_param( "method" ), "linear" ) );
345     ptr += strlen(ptr);
346     params_left -= 2;
347
348     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
349 }
350
351
352 void CV_ResizeTest::run_func()
353 {
354     cvResize( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], interpolation );
355 }
356
357
358 double CV_ResizeTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
359 {
360     int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
361     return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 1e-1;
362 }
363
364
365 void CV_ResizeTest::prepare_to_validation( int /*test_case_idx*/ )
366 {
367     CvMat* src = &test_mat[INPUT][0];
368     CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0];
369     int i, j, k;
370     CvMat* x_idx = cvCreateMat( 1, dst->cols, CV_32SC1 );
371     CvMat* y_idx = cvCreateMat( 1, dst->rows, CV_32SC1 );
372     int* x_tab = x_idx->data.i;
373     int elem_size = CV_ELEM_SIZE(src->type); 
374     int drows = dst->rows, dcols = dst->cols;
375
376     if( interpolation == CV_INTER_NN )
377     {
378         for( j = 0; j < dcols; j++ )
379         {
380             int t = (j*src->cols*2 + MIN(src->cols,dcols) - 1)/(dcols*2);
381             t -= t >= src->cols;
382             x_idx->data.i[j] = t*elem_size;
383         }
384
385         for( j = 0; j < drows; j++ )
386         {
387             int t = (j*src->rows*2 + MIN(src->rows,drows) - 1)/(drows*2);
388             t -= t >= src->rows;
389             y_idx->data.i[j] = t;
390         }
391     }
392     else
393     {
394         double scale_x = (double)src->cols/dcols;
395         double scale_y = (double)src->rows/drows;
396         
397         for( j = 0; j < dcols; j++ )
398         {
399             double f = ((j+0.5)*scale_x - 0.5);
400             i = cvRound(f);
401             x_idx->data.i[j] = (i < 0 ? 0 : i >= src->cols ? src->cols - 1 : i)*elem_size;
402         }
403
404         for( j = 0; j < drows; j++ )
405         {
406             double f = ((j+0.5)*scale_y - 0.5);
407             i = cvRound(f);
408             y_idx->data.i[j] = i < 0 ? 0 : i >= src->rows ? src->rows - 1 : i;
409         }
410     }
411
412     for( i = 0; i < drows; i++ )
413     {
414         uchar* dptr = dst->data.ptr + dst->step*i;
415         const uchar* sptr0 = src->data.ptr + src->step*y_idx->data.i[i];
416         
417         for( j = 0; j < dcols; j++, dptr += elem_size )
418         {
419             const uchar* sptr = sptr0 + x_tab[j];
420             for( k = 0; k < elem_size; k++ )
421                 dptr[k] = sptr[k];
422         }
423     }
424
425     cvReleaseMat( &x_idx );
426     cvReleaseMat( &y_idx );
427 }
428
429 CV_ResizeTest warp_resize_test;
430
431
432 /////////////////////////
433
434 void cvTsRemap( const CvMat* src, CvMat* dst,
435                 const CvMat* mapx, const CvMat* mapy,
436                 CvMat* mask, int interpolation=CV_INTER_LINEAR )
437 {
438     int x, y, k;
439     int drows = dst->rows, dcols = dst->cols;
440     int srows = src->rows, scols = src->cols;
441     uchar* sptr0 = src->data.ptr;
442     int depth = CV_MAT_DEPTH(src->type), cn = CV_MAT_CN(src->type);
443     int elem_size = CV_ELEM_SIZE(src->type);
444     int step = src->step / CV_ELEM_SIZE(depth);
445     int delta;
446
447     if( interpolation != CV_INTER_CUBIC )
448     {
449         delta = 0;
450         scols -= 1; srows -= 1;
451     }
452     else
453     {
454         delta = 1;
455         scols = MAX(scols - 3, 0);
456         srows = MAX(srows - 3, 0);
457     }
458
459     int scols1 = MAX(scols - 2, 0);
460     int srows1 = MAX(srows - 2, 0);
461
462     if( mask )
463         cvTsZero(mask);
464
465     for( y = 0; y < drows; y++ )
466     {
467         uchar* dptr = dst->data.ptr + dst->step*y;
468         const float* mx = (const float*)(mapx->data.ptr + mapx->step*y);
469         const float* my = (const float*)(mapy->data.ptr + mapy->step*y);
470         uchar* m = mask ? mask->data.ptr + mask->step*y : 0;
471
472         for( x = 0; x < dcols; x++, dptr += elem_size )
473         {
474             float xs = mx[x];
475             float ys = my[x];
476             int ixs = cvFloor(xs);
477             int iys = cvFloor(ys);
478
479             if( (unsigned)(ixs - delta - 1) >= (unsigned)scols1 ||
480                 (unsigned)(iys - delta - 1) >= (unsigned)srows1 )
481             {
482                 if( m )
483                     m[x] = 1;
484                 if( (unsigned)(ixs - delta) >= (unsigned)scols ||
485                     (unsigned)(iys - delta) >= (unsigned)srows )
486                     continue;
487             }
488
489             xs -= ixs;
490             ys -= iys;
491             
492             switch( depth )
493             {
494             case CV_8U:
495                 {
496                 const uchar* sptr = sptr0 + iys*step + ixs*cn;
497                 for( k = 0; k < cn; k++ )
498                 {
499                     float v00 = sptr[k];
500                     float v01 = sptr[cn + k];
501                     float v10 = sptr[step + k];
502                     float v11 = sptr[step + cn + k];
503
504                     v00 = v00 + xs*(v01 - v00);
505                     v10 = v10 + xs*(v11 - v10);
506                     v00 = v00 + ys*(v10 - v00);
507                     dptr[k] = (uchar)cvRound(v00);
508                 }
509                 }
510                 break;
511             case CV_16U:
512                 {
513                 const ushort* sptr = (const ushort*)sptr0 + iys*step + ixs*cn;
514                 for( k = 0; k < cn; k++ )
515                 {
516                     float v00 = sptr[k];
517                     float v01 = sptr[cn + k];
518                     float v10 = sptr[step + k];
519                     float v11 = sptr[step + cn + k];
520
521                     v00 = v00 + xs*(v01 - v00);
522                     v10 = v10 + xs*(v11 - v10);
523                     v00 = v00 + ys*(v10 - v00);
524                     ((ushort*)dptr)[k] = (ushort)cvRound(v00);
525                 }
526                 }
527                 break;
528             case CV_32F:
529                 {
530                 const float* sptr = (const float*)sptr0 + iys*step + ixs*cn;
531                 for( k = 0; k < cn; k++ )
532                 {
533                     float v00 = sptr[k];
534                     float v01 = sptr[cn + k];
535                     float v10 = sptr[step + k];
536                     float v11 = sptr[step + cn + k];
537
538                     v00 = v00 + xs*(v01 - v00);
539                     v10 = v10 + xs*(v11 - v10);
540                     v00 = v00 + ys*(v10 - v00);
541                     ((float*)dptr)[k] = (float)v00;
542                 }
543                 }
544                 break;
545             default:
546                 assert(0);
547             }
548         }
549     }
550 }
551
552 /////////////////////////
553
554 class CV_WarpAffineTest : public CV_ImgWarpBaseTest
555 {
556 public:
557     CV_WarpAffineTest();
558
559 protected:
560     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
561     void run_func();
562     int prepare_test_case( int test_case_idx );
563     void prepare_to_validation( int /*test_case_idx*/ );
564     double get_success_error_level( int test_case_idx, int i, int j );
565
566     int write_default_params(CvFileStorage* fs);
567     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
568                                                 CvSize** whole_sizes, bool *are_images );
569     void print_timing_params( int test_case_idx, char* ptr, int params_left );
570 };
571
572
573 CV_WarpAffineTest::CV_WarpAffineTest()
574     : CV_ImgWarpBaseTest( "warp-affine", "cvWarpAffine", true )
575 {
576     //spatial_scale_zoom = spatial_scale_decimate;
577     test_array[TEMP].push(NULL);
578     test_array[TEMP].push(NULL);
579     
580     spatial_scale_decimate = spatial_scale_zoom;
581
582     default_timing_param_names = imgwarp_affine_param_names;
583 }
584
585
586 int CV_WarpAffineTest::write_default_params( CvFileStorage* fs )
587 {
588     int code = CV_ImgWarpBaseTest::write_default_params( fs );
589     if( code < 0 )
590         return code;
591     
592     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
593     {
594         int i;
595         start_write_param( fs );
596
597         cvStartWriteStruct( fs, "rotate_scale", CV_NODE_SEQ+CV_NODE_FLOW );
598         for( i = 0; imgwarp_affine_rotate_scale[i][0] >= 0; i++ )
599         {
600             cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW );
601             cvWriteRawData( fs, imgwarp_affine_rotate_scale[i], 4, "d" );
602             cvEndWriteStruct(fs);
603         }
604         cvEndWriteStruct(fs);
605     }
606
607     return code;
608 }
609
610
611 void CV_WarpAffineTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
612 {
613     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
614     CvSize sz = sizes[INPUT][0];
615     // run for the second time to get output of a different size
616     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
617     sizes[INPUT][0] = sz;
618     sizes[INPUT][1] = cvSize( 3, 2 );
619     sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT_OUTPUT][0];
620     types[TEMP][0] = types[TEMP][1] = CV_32FC1;
621 }
622
623
624 void CV_WarpAffineTest::get_timing_test_array_types_and_sizes( int test_case_idx,
625                 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
626 {
627     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
628                                                                whole_sizes, are_images );
629
630     sizes[INPUT][1] = whole_sizes[INPUT][1] = cvSize(3,2);
631     sizes[TEMP][0] = whole_sizes[TEMP][0] =
632         sizes[TEMP][1] = whole_sizes[TEMP][1] = cvSize(0,0);
633     types[INPUT][1] = CV_64FC1;
634
635     interpolation = CV_INTER_LINEAR;
636 }
637
638
639 void CV_WarpAffineTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
640 {
641     double coeffs[4];
642     const CvFileNode* node = find_timing_param( "rotate_scale" );
643     assert( node && CV_NODE_IS_SEQ(node->tag) );
644     cvReadRawData( ts->get_file_storage(), node, coeffs, "4d" );
645     
646     sprintf( ptr, "fx=%.2f,fy=%.2f,angle=%.1fdeg,scale=%.1f,", coeffs[0], coeffs[1], coeffs[2], coeffs[3] );
647     ptr += strlen(ptr);
648     params_left -= 4;
649
650     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
651 }
652
653
654 void CV_WarpAffineTest::run_func()
655 {
656     cvWarpAffine( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],
657                   &test_mat[INPUT][1], interpolation );
658 }
659
660
661 double CV_WarpAffineTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
662 {
663     int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
664     return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
665 }
666
667
668 int CV_WarpAffineTest::prepare_test_case( int test_case_idx )
669 {
670     CvRNG* rng = ts->get_rng();
671     int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
672     const CvMat* src = &test_mat[INPUT][0];
673     const CvMat* dst = &test_mat[INPUT_OUTPUT][0]; 
674     CvMat* mat = &test_mat[INPUT][1];
675     CvPoint2D32f center;
676     double scale, angle;
677
678     if( code <= 0 )
679         return code;
680
681     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
682     {
683         double buf[6];
684         CvMat tmp = cvMat( 2, 3, mat->type, buf );
685
686         center.x = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->cols);
687         center.y = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->rows);
688         angle = cvTsRandReal(rng)*360;
689         scale = ((double)dst->rows/src->rows + (double)dst->cols/src->cols)*0.5;
690         cv2DRotationMatrix( center, angle, scale, mat );
691         cvRandArr( rng, &tmp, CV_RAND_NORMAL, cvScalarAll(1.), cvScalarAll(0.01) );
692         cvMaxS( &tmp, 0.9, &tmp );
693         cvMinS( &tmp, 1.1, &tmp );
694         cvMul( &tmp, mat, mat, 1. );
695     }
696     else
697     {
698         double coeffs[4];
699         const CvFileNode* node = find_timing_param( "rotate_scale" );
700
701         assert( node && CV_NODE_IS_SEQ(node->tag) );
702         cvReadRawData( ts->get_file_storage(), node, coeffs, "4d" );
703
704         center.x = (float)(coeffs[0]*src->cols);
705         center.y = (float)(coeffs[1]*src->rows);
706         angle = coeffs[2];
707         scale = coeffs[3];
708         cv2DRotationMatrix( center, angle, scale, mat );
709     }
710
711     return code;
712 }
713
714
715 void CV_WarpAffineTest::prepare_to_validation( int /*test_case_idx*/ )
716 {
717     CvMat* src = &test_mat[INPUT][0];
718     CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0];
719     CvMat* dst0 = &test_mat[INPUT_OUTPUT][0];
720     CvMat* mapx = &test_mat[TEMP][0];
721     CvMat* mapy = &test_mat[TEMP][1];
722     int x, y;
723     double m[6], tm[6];
724     CvMat srcAb = cvMat(2, 3, CV_64FC1, tm ), A, b, invA, invAb, dstAb = cvMat( 2, 3, CV_64FC1, m );
725
726     //cvInvert( &tM, &M, CV_LU );
727     // [R|t] -> [R^-1 | -(R^-1)*t]
728     cvTsConvert( &test_mat[INPUT][1], &srcAb );
729     cvGetCols( &srcAb, &A, 0, 2 );
730     cvGetCol( &srcAb, &b, 2 );
731     cvGetCols( &dstAb, &invA, 0, 2 );
732     cvGetCol( &dstAb, &invAb, 2 );
733     cvInvert( &A, &invA, CV_SVD );
734     cvGEMM( &invA, &b, -1, 0, 0, &invAb );
735
736     for( y = 0; y < dst->rows; y++ )
737     {
738         float* mx = (float*)(mapx->data.ptr + y*mapx->step);
739         float* my = (float*)(mapy->data.ptr + y*mapy->step);
740
741         for( x = 0; x < dst->cols; x++ )
742         {
743             mx[x] = (float)(x*m[0] + y*m[1] + m[2]);
744             my[x] = (float)(x*m[3] + y*m[4] + m[5]);
745         }
746     }
747
748     CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U );
749     cvTsRemap( src, dst, mapx, mapy, mask );
750     cvTsZero( dst, mask );
751     cvTsZero( dst0, mask );
752     cvReleaseMat( &mask );
753 }
754
755
756 CV_WarpAffineTest warp_affine_test;
757
758
759
760 /////////////////////////
761
762 class CV_WarpPerspectiveTest : public CV_ImgWarpBaseTest
763 {
764 public:
765     CV_WarpPerspectiveTest();
766
767 protected:
768     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
769     void run_func();
770     int prepare_test_case( int test_case_idx );
771     void prepare_to_validation( int /*test_case_idx*/ );
772     double get_success_error_level( int test_case_idx, int i, int j );
773
774     int write_default_params(CvFileStorage* fs);
775     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
776                                                 CvSize** whole_sizes, bool *are_images );
777     void print_timing_params( int test_case_idx, char* ptr, int params_left );
778 };
779
780
781 CV_WarpPerspectiveTest::CV_WarpPerspectiveTest()
782     : CV_ImgWarpBaseTest( "warp-perspective", "cvWarpPerspective", true )
783 {
784     //spatial_scale_zoom = spatial_scale_decimate;
785     test_array[TEMP].push(NULL);
786     test_array[TEMP].push(NULL);
787
788     spatial_scale_decimate = spatial_scale_zoom;
789     default_timing_param_names = imgwarp_perspective_param_names;
790 }
791
792
793 int CV_WarpPerspectiveTest::write_default_params( CvFileStorage* fs )
794 {
795     int code = CV_ImgWarpBaseTest::write_default_params( fs );
796     if( code < 0 )
797         return code;
798     
799     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
800     {
801         int i;
802         start_write_param( fs );
803
804         cvStartWriteStruct( fs, "shift_vtx", CV_NODE_SEQ+CV_NODE_FLOW );
805         for( i = 0; imgwarp_perspective_shift_vtx[i][0] >= 0; i++ )
806         {
807             cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW );
808             cvWriteRawData( fs, imgwarp_perspective_shift_vtx[i], 8, "d" );
809             cvEndWriteStruct(fs);
810         }
811         cvEndWriteStruct(fs);
812     }
813
814     return code;
815 }
816
817
818 void CV_WarpPerspectiveTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
819 {
820     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
821     CvSize sz = sizes[INPUT][0];
822     // run for the second time to get output of a different size
823     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
824     sizes[INPUT][0] = sz;
825     sizes[INPUT][1] = cvSize( 3, 3 );
826
827     sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT_OUTPUT][0];
828     types[TEMP][0] = types[TEMP][1] = CV_32FC1;
829 }
830
831
832 void CV_WarpPerspectiveTest::get_timing_test_array_types_and_sizes( int test_case_idx,
833                 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
834 {
835     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
836                                                                whole_sizes, are_images );
837
838     sizes[INPUT][1] = whole_sizes[INPUT][1] = cvSize(3,3);
839     sizes[TEMP][0] = whole_sizes[TEMP][0] =
840         sizes[TEMP][1] = whole_sizes[TEMP][1] = cvSize(0,0);
841     types[INPUT][1] = CV_64FC1;
842
843     interpolation = CV_INTER_LINEAR;
844 }
845
846
847 void CV_WarpPerspectiveTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
848 {
849     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
850 }
851
852
853 void CV_WarpPerspectiveTest::run_func()
854 {
855     cvWarpPerspective( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],
856                        &test_mat[INPUT][1], interpolation );
857 }
858
859
860 double CV_WarpPerspectiveTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
861 {
862     int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
863     return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
864 }
865
866
867 int CV_WarpPerspectiveTest::prepare_test_case( int test_case_idx )
868 {
869     CvRNG* rng = ts->get_rng();
870     int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
871     const CvMat* src = &test_mat[INPUT][0];
872     const CvMat* dst = &test_mat[INPUT_OUTPUT][0]; 
873     CvMat* mat = &test_mat[INPUT][1];
874     CvPoint2D32f s[4], d[4];
875     int i;
876
877     if( code <= 0 )
878         return code;
879
880     s[0] = cvPoint2D32f(0,0);
881     d[0] = cvPoint2D32f(0,0);
882     s[1] = cvPoint2D32f(src->cols-1,0);
883     d[1] = cvPoint2D32f(dst->cols-1,0);
884     s[2] = cvPoint2D32f(src->cols-1,src->rows-1);
885     d[2] = cvPoint2D32f(dst->cols-1,dst->rows-1);
886     s[3] = cvPoint2D32f(0,src->rows-1);
887     d[3] = cvPoint2D32f(0,dst->rows-1);
888
889     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
890     {
891         float buf[16];
892         CvMat tmp = cvMat( 1, 16, CV_32FC1, buf );
893
894         cvRandArr( rng, &tmp, CV_RAND_NORMAL, cvScalarAll(0.), cvScalarAll(0.1) );
895
896         for( i = 0; i < 4; i++ )
897         {
898             s[i].x += buf[i*4]*src->cols/2;
899             s[i].y += buf[i*4+1]*src->rows/2;
900             d[i].x += buf[i*4+2]*dst->cols/2;
901             d[i].y += buf[i*4+3]*dst->rows/2;
902         }
903     }
904     else
905     {
906         double coeffs[8];
907         const CvFileNode* node = find_timing_param( "shift_vtx" );
908
909         assert( node && CV_NODE_IS_SEQ(node->tag) );
910         cvReadRawData( ts->get_file_storage(), node, coeffs, "8d" );
911
912         for( i = 0; i < 4; i++ )
913         {
914             d[i].x += (float)(coeffs[i*2]*src->cols*(i == 0 || i == 3 ? 1 : -1));
915             d[i].y += (float)(coeffs[i*2+1]*src->rows*(i == 0 || i == 1 ? 1 : -1));
916         }
917     }
918
919     cvWarpPerspectiveQMatrix( s, d, mat );
920     return code;
921 }
922
923
924 void CV_WarpPerspectiveTest::prepare_to_validation( int /*test_case_idx*/ )
925 {
926     CvMat* src = &test_mat[INPUT][0];
927     CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0];
928     CvMat* dst0 = &test_mat[INPUT_OUTPUT][0];
929     CvMat* mapx = &test_mat[TEMP][0];
930     CvMat* mapy = &test_mat[TEMP][1];
931     int x, y;
932     double m[9], tm[9];
933     CvMat srcM = cvMat(3, 3, CV_64FC1, tm ), dstM = cvMat( 3, 3, CV_64FC1, m );
934
935     //cvInvert( &tM, &M, CV_LU );
936     // [R|t] -> [R^-1 | -(R^-1)*t]
937     cvTsConvert( &test_mat[INPUT][1], &srcM );
938     cvInvert( &srcM, &dstM, CV_SVD );
939
940     for( y = 0; y < dst->rows; y++ )
941     {
942         float* mx = (float*)(mapx->data.ptr + y*mapx->step);
943         float* my = (float*)(mapy->data.ptr + y*mapy->step);
944
945         for( x = 0; x < dst->cols; x++ )
946         {
947             double xs = x*m[0] + y*m[1] + m[2];
948             double ys = x*m[3] + y*m[4] + m[5];
949             double ds = x*m[6] + y*m[7] + m[8];
950             
951             ds = ds ? 1./ds : 0;
952             xs *= ds;
953             ys *= ds;
954             
955             mx[x] = (float)xs;
956             my[x] = (float)ys;
957         }
958     }
959
960     CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U );
961     cvTsRemap( src, dst, mapx, mapy, mask );
962     cvTsZero( dst, mask );
963     cvTsZero( dst0, mask );
964     cvReleaseMat( &mask );
965 }
966
967
968 CV_WarpPerspectiveTest warp_perspective_test;
969
970
971
972 /////////////////////////
973
974 void cvTsInitUndistortMap( const CvMat* _a0, const CvMat* _k0, CvMat* _mapx, CvMat* _mapy )
975 {
976         CvMat* mapx = cvCreateMat(_mapx->rows,_mapx->cols,CV_32F);
977         CvMat* mapy = cvCreateMat(_mapx->rows,_mapx->cols,CV_32F);
978
979     int u, v;
980     double a[9], k[5]={0,0,0,0,0};
981     CvMat _a = cvMat(3, 3, CV_64F, a);
982     CvMat _k = cvMat(_k0->rows,_k0->cols,
983         CV_MAKETYPE(CV_64F,CV_MAT_CN(_k0->type)),k);
984     double fx, fy, cx, cy, ifx, ify, cxn, cyn;
985     
986     cvTsConvert( _a0, &_a );
987     cvTsConvert( _k0, &_k );
988     fx = a[0]; fy = a[4]; cx = a[2]; cy = a[5];
989     ifx = 1./fx; ify = 1./fy;
990     cxn = cx;//(mapy->cols - 1)*0.5;
991     cyn = cy;//(mapy->rows - 1)*0.5;
992
993     for( v = 0; v < mapy->rows; v++ )
994     {
995         float* mx = (float*)(mapx->data.ptr + v*mapx->step);
996                 float* my = (float*)(mapy->data.ptr + v*mapy->step);
997         
998         for( u = 0; u < mapy->cols; u++ )
999         {
1000             double x = (u - cxn)*ifx;
1001             double y = (v - cyn)*ify;
1002             double x2 = x*x, y2 = y*y;
1003             double r2 = x2 + y2;
1004             double cdist = 1 + (k[0] + (k[1] + k[4]*r2)*r2)*r2;
1005             double x1 = x*cdist + k[2]*2*x*y + k[3]*(r2 + 2*x2);
1006             double y1 = y*cdist + k[3]*2*x*y + k[2]*(r2 + 2*y2);
1007            
1008                         my[u] = (float)(y1*fy + cy);
1009                         mx[u] = (float)(x1*fx + cx);
1010         }
1011     }
1012
1013         if (_mapy)
1014         {
1015                 cvCopy(mapy,_mapy);
1016                 cvCopy(mapx,_mapx);
1017         }
1018         else
1019         {
1020                 for (int i=0;i<mapx->rows;i++)
1021                 {
1022                         float* _mx = (float*)(_mapx->data.ptr + _mapx->step*i);
1023                         float* _my = (float*)(_mapx->data.ptr + _mapx->step*i);
1024                         for (int j=0;j<mapx->cols;j++)
1025                         {
1026                                 _mx[2*j] = mapx->data.fl[j+i*mapx->cols];
1027                                 _my[2*j+1] = mapy->data.fl[j+i*mapy->cols];
1028                         }
1029                 }
1030         }
1031         cvReleaseMat(&mapx);
1032         cvReleaseMat(&mapy);
1033 }
1034
1035
1036 static double remap_undistort_params[] = { 0.5, 0.5, 0.5, 0.5, 0.01, -0.01, 0.001, -0.001 };
1037
1038 class CV_RemapTest : public CV_ImgWarpBaseTest
1039 {
1040 public:
1041     CV_RemapTest();
1042
1043 protected:
1044     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1045     void run_func();
1046     int prepare_test_case( int test_case_idx );
1047     void prepare_to_validation( int /*test_case_idx*/ );
1048     double get_success_error_level( int test_case_idx, int i, int j );
1049     void fill_array( int test_case_idx, int i, int j, CvMat* arr );
1050
1051     int write_default_params(CvFileStorage* fs);
1052     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1053                                                 CvSize** whole_sizes, bool *are_images );
1054     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1055 };
1056
1057
1058 CV_RemapTest::CV_RemapTest()
1059     : CV_ImgWarpBaseTest( "warp-remap", "cvRemap", false )
1060 {
1061     //spatial_scale_zoom = spatial_scale_decimate;
1062     test_array[INPUT].push(NULL);
1063     test_array[INPUT].push(NULL);
1064
1065     spatial_scale_decimate = spatial_scale_zoom;
1066     //default_timing_param_names = imgwarp_perspective_param_names;
1067     support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1068     default_timing_param_names = 0;
1069 }
1070
1071
1072 int CV_RemapTest::write_default_params( CvFileStorage* fs )
1073 {
1074     int code = CV_ImgWarpBaseTest::write_default_params( fs );
1075     if( code < 0 )
1076         return code;
1077     
1078     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
1079     {
1080         int i;
1081         start_write_param( fs );
1082
1083         cvStartWriteStruct( fs, "params", CV_NODE_SEQ+CV_NODE_FLOW );
1084         for( i = 0; i < 8; i++ )
1085             cvWriteReal( fs, 0, remap_undistort_params[i] );
1086         cvEndWriteStruct(fs);
1087     }
1088
1089     return code;
1090 }
1091
1092
1093 void CV_RemapTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1094 {
1095     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1096     types[INPUT][1] = types[INPUT][2] = CV_32FC1;
1097     interpolation = CV_INTER_LINEAR;
1098 }
1099
1100
1101 void CV_RemapTest::fill_array( int test_case_idx, int i, int j, CvMat* arr )
1102 {
1103     if( i != INPUT )
1104         CV_ImgWarpBaseTestImpl::fill_array( test_case_idx, i, j, arr );
1105 }
1106
1107 void CV_RemapTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1108         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1109 {
1110     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1111                                                                whole_sizes, are_images );
1112     types[INPUT][1] = types[INPUT][2] = CV_32FC1;
1113     interpolation = CV_INTER_LINEAR;
1114 }
1115
1116
1117 void CV_RemapTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1118 {
1119     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
1120 }
1121
1122
1123 void CV_RemapTest::run_func()
1124 {
1125     cvRemap( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],
1126              test_array[INPUT][1], test_array[INPUT][2], interpolation );
1127 }
1128
1129
1130 double CV_RemapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1131 {
1132     int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1133     return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
1134 }
1135
1136
1137 int CV_RemapTest::prepare_test_case( int test_case_idx )
1138 {
1139     CvRNG* rng = ts->get_rng();
1140     int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
1141     const CvMat* src = &test_mat[INPUT][0];
1142     double a[9] = {0,0,0,0,0,0,0,0,1}, k[4];
1143     CvMat _a = cvMat( 3, 3, CV_64F, a );
1144     CvMat _k = cvMat( 4, 1, CV_64F, k );
1145     double sz = MAX(src->rows, src->cols);
1146
1147     if( code <= 0 )
1148         return code;
1149
1150     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1151     {
1152         double aspect_ratio = cvTsRandReal(rng)*0.6 + 0.7;
1153         a[2] = (src->cols - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1154         a[5] = (src->rows - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1155         a[0] = sz/(0.9 - cvTsRandReal(rng)*0.6);
1156         a[4] = aspect_ratio*a[0];
1157         k[0] = cvTsRandReal(rng)*0.06 - 0.03;
1158         k[1] = cvTsRandReal(rng)*0.06 - 0.03;
1159         if( k[0]*k[1] > 0 )
1160             k[1] = -k[1];
1161         k[2] = cvTsRandReal(rng)*0.004 - 0.002;
1162         k[3] = cvTsRandReal(rng)*0.004 - 0.002;
1163     }
1164     else
1165     {
1166         int i;
1167         a[2] = (src->cols - 1)*remap_undistort_params[0];
1168         a[5] = (src->rows - 1)*remap_undistort_params[1];
1169         a[0] = sz/remap_undistort_params[2];
1170         a[4] = sz/remap_undistort_params[3];
1171         for( i = 0; i < 4; i++ )
1172             k[i] = remap_undistort_params[i+4];
1173     }
1174
1175     cvTsInitUndistortMap( &_a, &_k, &test_mat[INPUT][1], &test_mat[INPUT][2] );
1176     return code;
1177 }
1178
1179
1180 void CV_RemapTest::prepare_to_validation( int /*test_case_idx*/ )
1181 {
1182     CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0];
1183     CvMat* dst0 = &test_mat[INPUT_OUTPUT][0];
1184     CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U );
1185     cvTsRemap( &test_mat[INPUT][0], dst,
1186                &test_mat[INPUT][1], &test_mat[INPUT][2],
1187                mask, interpolation );
1188     cvTsZero( dst, mask );
1189     cvTsZero( dst0, mask );
1190     cvReleaseMat( &mask );
1191 }
1192
1193
1194 CV_RemapTest remap_test;
1195
1196
1197 ////////////////////////////// undistort /////////////////////////////////
1198
1199 class CV_UndistortTest : public CV_ImgWarpBaseTest
1200 {
1201 public:
1202     CV_UndistortTest();
1203
1204 protected:
1205     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1206     void run_func();
1207     int prepare_test_case( int test_case_idx );
1208     void prepare_to_validation( int /*test_case_idx*/ );
1209     double get_success_error_level( int test_case_idx, int i, int j );
1210     void fill_array( int test_case_idx, int i, int j, CvMat* arr );
1211
1212     int write_default_params(CvFileStorage* fs);
1213     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1214                                                 CvSize** whole_sizes, bool *are_images );
1215     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1216
1217 private:
1218         bool useCPlus;
1219         cv::Mat input0;
1220         cv::Mat input1;
1221         cv::Mat input2;
1222         cv::Mat input_new_cam;
1223         cv::Mat input_output;
1224
1225         bool zero_new_cam;
1226         bool zero_distortion;
1227 };
1228
1229
1230 CV_UndistortTest::CV_UndistortTest()
1231     : CV_ImgWarpBaseTest( "warp-undistort", "cvUndistort2", false )
1232 {
1233     //spatial_scale_zoom = spatial_scale_decimate;
1234     test_array[INPUT].push(NULL);
1235     test_array[INPUT].push(NULL);
1236         test_array[INPUT].push(NULL);
1237
1238     spatial_scale_decimate = spatial_scale_zoom;
1239     //default_timing_param_names = imgwarp_perspective_param_names;
1240     support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1241     default_timing_param_names = 0;
1242 }
1243
1244
1245 int CV_UndistortTest::write_default_params( CvFileStorage* fs )
1246 {
1247     int code = CV_ImgWarpBaseTest::write_default_params( fs );
1248     if( code < 0 )
1249         return code;
1250     
1251     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
1252     {
1253         int i;
1254         start_write_param( fs );
1255
1256         cvStartWriteStruct( fs, "params", CV_NODE_SEQ+CV_NODE_FLOW );
1257         for( i = 0; i < 8; i++ )
1258             cvWriteReal( fs, 0, remap_undistort_params[i] );
1259         cvEndWriteStruct(fs);
1260     }
1261
1262     return code;
1263 }
1264
1265
1266 void CV_UndistortTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1267 {
1268     CvRNG* rng = ts->get_rng();
1269     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1270     int type = types[INPUT][0];
1271     type = CV_MAKETYPE( CV_8U, CV_MAT_CN(type) ); 
1272     types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = type;
1273     types[INPUT][1] = cvTsRandInt(rng)%2 ? CV_64F : CV_32F;
1274     types[INPUT][2] = cvTsRandInt(rng)%2 ? CV_64F : CV_32F;
1275     sizes[INPUT][1] = cvSize(3,3);
1276     sizes[INPUT][2] = cvTsRandInt(rng)%2 ? cvSize(4,1) : cvSize(1,4);
1277         types[INPUT][3] =  types[INPUT][1];
1278         sizes[INPUT][3] = sizes[INPUT][1];
1279     interpolation = CV_INTER_LINEAR;
1280 }
1281
1282
1283 void CV_UndistortTest::fill_array( int test_case_idx, int i, int j, CvMat* arr )
1284 {
1285     if( i != INPUT )
1286         CV_ImgWarpBaseTestImpl::fill_array( test_case_idx, i, j, arr );
1287 }
1288
1289 void CV_UndistortTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1290         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1291 {
1292     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1293                                                                whole_sizes, are_images );
1294     types[INPUT][1] = types[INPUT][2] = CV_32FC1;
1295     interpolation = CV_INTER_LINEAR;
1296 }
1297
1298
1299 void CV_UndistortTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1300 {
1301     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
1302 }
1303
1304
1305 void CV_UndistortTest::run_func()
1306 {
1307         if (!useCPlus)
1308         {
1309                 cvUndistort2( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],
1310                  &test_mat[INPUT][1], &test_mat[INPUT][2] );
1311         }
1312         else
1313         {
1314                 if (zero_distortion)
1315                 {
1316                         cv::undistort(input0,input_output,input1,cv::Mat());
1317                 }
1318                 else
1319                 {
1320                         cv::undistort(input0,input_output,input1,input2);
1321                 }
1322         }
1323 }
1324
1325
1326 double CV_UndistortTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1327 {
1328     int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1329     return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
1330 }
1331
1332
1333 int CV_UndistortTest::prepare_test_case( int test_case_idx )
1334 {
1335     CvRNG* rng = ts->get_rng();
1336     int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
1337
1338     const CvMat* src = &test_mat[INPUT][0];
1339     double k[4], a[9] = {0,0,0,0,0,0,0,0,1};
1340     double sz = MAX(src->rows, src->cols);
1341
1342         double new_cam[9] = {0,0,0,0,0,0,0,0,1};
1343         CvMat _new_cam = cvMat(test_mat[INPUT][3].rows,test_mat[INPUT][3].cols,CV_64F,new_cam);
1344         CvMat* _new_cam0 = &test_mat[INPUT][3];
1345
1346     CvMat* _a0 = &test_mat[INPUT][1], *_k0 = &test_mat[INPUT][2];
1347     CvMat _a = cvMat(3,3,CV_64F,a);
1348     CvMat _k = cvMat(_k0->rows,_k0->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(_k0->type)),k);
1349
1350     if( code <= 0 )
1351         return code;
1352
1353     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1354     {
1355         double aspect_ratio = cvTsRandReal(rng)*0.6 + 0.7;
1356         a[2] = (src->cols - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1357         a[5] = (src->rows - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1358         a[0] = sz/(0.9 - cvTsRandReal(rng)*0.6);
1359         a[4] = aspect_ratio*a[0];
1360         k[0] = cvTsRandReal(rng)*0.06 - 0.03;
1361         k[1] = cvTsRandReal(rng)*0.06 - 0.03;
1362         if( k[0]*k[1] > 0 )
1363             k[1] = -k[1];
1364         if( cvTsRandInt(rng)%4 != 0 )
1365         {
1366             k[2] = cvTsRandReal(rng)*0.004 - 0.002;
1367             k[3] = cvTsRandReal(rng)*0.004 - 0.002;
1368         }
1369         else
1370             k[2] = k[3] = 0;
1371
1372                 new_cam[0] = a[0] + (cvTsRandReal(rng) - (double)0.5)*0.2*a[0]; //10%
1373                 new_cam[4] = a[4] + (cvTsRandReal(rng) - (double)0.5)*0.2*a[4]; //10%
1374                 new_cam[2] = a[2] + (cvTsRandReal(rng) - (double)0.5)*0.3*test_mat[INPUT][0].rows; //15%
1375                 new_cam[5] = a[5] + (cvTsRandReal(rng) - (double)0.5)*0.3*test_mat[INPUT][0].cols; //15%
1376     }
1377     else
1378     {
1379         int i;
1380         a[2] = (src->cols - 1)*remap_undistort_params[0];
1381         a[5] = (src->rows - 1)*remap_undistort_params[1];
1382         a[0] = sz/remap_undistort_params[2];
1383         a[4] = sz/remap_undistort_params[3];
1384         for( i = 0; i < 4; i++ )
1385             k[i] = remap_undistort_params[i+4];
1386     }
1387
1388     cvTsConvert( &_a, _a0 );
1389
1390
1391         zero_distortion = (cvRandInt(rng)%2) == 0 ? false : true;
1392         cvTsConvert( &_k, _k0 );
1393
1394         zero_new_cam = (cvRandInt(rng)%2) == 0 ? false : true;
1395         cvTsConvert( &_new_cam, _new_cam0 );
1396     
1397
1398         //Testing C++ code
1399         useCPlus = ((cvTsRandInt(rng) % 2)!=0);
1400         if (useCPlus)
1401         {
1402                 input0 = &test_mat[INPUT][0];
1403                 input1 = &test_mat[INPUT][1];
1404                 input2 = &test_mat[INPUT][2];
1405                 input_new_cam = &test_mat[INPUT][3];
1406         }
1407
1408     return code;
1409 }
1410
1411
1412 void CV_UndistortTest::prepare_to_validation( int /*test_case_idx*/ )
1413 {
1414         if (useCPlus)
1415         {
1416                 CvMat result = input_output;
1417                 CvMat* test_input_output = &test_mat[INPUT_OUTPUT][0];
1418                 cvTsConvert(&result,test_input_output);
1419         }
1420     CvMat* src = &test_mat[INPUT][0];
1421     CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0];
1422     CvMat* dst0 = &test_mat[INPUT_OUTPUT][0];
1423     CvMat* mapx = cvCreateMat( dst->rows, dst->cols, CV_32FC1 );
1424     CvMat* mapy = cvCreateMat( dst->rows, dst->cols, CV_32FC1 );
1425     cvTsInitUndistortMap( &test_mat[INPUT][1], &test_mat[INPUT][2],
1426                           mapx, mapy );
1427     CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U );
1428     cvTsRemap( src, dst, mapx, mapy, mask, interpolation );
1429     cvTsZero( dst, mask );
1430     cvTsZero( dst0, mask );
1431
1432     cvReleaseMat( &mapx );
1433     cvReleaseMat( &mapy );
1434     cvReleaseMat( &mask );
1435 }
1436
1437
1438 CV_UndistortTest undistort_test;
1439
1440
1441
1442 class CV_UndistortMapTest : public CvArrTest
1443 {
1444 public:
1445     CV_UndistortMapTest();
1446
1447 protected:
1448     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1449     void run_func();
1450     int prepare_test_case( int test_case_idx );
1451     void prepare_to_validation( int /*test_case_idx*/ );
1452     double get_success_error_level( int test_case_idx, int i, int j );
1453     void fill_array( int test_case_idx, int i, int j, CvMat* arr );
1454
1455     int write_default_params(CvFileStorage* fs);
1456     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1457                                                 CvSize** whole_sizes, bool *are_images );
1458     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1459 private:
1460         bool dualChannel;
1461 };
1462
1463
1464 CV_UndistortMapTest::CV_UndistortMapTest()
1465     : CvArrTest( "warp-undistort-map", "cvInitUndistortMap", "" )
1466 {
1467     test_array[INPUT].push(NULL);
1468     test_array[INPUT].push(NULL);
1469     test_array[OUTPUT].push(NULL);
1470     test_array[OUTPUT].push(NULL);
1471     test_array[REF_OUTPUT].push(NULL);
1472     test_array[REF_OUTPUT].push(NULL);
1473
1474     element_wise_relative_error = false;
1475
1476     support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1477     default_timing_param_names = 0;
1478 }
1479
1480
1481 int CV_UndistortMapTest::write_default_params( CvFileStorage* fs )
1482 {
1483     int code = CvArrTest::write_default_params( fs );
1484     if( code < 0 )
1485         return code;
1486     
1487     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
1488     {
1489         int i;
1490         start_write_param( fs );
1491
1492         cvStartWriteStruct( fs, "params", CV_NODE_SEQ+CV_NODE_FLOW );
1493         for( i = 0; i < 8; i++ )
1494             cvWriteReal( fs, 0, remap_undistort_params[i] );
1495         cvEndWriteStruct(fs);
1496     }
1497
1498     return code;
1499 }
1500
1501
1502 void CV_UndistortMapTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1503 {
1504     CvRNG* rng = ts->get_rng();
1505     CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1506     int depth = cvTsRandInt(rng)%2 ? CV_64F : CV_32F;
1507
1508
1509
1510     CvSize sz = sizes[OUTPUT][0];
1511     types[INPUT][0] = types[INPUT][1] = depth;
1512         dualChannel = cvTsRandInt(rng)%2 == 0;
1513     types[OUTPUT][0] = types[OUTPUT][1] = 
1514         types[REF_OUTPUT][0] = types[REF_OUTPUT][1] = dualChannel ? CV_32FC2 : CV_32F;
1515     sizes[INPUT][0] = cvSize(3,3);
1516     sizes[INPUT][1] = cvTsRandInt(rng)%2 ? cvSize(4,1) : cvSize(1,4);
1517
1518     sz.width = MAX(sz.width,16);
1519     sz.height = MAX(sz.height,16);
1520     sizes[OUTPUT][0] = sizes[OUTPUT][1] =
1521         sizes[REF_OUTPUT][0] = sizes[REF_OUTPUT][1] = sz;
1522 }
1523
1524
1525 void CV_UndistortMapTest::fill_array( int test_case_idx, int i, int j, CvMat* arr )
1526 {
1527     if( i != INPUT )
1528         CvArrTest::fill_array( test_case_idx, i, j, arr );
1529 }
1530
1531 void CV_UndistortMapTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1532         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1533 {
1534     CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1535                                                       whole_sizes, are_images );
1536 }
1537
1538
1539 void CV_UndistortMapTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1540 {
1541     CvArrTest::print_timing_params( test_case_idx, ptr, params_left );
1542 }
1543
1544
1545 void CV_UndistortMapTest::run_func()
1546 {
1547         if (!dualChannel )
1548                 cvInitUndistortMap( &test_mat[INPUT][0], &test_mat[INPUT][1],
1549                         test_array[OUTPUT][0], test_array[OUTPUT][1] );
1550         else
1551                 cvInitUndistortMap( &test_mat[INPUT][0], &test_mat[INPUT][1],
1552                         test_array[OUTPUT][0], 0 );
1553
1554 }
1555
1556
1557 double CV_UndistortMapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1558 {
1559     return 1e-3;
1560 }
1561
1562
1563 int CV_UndistortMapTest::prepare_test_case( int test_case_idx )
1564 {
1565     CvRNG* rng = ts->get_rng();
1566     int code = CvArrTest::prepare_test_case( test_case_idx );
1567     const CvMat* mapx = &test_mat[OUTPUT][0];
1568     double k[4], a[9] = {0,0,0,0,0,0,0,0,1};
1569     double sz = MAX(mapx->rows, mapx->cols);
1570     CvMat* _a0 = &test_mat[INPUT][0], *_k0 = &test_mat[INPUT][1];
1571     CvMat _a = cvMat(3,3,CV_64F,a);
1572     CvMat _k = cvMat(_k0->rows,_k0->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(_k0->type)),k);
1573
1574     if( code <= 0 )
1575         return code;
1576
1577     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1578     {
1579         double aspect_ratio = cvTsRandReal(rng)*0.6 + 0.7;
1580         a[2] = (mapx->cols - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1581         a[5] = (mapx->rows - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1582         a[0] = sz/(0.9 - cvTsRandReal(rng)*0.6);
1583         a[4] = aspect_ratio*a[0];
1584         k[0] = cvTsRandReal(rng)*0.06 - 0.03;
1585         k[1] = cvTsRandReal(rng)*0.06 - 0.03;
1586         if( k[0]*k[1] > 0 )
1587             k[1] = -k[1];
1588         k[2] = cvTsRandReal(rng)*0.004 - 0.002;
1589         k[3] = cvTsRandReal(rng)*0.004 - 0.002;
1590     }
1591     else
1592     {
1593         int i;
1594         a[2] = (mapx->cols - 1)*remap_undistort_params[0];
1595         a[5] = (mapx->rows - 1)*remap_undistort_params[1];
1596         a[0] = sz/remap_undistort_params[2];
1597         a[4] = sz/remap_undistort_params[3];
1598         for( i = 0; i < 4; i++ )
1599             k[i] = remap_undistort_params[i+4];
1600     }
1601
1602     cvTsConvert( &_a, _a0 );
1603         cvTsConvert( &_k, _k0 );
1604
1605         if (dualChannel)
1606         {
1607                 cvZero(&test_mat[REF_OUTPUT][1]);
1608                 cvZero(&test_mat[OUTPUT][1]);
1609         }
1610
1611     return code;
1612 }
1613
1614
1615 void CV_UndistortMapTest::prepare_to_validation( int test_case_idx )
1616 {
1617         if (!dualChannel )
1618                 cvTsInitUndistortMap( &test_mat[INPUT][0], &test_mat[INPUT][1],
1619                           &test_mat[REF_OUTPUT][0], &test_mat[REF_OUTPUT][1] );
1620         else
1621                 cvTsInitUndistortMap( &test_mat[INPUT][0], &test_mat[INPUT][1],
1622                           &test_mat[REF_OUTPUT][0], 0 );
1623 }
1624
1625
1626 CV_UndistortMapTest undistortmap_test;
1627
1628
1629
1630 ////////////////////////////// GetRectSubPix /////////////////////////////////
1631
1632 static const CvSize rectsubpix_sizes[] = {{11, 11}, {21,21}, {41,41},{-1,-1}};
1633
1634 static void
1635 cvTsGetQuadrangeSubPix( const CvMat* src, CvMat* dst, double* a )
1636 {
1637     int y, x, k, cn;
1638     int sstep = src->step / sizeof(float);
1639     int scols = src->cols, srows = src->rows;
1640     
1641     assert( CV_MAT_DEPTH(src->type) == CV_32F &&
1642             CV_ARE_TYPES_EQ(src, dst));
1643
1644     cn = CV_MAT_CN(dst->type);
1645
1646     for( y = 0; y < dst->rows; y++ )
1647         for( x = 0; x < dst->cols; x++ )
1648         {
1649             float* d = (float*)(dst->data.ptr + y*dst->step) + x*cn;
1650             float sx = (float)(a[0]*x + a[1]*y + a[2]);
1651             float sy = (float)(a[3]*x + a[4]*y + a[5]);
1652             int ix = cvFloor(sx), iy = cvFloor(sy);
1653             int dx = cn, dy = sstep;
1654             const float* s;
1655             sx -= ix; sy -= iy;
1656
1657             if( (unsigned)ix >= (unsigned)(scols-1) )
1658                 ix = ix < 0 ? 0 : scols - 1, sx = 0, dx = 0;
1659             if( (unsigned)iy >= (unsigned)(srows-1) )
1660                 iy = iy < 0 ? 0 : srows - 1, sy = 0, dy = 0;
1661
1662             s = src->data.fl + sstep*iy + ix*cn;
1663             for( k = 0; k < cn; k++, s++ )
1664             {
1665                 float t0 = s[0] + sx*(s[dx] - s[0]);
1666                 float t1 = s[dy] + sx*(s[dy + dx] - s[dy]);
1667                 d[k] = t0 + sy*(t1 - t0);
1668             }
1669         }
1670 }
1671
1672
1673 class CV_GetRectSubPixTest : public CV_ImgWarpBaseTest
1674 {
1675 public:
1676     CV_GetRectSubPixTest();
1677
1678 protected:
1679     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1680     void run_func();
1681     int prepare_test_case( int test_case_idx );
1682     void prepare_to_validation( int /*test_case_idx*/ );
1683     double get_success_error_level( int test_case_idx, int i, int j );
1684     void fill_array( int test_case_idx, int i, int j, CvMat* arr );
1685
1686     int write_default_params(CvFileStorage* fs);
1687     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1688                                                 CvSize** whole_sizes, bool *are_images );
1689     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1690     CvPoint2D32f center;
1691     bool test_cpp;
1692 };
1693
1694
1695 CV_GetRectSubPixTest::CV_GetRectSubPixTest()
1696     : CV_ImgWarpBaseTest( "warp-subpix-rect", "cvGetRectSubPix", false )
1697 {
1698     //spatial_scale_zoom = spatial_scale_decimate;
1699     spatial_scale_decimate = spatial_scale_zoom;
1700     //default_timing_param_names = imgwarp_perspective_param_names;
1701     support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1702     default_timing_param_names = 0;
1703     test_cpp = false;
1704 }
1705
1706
1707 int CV_GetRectSubPixTest::write_default_params( CvFileStorage* fs )
1708 {
1709     int code = CV_ImgWarpBaseTest::write_default_params( fs );
1710     if( code < 0 )
1711         return code;
1712     
1713     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
1714     {
1715         int i;
1716         start_write_param( fs );
1717
1718         cvStartWriteStruct( fs, "rect_size", CV_NODE_SEQ+CV_NODE_FLOW );
1719         for( i = 0; rectsubpix_sizes[i].width > 0; i++ )
1720         {
1721             cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW );
1722             cvWriteInt( fs, 0, rectsubpix_sizes[i].width );
1723             cvWriteInt( fs, 0, rectsubpix_sizes[i].height );
1724             cvEndWriteStruct(fs);
1725         }
1726         cvEndWriteStruct(fs);
1727     }
1728
1729     return code;
1730 }
1731
1732
1733 void CV_GetRectSubPixTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1734 {
1735     CvRNG* rng = ts->get_rng();
1736     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1737     int src_depth = cvTsRandInt(rng) % 2, dst_depth;
1738     int cn = cvTsRandInt(rng) % 2 ? 3 : 1;
1739     CvSize src_size, dst_size;
1740     
1741     dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F;
1742     if( src_depth < CV_32F && cvTsRandInt(rng) % 2 )
1743         dst_depth = CV_32F;
1744     
1745     types[INPUT][0] = CV_MAKETYPE(src_depth,cn);
1746     types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn);
1747
1748     src_size = sizes[INPUT][0];
1749     dst_size.width = cvRound(sqrt(cvTsRandReal(rng)*src_size.width) + 1);
1750     dst_size.height = cvRound(sqrt(cvTsRandReal(rng)*src_size.height) + 1);
1751     dst_size.width = MIN(dst_size.width,src_size.width);
1752     dst_size.height = MIN(dst_size.width,src_size.height);
1753     sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dst_size;
1754     
1755     center.x = (float)(cvTsRandReal(rng)*src_size.width);
1756     center.y = (float)(cvTsRandReal(rng)*src_size.height);
1757     interpolation = CV_INTER_LINEAR;
1758     
1759     test_cpp = (cvTsRandInt(rng) & 256) == 0;
1760 }
1761
1762
1763 void CV_GetRectSubPixTest::fill_array( int test_case_idx, int i, int j, CvMat* arr )
1764 {
1765     if( i != INPUT )
1766         CV_ImgWarpBaseTestImpl::fill_array( test_case_idx, i, j, arr );
1767 }
1768
1769 void CV_GetRectSubPixTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1770         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1771 {
1772     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1773                                                                whole_sizes, are_images );
1774     interpolation = CV_INTER_LINEAR;
1775 }
1776
1777
1778 void CV_GetRectSubPixTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1779 {
1780     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
1781 }
1782
1783
1784 void CV_GetRectSubPixTest::run_func()
1785 {
1786     if(!test_cpp)
1787         cvGetRectSubPix( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], center );
1788     else
1789     {
1790         cv::Mat _out = cv::cvarrToMat(test_array[INPUT_OUTPUT][0]);
1791         cv::getRectSubPix( cv::cvarrToMat(test_array[INPUT][0]), _out.size(), center, _out, _out.type());
1792     }
1793 }
1794
1795
1796 double CV_GetRectSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1797 {
1798     int in_depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1799     int out_depth = CV_MAT_DEPTH(test_mat[INPUT_OUTPUT][0].type);
1800
1801     return in_depth >= CV_32F ? 1e-3 : out_depth >= CV_32F ? 1e-2 : 1;
1802 }
1803
1804
1805 int CV_GetRectSubPixTest::prepare_test_case( int test_case_idx )
1806 {
1807     return CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
1808 }
1809
1810
1811 void CV_GetRectSubPixTest::prepare_to_validation( int /*test_case_idx*/ )
1812 {
1813     CvMat* src0 = &test_mat[INPUT][0];
1814     CvMat* dst0 = &test_mat[REF_INPUT_OUTPUT][0];
1815     CvMat* src = src0, *dst = dst0;
1816     int ftype = CV_MAKETYPE(CV_32F,CV_MAT_CN(src0->type));
1817     double a[] = { 1, 0, center.x - dst->cols*0.5 + 0.5,
1818                    0, 1, center.y - dst->rows*0.5 + 0.5 };
1819     if( CV_MAT_DEPTH(src->type) != CV_32F )
1820     {
1821         src = cvCreateMat( src0->rows, src0->cols, ftype );
1822         cvTsConvert( src0, src );
1823     }
1824
1825     if( CV_MAT_DEPTH(dst->type) != CV_32F )
1826         dst = cvCreateMat( dst0->rows, dst0->cols, ftype );
1827
1828     cvTsGetQuadrangeSubPix( src, dst, a );
1829
1830     if( dst != dst0 )
1831     {
1832         cvTsConvert( dst, dst0 );
1833         cvReleaseMat( &dst );
1834     }
1835     if( src != src0 )
1836         cvReleaseMat( &src );
1837 }
1838
1839
1840 CV_GetRectSubPixTest subpix_rect_test;
1841
1842
1843 class CV_GetQuadSubPixTest : public CV_ImgWarpBaseTest
1844 {
1845 public:
1846     CV_GetQuadSubPixTest();
1847
1848 protected:
1849     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1850     void run_func();
1851     int prepare_test_case( int test_case_idx );
1852     void prepare_to_validation( int /*test_case_idx*/ );
1853     double get_success_error_level( int test_case_idx, int i, int j );
1854
1855     int write_default_params(CvFileStorage* fs);
1856     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1857                                                 CvSize** whole_sizes, bool *are_images );
1858     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1859 };
1860
1861
1862 CV_GetQuadSubPixTest::CV_GetQuadSubPixTest()
1863     : CV_ImgWarpBaseTest( "warp-subpix-quad", "cvGetQuadSubPix", true )
1864 {
1865     //spatial_scale_zoom = spatial_scale_decimate;
1866     spatial_scale_decimate = spatial_scale_zoom;
1867     //default_timing_param_names = imgwarp_affine_param_names;
1868     support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1869     default_timing_param_names = 0;
1870 }
1871
1872
1873 int CV_GetQuadSubPixTest::write_default_params( CvFileStorage* fs )
1874 {
1875     int code = CV_ImgWarpBaseTest::write_default_params( fs );
1876     if( code < 0 )
1877         return code;
1878     
1879     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
1880     {
1881         int i;
1882         start_write_param( fs );
1883
1884         cvStartWriteStruct( fs, "rotate_scale", CV_NODE_SEQ+CV_NODE_FLOW );
1885         for( i = 0; imgwarp_affine_rotate_scale[i][0] >= 0; i++ )
1886         {
1887             cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW );
1888             cvWriteRawData( fs, imgwarp_affine_rotate_scale[i], 4, "d" );
1889             cvEndWriteStruct(fs);
1890         }
1891         cvEndWriteStruct(fs);
1892     }
1893
1894     return code;
1895 }
1896
1897
1898 void CV_GetQuadSubPixTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1899 {
1900     int min_size = 4;
1901     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1902     CvSize sz = sizes[INPUT][0], dsz;
1903     CvRNG* rng = ts->get_rng();
1904     int msz, src_depth = cvTsRandInt(rng) % 2, dst_depth;
1905     int cn = cvTsRandInt(rng) % 2 ? 3 : 1;
1906     
1907     dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F;
1908     if( src_depth < CV_32F && cvTsRandInt(rng) % 2 )
1909         dst_depth = CV_32F;
1910     
1911     types[INPUT][0] = CV_MAKETYPE(src_depth,cn);
1912     types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn);
1913
1914     sz.width = MAX(sz.width,min_size);
1915     sz.height = MAX(sz.height,min_size);
1916     sizes[INPUT][0] = sz;
1917     msz = MIN( sz.width, sz.height );
1918
1919     dsz.width = cvRound(sqrt(cvTsRandReal(rng)*msz) + 1);
1920     dsz.height = cvRound(sqrt(cvTsRandReal(rng)*msz) + 1);
1921     dsz.width = MIN(dsz.width,msz);
1922     dsz.height = MIN(dsz.width,msz);
1923     dsz.width = MAX(dsz.width,min_size);
1924     dsz.height = MAX(dsz.height,min_size);
1925     sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dsz;
1926     sizes[INPUT][1] = cvSize( 3, 2 );
1927 }
1928
1929
1930 void CV_GetQuadSubPixTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1931                 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1932 {
1933     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1934                                                                whole_sizes, are_images );
1935
1936     sizes[INPUT][1] = whole_sizes[INPUT][1] = cvSize(3,2);
1937     sizes[TEMP][0] = whole_sizes[TEMP][0] =
1938         sizes[TEMP][1] = whole_sizes[TEMP][1] = cvSize(0,0);
1939     types[INPUT][1] = CV_64FC1;
1940
1941     interpolation = CV_INTER_LINEAR;
1942 }
1943
1944
1945 void CV_GetQuadSubPixTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1946 {
1947     double coeffs[4];
1948     const CvFileNode* node = find_timing_param( "rotate_scale" );
1949     assert( node && CV_NODE_IS_SEQ(node->tag) );
1950     cvReadRawData( ts->get_file_storage(), node, coeffs, "4d" );
1951     
1952     sprintf( ptr, "fx=%.2f,fy=%.2f,angle=%.1fdeg,scale=%.1f,", coeffs[0], coeffs[1], coeffs[2], coeffs[3] );
1953     ptr += strlen(ptr);
1954     params_left -= 4;
1955
1956     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
1957 }
1958
1959
1960 void CV_GetQuadSubPixTest::run_func()
1961 {
1962     cvGetQuadrangleSubPix( test_array[INPUT][0],
1963         test_array[INPUT_OUTPUT][0], &test_mat[INPUT][1] );
1964 }
1965
1966
1967 double CV_GetQuadSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1968 {
1969     int in_depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1970     //int out_depth = CV_MAT_DEPTH(test_mat[INPUT_OUTPUT][0].type);
1971
1972     return in_depth >= CV_32F ? 1e-2 : 4;
1973 }
1974
1975
1976 int CV_GetQuadSubPixTest::prepare_test_case( int test_case_idx )
1977 {
1978     CvRNG* rng = ts->get_rng();
1979     int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
1980     const CvMat* src = &test_mat[INPUT][0];
1981     CvMat* mat = &test_mat[INPUT][1];
1982     CvPoint2D32f center;
1983     double scale, angle;
1984
1985     if( code <= 0 )
1986         return code;
1987
1988     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1989     {
1990         double a[6];
1991         CvMat A = cvMat( 2, 3, CV_64FC1, a );
1992
1993         center.x = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->cols);
1994         center.y = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->rows);
1995         angle = cvTsRandReal(rng)*360;
1996         scale = cvTsRandReal(rng)*0.2 + 0.9;
1997         
1998         // y = Ax + b -> x = A^-1(y - b) = A^-1*y - A^-1*b
1999         scale = 1./scale;
2000         angle = angle*(CV_PI/180.);
2001         a[0] = a[4] = cos(angle)*scale;
2002         a[1] = sin(angle)*scale;
2003         a[3] = -a[1];
2004         a[2] = center.x - a[0]*center.x - a[1]*center.y;
2005         a[5] = center.y - a[3]*center.x - a[4]*center.y;
2006         cvTsConvert( &A, mat );
2007     }
2008
2009     return code;
2010 }
2011
2012
2013 void CV_GetQuadSubPixTest::prepare_to_validation( int /*test_case_idx*/ )
2014 {
2015     CvMat* src0 = &test_mat[INPUT][0];
2016     CvMat* dst0 = &test_mat[REF_INPUT_OUTPUT][0];
2017     CvMat* src = src0, *dst = dst0;
2018     int ftype = CV_MAKETYPE(CV_32F,CV_MAT_CN(src0->type));
2019     double a[6], dx = (dst0->cols - 1)*0.5, dy = (dst0->rows - 1)*0.5;
2020     CvMat A = cvMat( 2, 3, CV_64F, a );
2021
2022     if( CV_MAT_DEPTH(src->type) != CV_32F )
2023     {
2024         src = cvCreateMat( src0->rows, src0->cols, ftype );
2025         cvTsConvert( src0, src );
2026     }
2027
2028     if( CV_MAT_DEPTH(dst->type) != CV_32F )
2029         dst = cvCreateMat( dst0->rows, dst0->cols, ftype );
2030
2031     cvTsConvert( &test_mat[INPUT][1], &A );
2032     a[2] -= a[0]*dx + a[1]*dy;
2033     a[5] -= a[3]*dx + a[4]*dy;
2034     cvTsGetQuadrangeSubPix( src, dst, a );
2035
2036     if( dst != dst0 )
2037     {
2038         cvTsConvert( dst, dst0 );
2039         cvReleaseMat( &dst );
2040     }
2041
2042     if( src != src0 )
2043         cvReleaseMat( &src );
2044 }
2045
2046
2047 CV_GetQuadSubPixTest warp_subpix_quad_test;
2048
2049 /* End of file. */