Update to 2.0.0 tree from current Fremantle build
[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 = 4;
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 }
315
316
317 void CV_ResizeTest::get_timing_test_array_types_and_sizes( int test_case_idx,
318                 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
319 {
320     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
321                                                                whole_sizes, are_images );
322     const char* method_str = cvReadString( find_timing_param( "method" ), "linear" );
323     double coeff = cvReadReal( find_timing_param( "coeff" ), 1. );
324     CvSize size = sizes[INPUT][0];
325
326     size.width = cvRound(size.width*coeff);
327     size.height = cvRound(size.height*coeff);
328     sizes[INPUT_OUTPUT][0] = whole_sizes[INPUT_OUTPUT][0] = size;
329
330     interpolation = strcmp( method_str, "nearest" ) == 0 ? CV_INTER_NN :
331                     strcmp( method_str, "linear" ) == 0 ? CV_INTER_LINEAR :
332                     strcmp( method_str, "cubic" ) == 0 ? CV_INTER_CUBIC : CV_INTER_AREA;
333 }
334
335
336 void CV_ResizeTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
337 {
338     sprintf( ptr, "coeff=%.3f,", cvReadReal( find_timing_param( "coeff" ), 1. ) );
339     ptr += strlen(ptr);
340     sprintf( ptr, "method=%s,", cvReadString( find_timing_param( "method" ), "linear" ) );
341     ptr += strlen(ptr);
342     params_left -= 2;
343
344     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
345 }
346
347
348 void CV_ResizeTest::run_func()
349 {
350     cvResize( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], interpolation );
351 }
352
353
354 double CV_ResizeTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
355 {
356     int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
357     return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 1e-1;
358 }
359
360
361 void CV_ResizeTest::prepare_to_validation( int /*test_case_idx*/ )
362 {
363     CvMat* src = &test_mat[INPUT][0];
364     CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0];
365     int i, j, k;
366     CvMat* x_idx = cvCreateMat( 1, dst->cols, CV_32SC1 );
367     CvMat* y_idx = cvCreateMat( 1, dst->rows, CV_32SC1 );
368     int* x_tab = x_idx->data.i;
369     int elem_size = CV_ELEM_SIZE(src->type); 
370     int drows = dst->rows, dcols = dst->cols;
371
372     if( interpolation == CV_INTER_NN )
373     {
374         for( j = 0; j < dcols; j++ )
375         {
376             int t = (j*src->cols*2 + MIN(src->cols,dcols) - 1)/(dcols*2);
377             t -= t >= src->cols;
378             x_idx->data.i[j] = t*elem_size;
379         }
380
381         for( j = 0; j < drows; j++ )
382         {
383             int t = (j*src->rows*2 + MIN(src->rows,drows) - 1)/(drows*2);
384             t -= t >= src->rows;
385             y_idx->data.i[j] = t;
386         }
387     }
388     else
389     {
390         double scale_x = (double)src->cols/dcols;
391         double scale_y = (double)src->rows/drows;
392         
393         for( j = 0; j < dcols; j++ )
394         {
395             double f = ((j+0.5)*scale_x - 0.5);
396             i = cvRound(f);
397             x_idx->data.i[j] = (i < 0 ? 0 : i >= src->cols ? src->cols - 1 : i)*elem_size;
398         }
399
400         for( j = 0; j < drows; j++ )
401         {
402             double f = ((j+0.5)*scale_y - 0.5);
403             i = cvRound(f);
404             y_idx->data.i[j] = i < 0 ? 0 : i >= src->rows ? src->rows - 1 : i;
405         }
406     }
407
408     for( i = 0; i < drows; i++ )
409     {
410         uchar* dptr = dst->data.ptr + dst->step*i;
411         const uchar* sptr0 = src->data.ptr + src->step*y_idx->data.i[i];
412         
413         for( j = 0; j < dcols; j++, dptr += elem_size )
414         {
415             const uchar* sptr = sptr0 + x_tab[j];
416             for( k = 0; k < elem_size; k++ )
417                 dptr[k] = sptr[k];
418         }
419     }
420
421     cvReleaseMat( &x_idx );
422     cvReleaseMat( &y_idx );
423 }
424
425 CV_ResizeTest warp_resize_test;
426
427
428 /////////////////////////
429
430 void cvTsRemap( const CvMat* src, CvMat* dst,
431                 const CvMat* mapx, const CvMat* mapy,
432                 CvMat* mask, int interpolation=CV_INTER_LINEAR )
433 {
434     int x, y, k;
435     int drows = dst->rows, dcols = dst->cols;
436     int srows = src->rows, scols = src->cols;
437     uchar* sptr0 = src->data.ptr;
438     int depth = CV_MAT_DEPTH(src->type), cn = CV_MAT_CN(src->type);
439     int elem_size = CV_ELEM_SIZE(src->type);
440     int step = src->step / CV_ELEM_SIZE(depth);
441     int delta;
442
443     if( interpolation != CV_INTER_CUBIC )
444     {
445         delta = 0;
446         scols -= 1; srows -= 1;
447     }
448     else
449     {
450         delta = 1;
451         scols = MAX(scols - 3, 0);
452         srows = MAX(srows - 3, 0);
453     }
454
455     int scols1 = MAX(scols - 2, 0);
456     int srows1 = MAX(srows - 2, 0);
457
458     if( mask )
459         cvTsZero(mask);
460
461     for( y = 0; y < drows; y++ )
462     {
463         uchar* dptr = dst->data.ptr + dst->step*y;
464         const float* mx = (const float*)(mapx->data.ptr + mapx->step*y);
465         const float* my = (const float*)(mapy->data.ptr + mapy->step*y);
466         uchar* m = mask ? mask->data.ptr + mask->step*y : 0;
467
468         for( x = 0; x < dcols; x++, dptr += elem_size )
469         {
470             float xs = mx[x];
471             float ys = my[x];
472             int ixs = cvFloor(xs);
473             int iys = cvFloor(ys);
474
475             if( (unsigned)(ixs - delta - 1) >= (unsigned)scols1 ||
476                 (unsigned)(iys - delta - 1) >= (unsigned)srows1 )
477             {
478                 if( m )
479                     m[x] = 1;
480                 if( (unsigned)(ixs - delta) >= (unsigned)scols ||
481                     (unsigned)(iys - delta) >= (unsigned)srows )
482                     continue;
483             }
484
485             xs -= ixs;
486             ys -= iys;
487             
488             switch( depth )
489             {
490             case CV_8U:
491                 {
492                 const uchar* sptr = sptr0 + iys*step + ixs*cn;
493                 for( k = 0; k < cn; k++ )
494                 {
495                     float v00 = sptr[k];
496                     float v01 = sptr[cn + k];
497                     float v10 = sptr[step + k];
498                     float v11 = sptr[step + cn + k];
499
500                     v00 = v00 + xs*(v01 - v00);
501                     v10 = v10 + xs*(v11 - v10);
502                     v00 = v00 + ys*(v10 - v00);
503                     dptr[k] = (uchar)cvRound(v00);
504                 }
505                 }
506                 break;
507             case CV_16U:
508                 {
509                 const ushort* sptr = (const ushort*)sptr0 + iys*step + ixs*cn;
510                 for( k = 0; k < cn; k++ )
511                 {
512                     float v00 = sptr[k];
513                     float v01 = sptr[cn + k];
514                     float v10 = sptr[step + k];
515                     float v11 = sptr[step + cn + k];
516
517                     v00 = v00 + xs*(v01 - v00);
518                     v10 = v10 + xs*(v11 - v10);
519                     v00 = v00 + ys*(v10 - v00);
520                     ((ushort*)dptr)[k] = (ushort)cvRound(v00);
521                 }
522                 }
523                 break;
524             case CV_32F:
525                 {
526                 const float* sptr = (const float*)sptr0 + iys*step + ixs*cn;
527                 for( k = 0; k < cn; k++ )
528                 {
529                     float v00 = sptr[k];
530                     float v01 = sptr[cn + k];
531                     float v10 = sptr[step + k];
532                     float v11 = sptr[step + cn + k];
533
534                     v00 = v00 + xs*(v01 - v00);
535                     v10 = v10 + xs*(v11 - v10);
536                     v00 = v00 + ys*(v10 - v00);
537                     ((float*)dptr)[k] = (float)v00;
538                 }
539                 }
540                 break;
541             default:
542                 assert(0);
543             }
544         }
545     }
546 }
547
548 /////////////////////////
549
550 class CV_WarpAffineTest : public CV_ImgWarpBaseTest
551 {
552 public:
553     CV_WarpAffineTest();
554
555 protected:
556     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
557     void run_func();
558     int prepare_test_case( int test_case_idx );
559     void prepare_to_validation( int /*test_case_idx*/ );
560     double get_success_error_level( int test_case_idx, int i, int j );
561
562     int write_default_params(CvFileStorage* fs);
563     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
564                                                 CvSize** whole_sizes, bool *are_images );
565     void print_timing_params( int test_case_idx, char* ptr, int params_left );
566 };
567
568
569 CV_WarpAffineTest::CV_WarpAffineTest()
570     : CV_ImgWarpBaseTest( "warp-affine", "cvWarpAffine", true )
571 {
572     //spatial_scale_zoom = spatial_scale_decimate;
573     test_array[TEMP].push(NULL);
574     test_array[TEMP].push(NULL);
575     
576     spatial_scale_decimate = spatial_scale_zoom;
577
578     default_timing_param_names = imgwarp_affine_param_names;
579 }
580
581
582 int CV_WarpAffineTest::write_default_params( CvFileStorage* fs )
583 {
584     int code = CV_ImgWarpBaseTest::write_default_params( fs );
585     if( code < 0 )
586         return code;
587     
588     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
589     {
590         int i;
591         start_write_param( fs );
592
593         cvStartWriteStruct( fs, "rotate_scale", CV_NODE_SEQ+CV_NODE_FLOW );
594         for( i = 0; imgwarp_affine_rotate_scale[i][0] >= 0; i++ )
595         {
596             cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW );
597             cvWriteRawData( fs, imgwarp_affine_rotate_scale[i], 4, "d" );
598             cvEndWriteStruct(fs);
599         }
600         cvEndWriteStruct(fs);
601     }
602
603     return code;
604 }
605
606
607 void CV_WarpAffineTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
608 {
609     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
610     CvSize sz = sizes[INPUT][0];
611     // run for the second time to get output of a different size
612     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
613     sizes[INPUT][0] = sz;
614     sizes[INPUT][1] = cvSize( 3, 2 );
615     sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT_OUTPUT][0];
616     types[TEMP][0] = types[TEMP][1] = CV_32FC1;
617 }
618
619
620 void CV_WarpAffineTest::get_timing_test_array_types_and_sizes( int test_case_idx,
621                 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
622 {
623     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
624                                                                whole_sizes, are_images );
625
626     sizes[INPUT][1] = whole_sizes[INPUT][1] = cvSize(3,2);
627     sizes[TEMP][0] = whole_sizes[TEMP][0] =
628         sizes[TEMP][1] = whole_sizes[TEMP][1] = cvSize(0,0);
629     types[INPUT][1] = CV_64FC1;
630
631     interpolation = CV_INTER_LINEAR;
632 }
633
634
635 void CV_WarpAffineTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
636 {
637     double coeffs[4];
638     const CvFileNode* node = find_timing_param( "rotate_scale" );
639     assert( node && CV_NODE_IS_SEQ(node->tag) );
640     cvReadRawData( ts->get_file_storage(), node, coeffs, "4d" );
641     
642     sprintf( ptr, "fx=%.2f,fy=%.2f,angle=%.1fdeg,scale=%.1f,", coeffs[0], coeffs[1], coeffs[2], coeffs[3] );
643     ptr += strlen(ptr);
644     params_left -= 4;
645
646     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
647 }
648
649
650 void CV_WarpAffineTest::run_func()
651 {
652     cvWarpAffine( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],
653                   &test_mat[INPUT][1], interpolation );
654 }
655
656
657 double CV_WarpAffineTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
658 {
659     int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
660     return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
661 }
662
663
664 int CV_WarpAffineTest::prepare_test_case( int test_case_idx )
665 {
666     CvRNG* rng = ts->get_rng();
667     int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
668     const CvMat* src = &test_mat[INPUT][0];
669     const CvMat* dst = &test_mat[INPUT_OUTPUT][0]; 
670     CvMat* mat = &test_mat[INPUT][1];
671     CvPoint2D32f center;
672     double scale, angle;
673
674     if( code <= 0 )
675         return code;
676
677     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
678     {
679         double buf[6];
680         CvMat tmp = cvMat( 2, 3, mat->type, buf );
681
682         center.x = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->cols);
683         center.y = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->rows);
684         angle = cvTsRandReal(rng)*360;
685         scale = ((double)dst->rows/src->rows + (double)dst->cols/src->cols)*0.5;
686         cv2DRotationMatrix( center, angle, scale, mat );
687         cvRandArr( rng, &tmp, CV_RAND_NORMAL, cvScalarAll(1.), cvScalarAll(0.01) );
688         cvMaxS( &tmp, 0.9, &tmp );
689         cvMinS( &tmp, 1.1, &tmp );
690         cvMul( &tmp, mat, mat, 1. );
691     }
692     else
693     {
694         double coeffs[4];
695         const CvFileNode* node = find_timing_param( "rotate_scale" );
696
697         assert( node && CV_NODE_IS_SEQ(node->tag) );
698         cvReadRawData( ts->get_file_storage(), node, coeffs, "4d" );
699
700         center.x = (float)(coeffs[0]*src->cols);
701         center.y = (float)(coeffs[1]*src->rows);
702         angle = coeffs[2];
703         scale = coeffs[3];
704         cv2DRotationMatrix( center, angle, scale, mat );
705     }
706
707     return code;
708 }
709
710
711 void CV_WarpAffineTest::prepare_to_validation( int /*test_case_idx*/ )
712 {
713     CvMat* src = &test_mat[INPUT][0];
714     CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0];
715     CvMat* dst0 = &test_mat[INPUT_OUTPUT][0];
716     CvMat* mapx = &test_mat[TEMP][0];
717     CvMat* mapy = &test_mat[TEMP][1];
718     int x, y;
719     double m[6], tm[6];
720     CvMat srcAb = cvMat(2, 3, CV_64FC1, tm ), A, b, invA, invAb, dstAb = cvMat( 2, 3, CV_64FC1, m );
721
722     //cvInvert( &tM, &M, CV_LU );
723     // [R|t] -> [R^-1 | -(R^-1)*t]
724     cvTsConvert( &test_mat[INPUT][1], &srcAb );
725     cvGetCols( &srcAb, &A, 0, 2 );
726     cvGetCol( &srcAb, &b, 2 );
727     cvGetCols( &dstAb, &invA, 0, 2 );
728     cvGetCol( &dstAb, &invAb, 2 );
729     cvInvert( &A, &invA, CV_SVD );
730     cvGEMM( &invA, &b, -1, 0, 0, &invAb );
731
732     for( y = 0; y < dst->rows; y++ )
733     {
734         float* mx = (float*)(mapx->data.ptr + y*mapx->step);
735         float* my = (float*)(mapy->data.ptr + y*mapy->step);
736
737         for( x = 0; x < dst->cols; x++ )
738         {
739             mx[x] = (float)(x*m[0] + y*m[1] + m[2]);
740             my[x] = (float)(x*m[3] + y*m[4] + m[5]);
741         }
742     }
743
744     CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U );
745     cvTsRemap( src, dst, mapx, mapy, mask );
746     cvTsZero( dst, mask );
747     cvTsZero( dst0, mask );
748     cvReleaseMat( &mask );
749 }
750
751
752 CV_WarpAffineTest warp_affine_test;
753
754
755
756 /////////////////////////
757
758 class CV_WarpPerspectiveTest : public CV_ImgWarpBaseTest
759 {
760 public:
761     CV_WarpPerspectiveTest();
762
763 protected:
764     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
765     void run_func();
766     int prepare_test_case( int test_case_idx );
767     void prepare_to_validation( int /*test_case_idx*/ );
768     double get_success_error_level( int test_case_idx, int i, int j );
769
770     int write_default_params(CvFileStorage* fs);
771     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
772                                                 CvSize** whole_sizes, bool *are_images );
773     void print_timing_params( int test_case_idx, char* ptr, int params_left );
774 };
775
776
777 CV_WarpPerspectiveTest::CV_WarpPerspectiveTest()
778     : CV_ImgWarpBaseTest( "warp-perspective", "cvWarpPerspective", true )
779 {
780     //spatial_scale_zoom = spatial_scale_decimate;
781     test_array[TEMP].push(NULL);
782     test_array[TEMP].push(NULL);
783
784     spatial_scale_decimate = spatial_scale_zoom;
785     default_timing_param_names = imgwarp_perspective_param_names;
786 }
787
788
789 int CV_WarpPerspectiveTest::write_default_params( CvFileStorage* fs )
790 {
791     int code = CV_ImgWarpBaseTest::write_default_params( fs );
792     if( code < 0 )
793         return code;
794     
795     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
796     {
797         int i;
798         start_write_param( fs );
799
800         cvStartWriteStruct( fs, "shift_vtx", CV_NODE_SEQ+CV_NODE_FLOW );
801         for( i = 0; imgwarp_perspective_shift_vtx[i][0] >= 0; i++ )
802         {
803             cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW );
804             cvWriteRawData( fs, imgwarp_perspective_shift_vtx[i], 8, "d" );
805             cvEndWriteStruct(fs);
806         }
807         cvEndWriteStruct(fs);
808     }
809
810     return code;
811 }
812
813
814 void CV_WarpPerspectiveTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
815 {
816     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
817     CvSize sz = sizes[INPUT][0];
818     // run for the second time to get output of a different size
819     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
820     sizes[INPUT][0] = sz;
821     sizes[INPUT][1] = cvSize( 3, 3 );
822
823     sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT_OUTPUT][0];
824     types[TEMP][0] = types[TEMP][1] = CV_32FC1;
825 }
826
827
828 void CV_WarpPerspectiveTest::get_timing_test_array_types_and_sizes( int test_case_idx,
829                 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
830 {
831     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
832                                                                whole_sizes, are_images );
833
834     sizes[INPUT][1] = whole_sizes[INPUT][1] = cvSize(3,3);
835     sizes[TEMP][0] = whole_sizes[TEMP][0] =
836         sizes[TEMP][1] = whole_sizes[TEMP][1] = cvSize(0,0);
837     types[INPUT][1] = CV_64FC1;
838
839     interpolation = CV_INTER_LINEAR;
840 }
841
842
843 void CV_WarpPerspectiveTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
844 {
845     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
846 }
847
848
849 void CV_WarpPerspectiveTest::run_func()
850 {
851     cvWarpPerspective( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],
852                        &test_mat[INPUT][1], interpolation );
853 }
854
855
856 double CV_WarpPerspectiveTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
857 {
858     int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
859     return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
860 }
861
862
863 int CV_WarpPerspectiveTest::prepare_test_case( int test_case_idx )
864 {
865     CvRNG* rng = ts->get_rng();
866     int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
867     const CvMat* src = &test_mat[INPUT][0];
868     const CvMat* dst = &test_mat[INPUT_OUTPUT][0]; 
869     CvMat* mat = &test_mat[INPUT][1];
870     CvPoint2D32f s[4], d[4];
871     int i;
872
873     if( code <= 0 )
874         return code;
875
876     s[0] = cvPoint2D32f(0,0);
877     d[0] = cvPoint2D32f(0,0);
878     s[1] = cvPoint2D32f(src->cols-1,0);
879     d[1] = cvPoint2D32f(dst->cols-1,0);
880     s[2] = cvPoint2D32f(src->cols-1,src->rows-1);
881     d[2] = cvPoint2D32f(dst->cols-1,dst->rows-1);
882     s[3] = cvPoint2D32f(0,src->rows-1);
883     d[3] = cvPoint2D32f(0,dst->rows-1);
884
885     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
886     {
887         float buf[16];
888         CvMat tmp = cvMat( 1, 16, CV_32FC1, buf );
889
890         cvRandArr( rng, &tmp, CV_RAND_NORMAL, cvScalarAll(0.), cvScalarAll(0.1) );
891
892         for( i = 0; i < 4; i++ )
893         {
894             s[i].x += buf[i*4]*src->cols/2;
895             s[i].y += buf[i*4+1]*src->rows/2;
896             d[i].x += buf[i*4+2]*dst->cols/2;
897             d[i].y += buf[i*4+3]*dst->rows/2;
898         }
899     }
900     else
901     {
902         double coeffs[8];
903         const CvFileNode* node = find_timing_param( "shift_vtx" );
904
905         assert( node && CV_NODE_IS_SEQ(node->tag) );
906         cvReadRawData( ts->get_file_storage(), node, coeffs, "8d" );
907
908         for( i = 0; i < 4; i++ )
909         {
910             d[i].x += (float)(coeffs[i*2]*src->cols*(i == 0 || i == 3 ? 1 : -1));
911             d[i].y += (float)(coeffs[i*2+1]*src->rows*(i == 0 || i == 1 ? 1 : -1));
912         }
913     }
914
915     cvWarpPerspectiveQMatrix( s, d, mat );
916     return code;
917 }
918
919
920 void CV_WarpPerspectiveTest::prepare_to_validation( int /*test_case_idx*/ )
921 {
922     CvMat* src = &test_mat[INPUT][0];
923     CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0];
924     CvMat* dst0 = &test_mat[INPUT_OUTPUT][0];
925     CvMat* mapx = &test_mat[TEMP][0];
926     CvMat* mapy = &test_mat[TEMP][1];
927     int x, y;
928     double m[9], tm[9];
929     CvMat srcM = cvMat(3, 3, CV_64FC1, tm ), dstM = cvMat( 3, 3, CV_64FC1, m );
930
931     //cvInvert( &tM, &M, CV_LU );
932     // [R|t] -> [R^-1 | -(R^-1)*t]
933     cvTsConvert( &test_mat[INPUT][1], &srcM );
934     cvInvert( &srcM, &dstM, CV_SVD );
935
936     for( y = 0; y < dst->rows; y++ )
937     {
938         float* mx = (float*)(mapx->data.ptr + y*mapx->step);
939         float* my = (float*)(mapy->data.ptr + y*mapy->step);
940
941         for( x = 0; x < dst->cols; x++ )
942         {
943             double xs = x*m[0] + y*m[1] + m[2];
944             double ys = x*m[3] + y*m[4] + m[5];
945             double ds = x*m[6] + y*m[7] + m[8];
946             
947             ds = ds ? 1./ds : 0;
948             xs *= ds;
949             ys *= ds;
950             
951             mx[x] = (float)xs;
952             my[x] = (float)ys;
953         }
954     }
955
956     CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U );
957     cvTsRemap( src, dst, mapx, mapy, mask );
958     cvTsZero( dst, mask );
959     cvTsZero( dst0, mask );
960     cvReleaseMat( &mask );
961 }
962
963
964 CV_WarpPerspectiveTest warp_perspective_test;
965
966
967
968 /////////////////////////
969
970 void cvTsInitUndistortMap( const CvMat* _a0, const CvMat* _k0, CvMat* mapx, CvMat* mapy )
971 {
972     int u, v;
973     double a[9], k[5]={0,0,0,0,0};
974     CvMat _a = cvMat(3, 3, CV_64F, a);
975     CvMat _k = cvMat(_k0->rows,_k0->cols,
976         CV_MAKETYPE(CV_64F,CV_MAT_CN(_k0->type)),k);
977     double fx, fy, cx, cy, ifx, ify, cxn, cyn;
978     
979     cvTsConvert( _a0, &_a );
980     cvTsConvert( _k0, &_k );
981     fx = a[0]; fy = a[4]; cx = a[2]; cy = a[5];
982     ifx = 1./fx; ify = 1./fy;
983     cxn = cx;//(mapy->cols - 1)*0.5;
984     cyn = cy;//(mapy->rows - 1)*0.5;
985
986     for( v = 0; v < mapy->rows; v++ )
987     {
988         float* mx = (float*)(mapx->data.ptr + v*mapx->step);
989         float* my = (float*)(mapy->data.ptr + v*mapy->step);
990         
991         for( u = 0; u < mapy->cols; u++ )
992         {
993             double x = (u - cxn)*ifx;
994             double y = (v - cyn)*ify;
995             double x2 = x*x, y2 = y*y;
996             double r2 = x2 + y2;
997             double cdist = 1 + (k[0] + (k[1] + k[4]*r2)*r2)*r2;
998             double x1 = x*cdist + k[2]*2*x*y + k[3]*(r2 + 2*x2);
999             double y1 = y*cdist + k[3]*2*x*y + k[2]*(r2 + 2*y2);
1000             mx[u] = (float)(x1*fx + cx);
1001             my[u] = (float)(y1*fy + cy);
1002         }
1003     }
1004 }
1005
1006
1007 static double remap_undistort_params[] = { 0.5, 0.5, 0.5, 0.5, 0.01, -0.01, 0.001, -0.001 };
1008
1009 class CV_RemapTest : public CV_ImgWarpBaseTest
1010 {
1011 public:
1012     CV_RemapTest();
1013
1014 protected:
1015     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1016     void run_func();
1017     int prepare_test_case( int test_case_idx );
1018     void prepare_to_validation( int /*test_case_idx*/ );
1019     double get_success_error_level( int test_case_idx, int i, int j );
1020     void fill_array( int test_case_idx, int i, int j, CvMat* arr );
1021
1022     int write_default_params(CvFileStorage* fs);
1023     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1024                                                 CvSize** whole_sizes, bool *are_images );
1025     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1026 };
1027
1028
1029 CV_RemapTest::CV_RemapTest()
1030     : CV_ImgWarpBaseTest( "warp-remap", "cvRemap", false )
1031 {
1032     //spatial_scale_zoom = spatial_scale_decimate;
1033     test_array[INPUT].push(NULL);
1034     test_array[INPUT].push(NULL);
1035
1036     spatial_scale_decimate = spatial_scale_zoom;
1037     //default_timing_param_names = imgwarp_perspective_param_names;
1038     support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1039     default_timing_param_names = 0;
1040 }
1041
1042
1043 int CV_RemapTest::write_default_params( CvFileStorage* fs )
1044 {
1045     int code = CV_ImgWarpBaseTest::write_default_params( fs );
1046     if( code < 0 )
1047         return code;
1048     
1049     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
1050     {
1051         int i;
1052         start_write_param( fs );
1053
1054         cvStartWriteStruct( fs, "params", CV_NODE_SEQ+CV_NODE_FLOW );
1055         for( i = 0; i < 8; i++ )
1056             cvWriteReal( fs, 0, remap_undistort_params[i] );
1057         cvEndWriteStruct(fs);
1058     }
1059
1060     return code;
1061 }
1062
1063
1064 void CV_RemapTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1065 {
1066     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1067     types[INPUT][1] = types[INPUT][2] = CV_32FC1;
1068     interpolation = CV_INTER_LINEAR;
1069 }
1070
1071
1072 void CV_RemapTest::fill_array( int test_case_idx, int i, int j, CvMat* arr )
1073 {
1074     if( i != INPUT )
1075         CV_ImgWarpBaseTestImpl::fill_array( test_case_idx, i, j, arr );
1076 }
1077
1078 void CV_RemapTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1079         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1080 {
1081     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1082                                                                whole_sizes, are_images );
1083     types[INPUT][1] = types[INPUT][2] = CV_32FC1;
1084     interpolation = CV_INTER_LINEAR;
1085 }
1086
1087
1088 void CV_RemapTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1089 {
1090     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
1091 }
1092
1093
1094 void CV_RemapTest::run_func()
1095 {
1096     cvRemap( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],
1097              test_array[INPUT][1], test_array[INPUT][2], interpolation );
1098 }
1099
1100
1101 double CV_RemapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1102 {
1103     int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1104     return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
1105 }
1106
1107
1108 int CV_RemapTest::prepare_test_case( int test_case_idx )
1109 {
1110     CvRNG* rng = ts->get_rng();
1111     int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
1112     const CvMat* src = &test_mat[INPUT][0];
1113     double a[9] = {0,0,0,0,0,0,0,0,1}, k[4];
1114     CvMat _a = cvMat( 3, 3, CV_64F, a );
1115     CvMat _k = cvMat( 4, 1, CV_64F, k );
1116     double sz = MAX(src->rows, src->cols);
1117
1118     if( code <= 0 )
1119         return code;
1120
1121     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1122     {
1123         double aspect_ratio = cvTsRandReal(rng)*0.6 + 0.7;
1124         a[2] = (src->cols - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1125         a[5] = (src->rows - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1126         a[0] = sz/(0.9 - cvTsRandReal(rng)*0.6);
1127         a[4] = aspect_ratio*a[0];
1128         k[0] = cvTsRandReal(rng)*0.06 - 0.03;
1129         k[1] = cvTsRandReal(rng)*0.06 - 0.03;
1130         if( k[0]*k[1] > 0 )
1131             k[1] = -k[1];
1132         k[2] = cvTsRandReal(rng)*0.004 - 0.002;
1133         k[3] = cvTsRandReal(rng)*0.004 - 0.002;
1134     }
1135     else
1136     {
1137         int i;
1138         a[2] = (src->cols - 1)*remap_undistort_params[0];
1139         a[5] = (src->rows - 1)*remap_undistort_params[1];
1140         a[0] = sz/remap_undistort_params[2];
1141         a[4] = sz/remap_undistort_params[3];
1142         for( i = 0; i < 4; i++ )
1143             k[i] = remap_undistort_params[i+4];
1144     }
1145
1146     cvTsInitUndistortMap( &_a, &_k, &test_mat[INPUT][1], &test_mat[INPUT][2] );
1147     return code;
1148 }
1149
1150
1151 void CV_RemapTest::prepare_to_validation( int /*test_case_idx*/ )
1152 {
1153     CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0];
1154     CvMat* dst0 = &test_mat[INPUT_OUTPUT][0];
1155     CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U );
1156     cvTsRemap( &test_mat[INPUT][0], dst,
1157                &test_mat[INPUT][1], &test_mat[INPUT][2],
1158                mask, interpolation );
1159     cvTsZero( dst, mask );
1160     cvTsZero( dst0, mask );
1161     cvReleaseMat( &mask );
1162 }
1163
1164
1165 CV_RemapTest remap_test;
1166
1167
1168 ////////////////////////////// undistort /////////////////////////////////
1169
1170 class CV_UndistortTest : public CV_ImgWarpBaseTest
1171 {
1172 public:
1173     CV_UndistortTest();
1174
1175 protected:
1176     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1177     void run_func();
1178     int prepare_test_case( int test_case_idx );
1179     void prepare_to_validation( int /*test_case_idx*/ );
1180     double get_success_error_level( int test_case_idx, int i, int j );
1181     void fill_array( int test_case_idx, int i, int j, CvMat* arr );
1182
1183     int write_default_params(CvFileStorage* fs);
1184     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1185                                                 CvSize** whole_sizes, bool *are_images );
1186     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1187 };
1188
1189
1190 CV_UndistortTest::CV_UndistortTest()
1191     : CV_ImgWarpBaseTest( "warp-undistort", "cvUndistort2", false )
1192 {
1193     //spatial_scale_zoom = spatial_scale_decimate;
1194     test_array[INPUT].push(NULL);
1195     test_array[INPUT].push(NULL);
1196
1197     spatial_scale_decimate = spatial_scale_zoom;
1198     //default_timing_param_names = imgwarp_perspective_param_names;
1199     support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1200     default_timing_param_names = 0;
1201 }
1202
1203
1204 int CV_UndistortTest::write_default_params( CvFileStorage* fs )
1205 {
1206     int code = CV_ImgWarpBaseTest::write_default_params( fs );
1207     if( code < 0 )
1208         return code;
1209     
1210     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
1211     {
1212         int i;
1213         start_write_param( fs );
1214
1215         cvStartWriteStruct( fs, "params", CV_NODE_SEQ+CV_NODE_FLOW );
1216         for( i = 0; i < 8; i++ )
1217             cvWriteReal( fs, 0, remap_undistort_params[i] );
1218         cvEndWriteStruct(fs);
1219     }
1220
1221     return code;
1222 }
1223
1224
1225 void CV_UndistortTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1226 {
1227     CvRNG* rng = ts->get_rng();
1228     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1229     int type = types[INPUT][0];
1230     type = CV_MAKETYPE( CV_8U, CV_MAT_CN(type) ); 
1231     types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = type;
1232     types[INPUT][1] = cvTsRandInt(rng)%2 ? CV_64F : CV_32F;
1233     types[INPUT][2] = cvTsRandInt(rng)%2 ? CV_64F : CV_32F;
1234     sizes[INPUT][1] = cvSize(3,3);
1235     sizes[INPUT][2] = cvTsRandInt(rng)%2 ? cvSize(4,1) : cvSize(1,4);
1236     interpolation = CV_INTER_LINEAR;
1237 }
1238
1239
1240 void CV_UndistortTest::fill_array( int test_case_idx, int i, int j, CvMat* arr )
1241 {
1242     if( i != INPUT )
1243         CV_ImgWarpBaseTestImpl::fill_array( test_case_idx, i, j, arr );
1244 }
1245
1246 void CV_UndistortTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1247         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1248 {
1249     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1250                                                                whole_sizes, are_images );
1251     types[INPUT][1] = types[INPUT][2] = CV_32FC1;
1252     interpolation = CV_INTER_LINEAR;
1253 }
1254
1255
1256 void CV_UndistortTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1257 {
1258     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
1259 }
1260
1261
1262 void CV_UndistortTest::run_func()
1263 {
1264     cvUndistort2( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],
1265                   &test_mat[INPUT][1], &test_mat[INPUT][2] );
1266 }
1267
1268
1269 double CV_UndistortTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1270 {
1271     int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1272     return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
1273 }
1274
1275
1276 int CV_UndistortTest::prepare_test_case( int test_case_idx )
1277 {
1278     CvRNG* rng = ts->get_rng();
1279     int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
1280     const CvMat* src = &test_mat[INPUT][0];
1281     double k[4], a[9] = {0,0,0,0,0,0,0,0,1};
1282     double sz = MAX(src->rows, src->cols);
1283     CvMat* _a0 = &test_mat[INPUT][1], *_k0 = &test_mat[INPUT][2];
1284     CvMat _a = cvMat(3,3,CV_64F,a);
1285     CvMat _k = cvMat(_k0->rows,_k0->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(_k0->type)),k);
1286
1287     if( code <= 0 )
1288         return code;
1289
1290     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1291     {
1292         double aspect_ratio = cvTsRandReal(rng)*0.6 + 0.7;
1293         a[2] = (src->cols - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1294         a[5] = (src->rows - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1295         a[0] = sz/(0.9 - cvTsRandReal(rng)*0.6);
1296         a[4] = aspect_ratio*a[0];
1297         k[0] = cvTsRandReal(rng)*0.06 - 0.03;
1298         k[1] = cvTsRandReal(rng)*0.06 - 0.03;
1299         if( k[0]*k[1] > 0 )
1300             k[1] = -k[1];
1301         if( cvTsRandInt(rng)%4 != 0 )
1302         {
1303             k[2] = cvTsRandReal(rng)*0.004 - 0.002;
1304             k[3] = cvTsRandReal(rng)*0.004 - 0.002;
1305         }
1306         else
1307             k[2] = k[3] = 0;
1308     }
1309     else
1310     {
1311         int i;
1312         a[2] = (src->cols - 1)*remap_undistort_params[0];
1313         a[5] = (src->rows - 1)*remap_undistort_params[1];
1314         a[0] = sz/remap_undistort_params[2];
1315         a[4] = sz/remap_undistort_params[3];
1316         for( i = 0; i < 4; i++ )
1317             k[i] = remap_undistort_params[i+4];
1318     }
1319
1320     cvTsConvert( &_a, _a0 );
1321     cvTsConvert( &_k, _k0 );
1322
1323     return code;
1324 }
1325
1326
1327 void CV_UndistortTest::prepare_to_validation( int /*test_case_idx*/ )
1328 {
1329     CvMat* src = &test_mat[INPUT][0];
1330     CvMat* dst = &test_mat[REF_INPUT_OUTPUT][0];
1331     CvMat* dst0 = &test_mat[INPUT_OUTPUT][0];
1332     CvMat* mapx = cvCreateMat( dst->rows, dst->cols, CV_32FC1 );
1333     CvMat* mapy = cvCreateMat( dst->rows, dst->cols, CV_32FC1 );
1334     cvTsInitUndistortMap( &test_mat[INPUT][1], &test_mat[INPUT][2],
1335                           mapx, mapy );
1336     CvMat* mask = cvCreateMat( dst->rows, dst->cols, CV_8U );
1337     cvTsRemap( src, dst, mapx, mapy, mask, interpolation );
1338     cvTsZero( dst, mask );
1339     cvTsZero( dst0, mask );
1340
1341     cvReleaseMat( &mapx );
1342     cvReleaseMat( &mapy );
1343     cvReleaseMat( &mask );
1344 }
1345
1346
1347 CV_UndistortTest undistort_test;
1348
1349
1350
1351 class CV_UndistortMapTest : public CvArrTest
1352 {
1353 public:
1354     CV_UndistortMapTest();
1355
1356 protected:
1357     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1358     void run_func();
1359     int prepare_test_case( int test_case_idx );
1360     void prepare_to_validation( int /*test_case_idx*/ );
1361     double get_success_error_level( int test_case_idx, int i, int j );
1362     void fill_array( int test_case_idx, int i, int j, CvMat* arr );
1363
1364     int write_default_params(CvFileStorage* fs);
1365     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1366                                                 CvSize** whole_sizes, bool *are_images );
1367     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1368 };
1369
1370
1371 CV_UndistortMapTest::CV_UndistortMapTest()
1372     : CvArrTest( "warp-undistort-map", "cvInitUndistortMap", "" )
1373 {
1374     test_array[INPUT].push(NULL);
1375     test_array[INPUT].push(NULL);
1376     test_array[OUTPUT].push(NULL);
1377     test_array[OUTPUT].push(NULL);
1378     test_array[REF_OUTPUT].push(NULL);
1379     test_array[REF_OUTPUT].push(NULL);
1380
1381     element_wise_relative_error = false;
1382
1383     support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1384     default_timing_param_names = 0;
1385 }
1386
1387
1388 int CV_UndistortMapTest::write_default_params( CvFileStorage* fs )
1389 {
1390     int code = CvArrTest::write_default_params( fs );
1391     if( code < 0 )
1392         return code;
1393     
1394     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
1395     {
1396         int i;
1397         start_write_param( fs );
1398
1399         cvStartWriteStruct( fs, "params", CV_NODE_SEQ+CV_NODE_FLOW );
1400         for( i = 0; i < 8; i++ )
1401             cvWriteReal( fs, 0, remap_undistort_params[i] );
1402         cvEndWriteStruct(fs);
1403     }
1404
1405     return code;
1406 }
1407
1408
1409 void CV_UndistortMapTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1410 {
1411     CvRNG* rng = ts->get_rng();
1412     CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1413     int depth = cvTsRandInt(rng)%2 ? CV_64F : CV_32F;
1414     CvSize sz = sizes[OUTPUT][0];
1415     types[INPUT][0] = types[INPUT][1] = depth;
1416     types[OUTPUT][0] = types[OUTPUT][1] = 
1417         types[REF_OUTPUT][0] = types[REF_OUTPUT][1] = CV_32F;
1418     sizes[INPUT][0] = cvSize(3,3);
1419     sizes[INPUT][1] = cvTsRandInt(rng)%2 ? cvSize(4,1) : cvSize(1,4);
1420
1421     sz.width = MAX(sz.width,16);
1422     sz.height = MAX(sz.height,16);
1423     sizes[OUTPUT][0] = sizes[OUTPUT][1] =
1424         sizes[REF_OUTPUT][0] = sizes[REF_OUTPUT][1] = sz;
1425 }
1426
1427
1428 void CV_UndistortMapTest::fill_array( int test_case_idx, int i, int j, CvMat* arr )
1429 {
1430     if( i != INPUT )
1431         CvArrTest::fill_array( test_case_idx, i, j, arr );
1432 }
1433
1434 void CV_UndistortMapTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1435         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1436 {
1437     CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1438                                                       whole_sizes, are_images );
1439 }
1440
1441
1442 void CV_UndistortMapTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1443 {
1444     CvArrTest::print_timing_params( test_case_idx, ptr, params_left );
1445 }
1446
1447
1448 void CV_UndistortMapTest::run_func()
1449 {
1450     cvInitUndistortMap( &test_mat[INPUT][0], &test_mat[INPUT][1],
1451                         test_array[OUTPUT][0], test_array[OUTPUT][1] );
1452 }
1453
1454
1455 double CV_UndistortMapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1456 {
1457     return 1e-3;
1458 }
1459
1460
1461 int CV_UndistortMapTest::prepare_test_case( int test_case_idx )
1462 {
1463     CvRNG* rng = ts->get_rng();
1464     int code = CvArrTest::prepare_test_case( test_case_idx );
1465     const CvMat* mapx = &test_mat[OUTPUT][0];
1466     double k[4], a[9] = {0,0,0,0,0,0,0,0,1};
1467     double sz = MAX(mapx->rows, mapx->cols);
1468     CvMat* _a0 = &test_mat[INPUT][0], *_k0 = &test_mat[INPUT][1];
1469     CvMat _a = cvMat(3,3,CV_64F,a);
1470     CvMat _k = cvMat(_k0->rows,_k0->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(_k0->type)),k);
1471
1472     if( code <= 0 )
1473         return code;
1474
1475     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1476     {
1477         double aspect_ratio = cvTsRandReal(rng)*0.6 + 0.7;
1478         a[2] = (mapx->cols - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1479         a[5] = (mapx->rows - 1)*0.5 + cvTsRandReal(rng)*10 - 5;
1480         a[0] = sz/(0.9 - cvTsRandReal(rng)*0.6);
1481         a[4] = aspect_ratio*a[0];
1482         k[0] = cvTsRandReal(rng)*0.06 - 0.03;
1483         k[1] = cvTsRandReal(rng)*0.06 - 0.03;
1484         if( k[0]*k[1] > 0 )
1485             k[1] = -k[1];
1486         k[2] = cvTsRandReal(rng)*0.004 - 0.002;
1487         k[3] = cvTsRandReal(rng)*0.004 - 0.002;
1488     }
1489     else
1490     {
1491         int i;
1492         a[2] = (mapx->cols - 1)*remap_undistort_params[0];
1493         a[5] = (mapx->rows - 1)*remap_undistort_params[1];
1494         a[0] = sz/remap_undistort_params[2];
1495         a[4] = sz/remap_undistort_params[3];
1496         for( i = 0; i < 4; i++ )
1497             k[i] = remap_undistort_params[i+4];
1498     }
1499
1500     cvTsConvert( &_a, _a0 );
1501     cvTsConvert( &_k, _k0 );
1502
1503     return code;
1504 }
1505
1506
1507 void CV_UndistortMapTest::prepare_to_validation( int /*test_case_idx*/ )
1508 {
1509     cvTsInitUndistortMap( &test_mat[INPUT][0], &test_mat[INPUT][1],
1510                           &test_mat[REF_OUTPUT][0], &test_mat[REF_OUTPUT][1] );
1511 }
1512
1513
1514 CV_UndistortMapTest undistortmap_test;
1515
1516
1517
1518 ////////////////////////////// GetRectSubPix /////////////////////////////////
1519
1520 static const CvSize rectsubpix_sizes[] = {{11, 11}, {21,21}, {41,41},{-1,-1}};
1521
1522 static void
1523 cvTsGetQuadrangeSubPix( const CvMat* src, CvMat* dst, double* a )
1524 {
1525     int y, x, k, cn;
1526     int sstep = src->step / sizeof(float);
1527     int scols = src->cols, srows = src->rows;
1528     
1529     assert( CV_MAT_DEPTH(src->type) == CV_32F &&
1530             CV_ARE_TYPES_EQ(src, dst));
1531
1532     cn = CV_MAT_CN(dst->type);
1533
1534     for( y = 0; y < dst->rows; y++ )
1535         for( x = 0; x < dst->cols; x++ )
1536         {
1537             float* d = (float*)(dst->data.ptr + y*dst->step) + x*cn;
1538             float sx = (float)(a[0]*x + a[1]*y + a[2]);
1539             float sy = (float)(a[3]*x + a[4]*y + a[5]);
1540             int ix = cvFloor(sx), iy = cvFloor(sy);
1541             int dx = cn, dy = sstep;
1542             const float* s;
1543             sx -= ix; sy -= iy;
1544
1545             if( (unsigned)ix >= (unsigned)(scols-1) )
1546                 ix = ix < 0 ? 0 : scols - 1, sx = 0, dx = 0;
1547             if( (unsigned)iy >= (unsigned)(srows-1) )
1548                 iy = iy < 0 ? 0 : srows - 1, sy = 0, dy = 0;
1549
1550             s = src->data.fl + sstep*iy + ix*cn;
1551             for( k = 0; k < cn; k++, s++ )
1552             {
1553                 float t0 = s[0] + sx*(s[dx] - s[0]);
1554                 float t1 = s[dy] + sx*(s[dy + dx] - s[dy]);
1555                 d[k] = t0 + sy*(t1 - t0);
1556             }
1557         }
1558 }
1559
1560
1561 class CV_GetRectSubPixTest : public CV_ImgWarpBaseTest
1562 {
1563 public:
1564     CV_GetRectSubPixTest();
1565
1566 protected:
1567     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1568     void run_func();
1569     int prepare_test_case( int test_case_idx );
1570     void prepare_to_validation( int /*test_case_idx*/ );
1571     double get_success_error_level( int test_case_idx, int i, int j );
1572     void fill_array( int test_case_idx, int i, int j, CvMat* arr );
1573
1574     int write_default_params(CvFileStorage* fs);
1575     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1576                                                 CvSize** whole_sizes, bool *are_images );
1577     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1578     CvPoint2D32f center;
1579 };
1580
1581
1582 CV_GetRectSubPixTest::CV_GetRectSubPixTest()
1583     : CV_ImgWarpBaseTest( "warp-subpix-rect", "cvGetRectSubPix", false )
1584 {
1585     //spatial_scale_zoom = spatial_scale_decimate;
1586     spatial_scale_decimate = spatial_scale_zoom;
1587     //default_timing_param_names = imgwarp_perspective_param_names;
1588     support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1589     default_timing_param_names = 0;
1590 }
1591
1592
1593 int CV_GetRectSubPixTest::write_default_params( CvFileStorage* fs )
1594 {
1595     int code = CV_ImgWarpBaseTest::write_default_params( fs );
1596     if( code < 0 )
1597         return code;
1598     
1599     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
1600     {
1601         int i;
1602         start_write_param( fs );
1603
1604         cvStartWriteStruct( fs, "rect_size", CV_NODE_SEQ+CV_NODE_FLOW );
1605         for( i = 0; rectsubpix_sizes[i].width > 0; i++ )
1606         {
1607             cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW );
1608             cvWriteInt( fs, 0, rectsubpix_sizes[i].width );
1609             cvWriteInt( fs, 0, rectsubpix_sizes[i].height );
1610             cvEndWriteStruct(fs);
1611         }
1612         cvEndWriteStruct(fs);
1613     }
1614
1615     return code;
1616 }
1617
1618
1619 void CV_GetRectSubPixTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1620 {
1621     CvRNG* rng = ts->get_rng();
1622     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1623     int src_depth = cvTsRandInt(rng) % 2, dst_depth;
1624     int cn = cvTsRandInt(rng) % 2 ? 3 : 1;
1625     CvSize src_size, dst_size;
1626     
1627     dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F;
1628     if( src_depth < CV_32F && cvTsRandInt(rng) % 2 )
1629         dst_depth = CV_32F;
1630     
1631     types[INPUT][0] = CV_MAKETYPE(src_depth,cn);
1632     types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn);
1633
1634     src_size = sizes[INPUT][0];
1635     dst_size.width = cvRound(sqrt(cvTsRandReal(rng)*src_size.width) + 1);
1636     dst_size.height = cvRound(sqrt(cvTsRandReal(rng)*src_size.height) + 1);
1637     dst_size.width = MIN(dst_size.width,src_size.width);
1638     dst_size.height = MIN(dst_size.width,src_size.height);
1639     sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dst_size;
1640     
1641     center.x = (float)(cvTsRandReal(rng)*src_size.width);
1642     center.y = (float)(cvTsRandReal(rng)*src_size.height);
1643     interpolation = CV_INTER_LINEAR;
1644 }
1645
1646
1647 void CV_GetRectSubPixTest::fill_array( int test_case_idx, int i, int j, CvMat* arr )
1648 {
1649     if( i != INPUT )
1650         CV_ImgWarpBaseTestImpl::fill_array( test_case_idx, i, j, arr );
1651 }
1652
1653 void CV_GetRectSubPixTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1654         CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1655 {
1656     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1657                                                                whole_sizes, are_images );
1658     interpolation = CV_INTER_LINEAR;
1659 }
1660
1661
1662 void CV_GetRectSubPixTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1663 {
1664     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
1665 }
1666
1667
1668 void CV_GetRectSubPixTest::run_func()
1669 {
1670     cvGetRectSubPix( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], center );
1671 }
1672
1673
1674 double CV_GetRectSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1675 {
1676     int in_depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1677     int out_depth = CV_MAT_DEPTH(test_mat[INPUT_OUTPUT][0].type);
1678
1679     return in_depth >= CV_32F ? 1e-3 : out_depth >= CV_32F ? 1e-2 : 1;
1680 }
1681
1682
1683 int CV_GetRectSubPixTest::prepare_test_case( int test_case_idx )
1684 {
1685     return CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
1686 }
1687
1688
1689 void CV_GetRectSubPixTest::prepare_to_validation( int /*test_case_idx*/ )
1690 {
1691     CvMat* src0 = &test_mat[INPUT][0];
1692     CvMat* dst0 = &test_mat[REF_INPUT_OUTPUT][0];
1693     CvMat* src = src0, *dst = dst0;
1694     int ftype = CV_MAKETYPE(CV_32F,CV_MAT_CN(src0->type));
1695     double a[] = { 1, 0, center.x - dst->cols*0.5 + 0.5,
1696                    0, 1, center.y - dst->rows*0.5 + 0.5 };
1697     if( CV_MAT_DEPTH(src->type) != CV_32F )
1698     {
1699         src = cvCreateMat( src0->rows, src0->cols, ftype );
1700         cvTsConvert( src0, src );
1701     }
1702
1703     if( CV_MAT_DEPTH(dst->type) != CV_32F )
1704         dst = cvCreateMat( dst0->rows, dst0->cols, ftype );
1705
1706     cvTsGetQuadrangeSubPix( src, dst, a );
1707
1708     if( dst != dst0 )
1709     {
1710         cvTsConvert( dst, dst0 );
1711         cvReleaseMat( &dst );
1712     }
1713     if( src != src0 )
1714         cvReleaseMat( &src );
1715 }
1716
1717
1718 CV_GetRectSubPixTest subpix_rect_test;
1719
1720
1721 class CV_GetQuadSubPixTest : public CV_ImgWarpBaseTest
1722 {
1723 public:
1724     CV_GetQuadSubPixTest();
1725
1726 protected:
1727     void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1728     void run_func();
1729     int prepare_test_case( int test_case_idx );
1730     void prepare_to_validation( int /*test_case_idx*/ );
1731     double get_success_error_level( int test_case_idx, int i, int j );
1732
1733     int write_default_params(CvFileStorage* fs);
1734     void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1735                                                 CvSize** whole_sizes, bool *are_images );
1736     void print_timing_params( int test_case_idx, char* ptr, int params_left );
1737 };
1738
1739
1740 CV_GetQuadSubPixTest::CV_GetQuadSubPixTest()
1741     : CV_ImgWarpBaseTest( "warp-subpix-quad", "cvGetQuadSubPix", true )
1742 {
1743     //spatial_scale_zoom = spatial_scale_decimate;
1744     spatial_scale_decimate = spatial_scale_zoom;
1745     //default_timing_param_names = imgwarp_affine_param_names;
1746     support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
1747     default_timing_param_names = 0;
1748 }
1749
1750
1751 int CV_GetQuadSubPixTest::write_default_params( CvFileStorage* fs )
1752 {
1753     int code = CV_ImgWarpBaseTest::write_default_params( fs );
1754     if( code < 0 )
1755         return code;
1756     
1757     if( ts->get_testing_mode() == CvTS::TIMING_MODE )
1758     {
1759         int i;
1760         start_write_param( fs );
1761
1762         cvStartWriteStruct( fs, "rotate_scale", CV_NODE_SEQ+CV_NODE_FLOW );
1763         for( i = 0; imgwarp_affine_rotate_scale[i][0] >= 0; i++ )
1764         {
1765             cvStartWriteStruct( fs, 0, CV_NODE_SEQ+CV_NODE_FLOW );
1766             cvWriteRawData( fs, imgwarp_affine_rotate_scale[i], 4, "d" );
1767             cvEndWriteStruct(fs);
1768         }
1769         cvEndWriteStruct(fs);
1770     }
1771
1772     return code;
1773 }
1774
1775
1776 void CV_GetQuadSubPixTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1777 {
1778     int min_size = 4;
1779     CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1780     CvSize sz = sizes[INPUT][0], dsz;
1781     CvRNG* rng = ts->get_rng();
1782     int msz, src_depth = cvTsRandInt(rng) % 2, dst_depth;
1783     int cn = cvTsRandInt(rng) % 2 ? 3 : 1;
1784     
1785     dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F;
1786     if( src_depth < CV_32F && cvTsRandInt(rng) % 2 )
1787         dst_depth = CV_32F;
1788     
1789     types[INPUT][0] = CV_MAKETYPE(src_depth,cn);
1790     types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn);
1791
1792     sz.width = MAX(sz.width,min_size);
1793     sz.height = MAX(sz.height,min_size);
1794     sizes[INPUT][0] = sz;
1795     msz = MIN( sz.width, sz.height );
1796
1797     dsz.width = cvRound(sqrt(cvTsRandReal(rng)*msz) + 1);
1798     dsz.height = cvRound(sqrt(cvTsRandReal(rng)*msz) + 1);
1799     dsz.width = MIN(dsz.width,msz);
1800     dsz.height = MIN(dsz.width,msz);
1801     dsz.width = MAX(dsz.width,min_size);
1802     dsz.height = MAX(dsz.height,min_size);
1803     sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dsz;
1804     sizes[INPUT][1] = cvSize( 3, 2 );
1805 }
1806
1807
1808 void CV_GetQuadSubPixTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1809                 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1810 {
1811     CV_ImgWarpBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
1812                                                                whole_sizes, are_images );
1813
1814     sizes[INPUT][1] = whole_sizes[INPUT][1] = cvSize(3,2);
1815     sizes[TEMP][0] = whole_sizes[TEMP][0] =
1816         sizes[TEMP][1] = whole_sizes[TEMP][1] = cvSize(0,0);
1817     types[INPUT][1] = CV_64FC1;
1818
1819     interpolation = CV_INTER_LINEAR;
1820 }
1821
1822
1823 void CV_GetQuadSubPixTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1824 {
1825     double coeffs[4];
1826     const CvFileNode* node = find_timing_param( "rotate_scale" );
1827     assert( node && CV_NODE_IS_SEQ(node->tag) );
1828     cvReadRawData( ts->get_file_storage(), node, coeffs, "4d" );
1829     
1830     sprintf( ptr, "fx=%.2f,fy=%.2f,angle=%.1fdeg,scale=%.1f,", coeffs[0], coeffs[1], coeffs[2], coeffs[3] );
1831     ptr += strlen(ptr);
1832     params_left -= 4;
1833
1834     CV_ImgWarpBaseTest::print_timing_params( test_case_idx, ptr, params_left );
1835 }
1836
1837
1838 void CV_GetQuadSubPixTest::run_func()
1839 {
1840     cvGetQuadrangleSubPix( test_array[INPUT][0],
1841         test_array[INPUT_OUTPUT][0], &test_mat[INPUT][1] );
1842 }
1843
1844
1845 double CV_GetQuadSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1846 {
1847     int in_depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1848     //int out_depth = CV_MAT_DEPTH(test_mat[INPUT_OUTPUT][0].type);
1849
1850     return in_depth >= CV_32F ? 1e-2 : 4;
1851 }
1852
1853
1854 int CV_GetQuadSubPixTest::prepare_test_case( int test_case_idx )
1855 {
1856     CvRNG* rng = ts->get_rng();
1857     int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
1858     const CvMat* src = &test_mat[INPUT][0];
1859     CvMat* mat = &test_mat[INPUT][1];
1860     CvPoint2D32f center;
1861     double scale, angle;
1862
1863     if( code <= 0 )
1864         return code;
1865
1866     if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1867     {
1868         double a[6];
1869         CvMat A = cvMat( 2, 3, CV_64FC1, a );
1870
1871         center.x = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->cols);
1872         center.y = (float)((cvTsRandReal(rng)*1.2 - 0.1)*src->rows);
1873         angle = cvTsRandReal(rng)*360;
1874         scale = cvTsRandReal(rng)*0.2 + 0.9;
1875         
1876         // y = Ax + b -> x = A^-1(y - b) = A^-1*y - A^-1*b
1877         scale = 1./scale;
1878         angle = angle*(CV_PI/180.);
1879         a[0] = a[4] = cos(angle)*scale;
1880         a[1] = sin(angle)*scale;
1881         a[3] = -a[1];
1882         a[2] = center.x - a[0]*center.x - a[1]*center.y;
1883         a[5] = center.y - a[3]*center.x - a[4]*center.y;
1884         cvTsConvert( &A, mat );
1885     }
1886
1887     return code;
1888 }
1889
1890
1891 void CV_GetQuadSubPixTest::prepare_to_validation( int /*test_case_idx*/ )
1892 {
1893     CvMat* src0 = &test_mat[INPUT][0];
1894     CvMat* dst0 = &test_mat[REF_INPUT_OUTPUT][0];
1895     CvMat* src = src0, *dst = dst0;
1896     int ftype = CV_MAKETYPE(CV_32F,CV_MAT_CN(src0->type));
1897     double a[6], dx = (dst0->cols - 1)*0.5, dy = (dst0->rows - 1)*0.5;
1898     CvMat A = cvMat( 2, 3, CV_64F, a );
1899
1900     if( CV_MAT_DEPTH(src->type) != CV_32F )
1901     {
1902         src = cvCreateMat( src0->rows, src0->cols, ftype );
1903         cvTsConvert( src0, src );
1904     }
1905
1906     if( CV_MAT_DEPTH(dst->type) != CV_32F )
1907         dst = cvCreateMat( dst0->rows, dst0->cols, ftype );
1908
1909     cvTsConvert( &test_mat[INPUT][1], &A );
1910     a[2] -= a[0]*dx + a[1]*dy;
1911     a[5] -= a[3]*dx + a[4]*dy;
1912     cvTsGetQuadrangeSubPix( src, dst, a );
1913
1914     if( dst != dst0 )
1915     {
1916         cvTsConvert( dst, dst0 );
1917         cvReleaseMat( &dst );
1918     }
1919
1920     if( src != src0 )
1921         cvReleaseMat( &src );
1922 }
1923
1924
1925 CV_GetQuadSubPixTest warp_subpix_quad_test;
1926
1927 /* End of file. */