1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
44 static const CvSize filter_sizes[] = {{30,30}, {320, 240}, {720,480}, {-1,-1}};
45 static const CvSize filter_whole_sizes[] = {{320,240}, {320, 240}, {720,480}, {-1,-1}};
46 static const int filter_depths[] = { CV_8U, CV_16U, CV_32F, -1 };
47 static const int filter_channels[] = { 1, 3, 4, -1 };
49 class CV_FilterBaseTestImpl : public CvArrTest
52 CV_FilterBaseTestImpl( const char* test_name, const char* test_funcs, bool _fp_kernel );
55 int prepare_test_case( int test_case_idx );
56 void prepare_to_validation( int /*test_case_idx*/ );
57 int read_params( CvFileStorage* fs );
58 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
59 void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
60 int write_default_params(CvFileStorage* fs);
63 int max_aperture_size;
69 CV_FilterBaseTestImpl::CV_FilterBaseTestImpl( const char* test_name, const char* test_funcs, bool _fp_kernel )
70 : CvArrTest( test_name, test_funcs, "" ), fp_kernel(_fp_kernel)
72 test_array[INPUT].push(NULL);
73 test_array[INPUT].push(NULL);
74 test_array[TEMP].push(NULL);
75 test_array[OUTPUT].push(NULL);
76 test_array[REF_OUTPUT].push(NULL);
77 max_aperture_size = 13;
79 aperture_size = cvSize(0,0);
80 anchor = cvPoint(0,0);
81 element_wise_relative_error = false;
83 size_list = filter_sizes;
84 whole_size_list = filter_whole_sizes;
85 depth_list = filter_depths;
86 cn_list = filter_channels;
90 int CV_FilterBaseTestImpl::read_params( CvFileStorage* fs )
92 int code = CvArrTest::read_params( fs );
96 if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
98 max_aperture_size = cvReadInt( find_param( fs, "max_aperture_size" ), max_aperture_size );
99 max_aperture_size = cvTsClipInt( max_aperture_size, 1, 100 );
106 int CV_FilterBaseTestImpl::write_default_params( CvFileStorage* fs )
108 int code = CvArrTest::write_default_params( fs );
112 if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
114 write_param( fs, "max_aperture_size", max_aperture_size );
121 void CV_FilterBaseTestImpl::get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high )
123 CvArrTest::get_minmax_bounds( i, j, type, low, high );
130 if( ts->get_testing_mode() == CvTS::TIMING_MODE )
132 *low = cvScalarAll(-1);
133 *high = cvScalarAll(1);
137 CvRNG* rng = ts->get_rng();
138 double val = exp( cvTsRandReal(rng)*10 - 4 );
139 *low = cvScalarAll(-val);
140 *high = cvScalarAll(val);
145 *low = cvScalarAll(0);
146 *high = cvScalarAll(2);
149 else if( CV_MAT_DEPTH(type) == CV_32F )
151 *low = cvScalarAll(-10.);
152 *high = cvScalarAll(10.);
158 void CV_FilterBaseTestImpl::get_test_array_types_and_sizes( int test_case_idx,
159 CvSize** sizes, int** types )
161 CvRNG* rng = ts->get_rng();
162 int depth = cvTsRandInt(rng) % CV_32F;
163 int cn = cvTsRandInt(rng) % 3 + 1;
164 CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
165 depth += depth == CV_8S;
168 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0] = CV_MAKETYPE(depth, cn);
170 aperture_size.width = cvTsRandInt(rng) % max_aperture_size + 1;
171 aperture_size.height = cvTsRandInt(rng) % max_aperture_size + 1;
172 anchor.x = cvTsRandInt(rng) % aperture_size.width;
173 anchor.y = cvTsRandInt(rng) % aperture_size.height;
175 types[INPUT][1] = fp_kernel ? CV_32FC1 : CV_8UC1;
176 sizes[INPUT][1] = aperture_size;
177 sizes[TEMP][0].width += aperture_size.width - 1;
178 sizes[TEMP][0].height += aperture_size.height - 1;
180 inplace = cvTsRandInt(rng) % 2 != 0;
184 int CV_FilterBaseTestImpl::prepare_test_case( int test_case_idx )
186 int code = CvArrTest::prepare_test_case( test_case_idx );
189 if( inplace && CV_ARE_TYPES_EQ(&test_mat[INPUT][0],&test_mat[OUTPUT][0]))
190 cvTsCopy( &test_mat[INPUT][0], &test_mat[OUTPUT][0] );
198 void CV_FilterBaseTestImpl::prepare_to_validation( int /*test_case_idx*/ )
200 CvMat* src = &test_mat[INPUT][0];
202 if( !CV_ARE_TYPES_EQ( src, &test_mat[TEMP][0] ))
204 cvTsConvert( src, &test_mat[REF_OUTPUT][0] );
205 src = &test_mat[REF_OUTPUT][0];
207 cvTsPrepareToFilter( src, &test_mat[TEMP][0],
208 anchor, CV_TS_BORDER_REPLICATE );
212 CV_FilterBaseTestImpl filter_base( "filter", "", false );
215 class CV_FilterBaseTest : public CV_FilterBaseTestImpl
218 CV_FilterBaseTest( const char* test_name, const char* test_funcs, bool _fp_kernel );
222 CV_FilterBaseTest::CV_FilterBaseTest( const char* test_name, const char* test_funcs, bool _fp_kernel )
223 : CV_FilterBaseTestImpl( test_name, test_funcs, _fp_kernel )
232 /////////////////////////
234 static const char* morph_param_names[] = { "mask_size", "shape", "size", "channels", "depth", 0 };
235 static const int morph_depths[] = { CV_8U, CV_32F, -1 };
236 static const int morph_mask_size[] = { 3, 5, 11 };
237 static const char* morph_mask_shape[] = { "rect", "ellipse", 0 };
239 class CV_MorphologyBaseTestImpl : public CV_FilterBaseTest
242 CV_MorphologyBaseTestImpl( const char* test_name, const char* test_funcs );
245 void prepare_to_validation( int test_case_idx );
246 int prepare_test_case( int test_case_idx );
247 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
248 void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
249 CvSize** whole_sizes, bool *are_images );
250 void print_timing_params( int test_case_idx, char* ptr, int params_left );
251 double get_success_error_level( int test_case_idx, int i, int j );
252 int write_default_params(CvFileStorage* fs);
253 int optype, optype_min, optype_max;
255 IplConvKernel* element;
259 CV_MorphologyBaseTestImpl::CV_MorphologyBaseTestImpl( const char* test_name, const char* test_funcs )
260 : CV_FilterBaseTest( test_name, test_funcs, false )
264 size_list = filter_sizes;
265 whole_size_list = filter_whole_sizes;
266 depth_list = morph_depths;
267 cn_list = filter_channels;
268 optype = optype_min = optype_max = -1;
274 int CV_MorphologyBaseTestImpl::write_default_params( CvFileStorage* fs )
276 int code = CV_FilterBaseTest::write_default_params( fs );
277 if( code >= 0 && ts->get_testing_mode() == CvTS::TIMING_MODE && strcmp(tested_functions,"") == 0 )
279 start_write_param( fs );
280 write_int_list( fs, "mask_size", morph_mask_size, CV_DIM(morph_mask_size) );
281 write_string_list( fs, "shape", morph_mask_shape );
287 void CV_MorphologyBaseTestImpl::get_test_array_types_and_sizes( int test_case_idx,
288 CvSize** sizes, int** types )
290 CvRNG* rng = ts->get_rng();
291 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
292 int depth = cvTsRandInt(rng) % 4;
293 depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : depth == 2 ? CV_16S : CV_32F;
294 int cn = CV_MAT_CN(types[INPUT][0]);
296 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0] = CV_MAKETYPE(depth, cn);
297 shape = cvTsRandInt(rng) % 4;
299 shape = CV_SHAPE_CUSTOM;
301 sizes[INPUT][1] = cvSize(0,0);
302 optype = cvTsRandInt(rng) % (optype_max - optype_min + 1) + optype_min;
306 void CV_MorphologyBaseTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
307 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
309 CV_FilterBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
310 whole_sizes, are_images );
311 const char* shape_str = cvReadString( find_timing_param( "shape" ), "rect" );
312 shape = strcmp( shape_str, "rect" ) == 0 ? CV_SHAPE_RECT : CV_SHAPE_ELLIPSE;
313 aperture_size.width = cvReadInt( find_timing_param( "mask_size" ), 3 );
314 aperture_size.height = aperture_size.width;
315 anchor.x = anchor.y = aperture_size.width / 2;
319 void CV_MorphologyBaseTestImpl::print_timing_params( int test_case_idx, char* ptr, int params_left )
321 sprintf( ptr, "%dx%d,", aperture_size.width, aperture_size.height );
323 sprintf( ptr, "%s,", shape == CV_SHAPE_RECT ? "rect" : "ellipse" );
327 CV_FilterBaseTest::print_timing_params( test_case_idx, ptr, params_left );
331 double CV_MorphologyBaseTestImpl::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
333 return CV_MAT_DEPTH(test_mat[INPUT][0].type) < CV_32F ||
334 (optype == CV_MOP_ERODE || optype == CV_MOP_DILATE ||
335 optype == CV_MOP_OPEN || optype == CV_MOP_CLOSE) ? 0 : 1e-5;
339 int CV_MorphologyBaseTestImpl::prepare_test_case( int test_case_idx )
341 int code = CV_FilterBaseTest::prepare_test_case( test_case_idx );
347 if( shape == CV_SHAPE_CUSTOM )
349 eldata = (int*)alloca( aperture_size.width*aperture_size.height*sizeof(eldata[0]) );
350 uchar* src = test_mat[INPUT][1].data.ptr;
351 int srcstep = test_mat[INPUT][1].step;
352 int i, j, nonzero = 0;
354 for( i = 0; i < aperture_size.height; i++ )
356 for( j = 0; j < aperture_size.width; j++ )
358 eldata[i*aperture_size.width + j] = src[i*srcstep + j];
359 nonzero += src[i*srcstep + j] != 0;
364 eldata[anchor.y*aperture_size.width + anchor.x] = 1;
367 cvReleaseStructuringElement( &element );
368 element = cvCreateStructuringElementEx( aperture_size.width, aperture_size.height,
369 anchor.x, anchor.y, shape, eldata );
374 void CV_MorphologyBaseTestImpl::prepare_to_validation( int test_case_idx )
376 CV_FilterBaseTest::prepare_to_validation( test_case_idx );
377 CvMat *src = &test_mat[TEMP][0], *dst = &test_mat[REF_OUTPUT][0];
379 if( optype == CV_MOP_ERODE || optype == CV_MOP_DILATE )
381 cvTsMinMaxFilter( src, dst, element, optype );
385 cv::Ptr<CvMat> dst0 = cvCloneMat(dst), src1 = cvCloneMat(src);
386 if( optype == CV_MOP_OPEN )
388 cvTsMinMaxFilter( src, dst0, element, CV_MOP_ERODE );
389 cvTsPrepareToFilter( dst0, src1, anchor, CV_TS_BORDER_REPLICATE );
390 cvTsMinMaxFilter( src1, dst, element, CV_MOP_DILATE );
392 else if( optype == CV_MOP_CLOSE )
394 cvTsMinMaxFilter( src, dst0, element, CV_MOP_DILATE );
395 cvTsPrepareToFilter( dst0, src1, anchor, CV_TS_BORDER_REPLICATE );
396 cvTsMinMaxFilter( src1, dst, element, CV_MOP_ERODE );
398 else if( optype == CV_MOP_GRADIENT )
400 cvTsMinMaxFilter( src, dst0, element, CV_MOP_ERODE );
401 cvTsMinMaxFilter( src, dst, element, CV_MOP_DILATE );
402 cvTsAdd( dst, cvScalarAll(1), dst0, cvScalarAll(-1), cvScalarAll(0), dst, 0 );
404 else if( optype == CV_MOP_TOPHAT )
406 cvTsMinMaxFilter( src, dst0, element, CV_MOP_ERODE );
407 cvTsPrepareToFilter( dst0, src1, anchor, CV_TS_BORDER_REPLICATE );
408 cvTsMinMaxFilter( src1, dst, element, CV_MOP_DILATE );
409 cvTsAdd( dst, cvScalarAll(-1), &test_mat[INPUT][0], cvScalarAll(1), cvScalarAll(0), dst, 0 );
413 cvTsMinMaxFilter( src, dst0, element, CV_MOP_DILATE );
414 cvTsPrepareToFilter( dst0, src1, anchor, CV_TS_BORDER_REPLICATE );
415 cvTsMinMaxFilter( src1, dst, element, CV_MOP_ERODE );
416 cvTsAdd( dst, cvScalarAll(1), &test_mat[INPUT][0], cvScalarAll(-1), cvScalarAll(0), dst, 0 );
420 cvReleaseStructuringElement( &element );
424 CV_MorphologyBaseTestImpl morph( "morph", "" );
427 class CV_MorphologyBaseTest : public CV_MorphologyBaseTestImpl
430 CV_MorphologyBaseTest( const char* test_name, const char* test_funcs );
434 CV_MorphologyBaseTest::CV_MorphologyBaseTest( const char* test_name, const char* test_funcs )
435 : CV_MorphologyBaseTestImpl( test_name, test_funcs )
437 default_timing_param_names = morph_param_names;
444 /////////////// erode ///////////////
446 class CV_ErodeTest : public CV_MorphologyBaseTest
455 CV_ErodeTest::CV_ErodeTest()
456 : CV_MorphologyBaseTest( "morph-erode", "cvErode" )
458 optype_min = optype_max = CV_MOP_ERODE;
462 void CV_ErodeTest::run_func()
464 cvErode( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
465 test_array[OUTPUT][0], element, 1 );
468 CV_ErodeTest erode_test;
471 /////////////// dilate ///////////////
473 class CV_DilateTest : public CV_MorphologyBaseTest
482 CV_DilateTest::CV_DilateTest()
483 : CV_MorphologyBaseTest( "morph-dilate", "cvDilate" )
485 optype_min = optype_max = CV_MOP_DILATE;
489 void CV_DilateTest::run_func()
491 cvDilate( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
492 test_array[OUTPUT][0], element, 1 );
495 CV_DilateTest dilate_test;
497 /////////////// morphEx ///////////////
499 class CV_MorphExTest : public CV_MorphologyBaseTest
508 CV_MorphExTest::CV_MorphExTest()
509 : CV_MorphologyBaseTest( "morph-ex", "cvMorphologyEx" )
511 optype_min = CV_MOP_ERODE;
512 optype_max = CV_MOP_BLACKHAT;
516 void CV_MorphExTest::run_func()
518 cvMorphologyEx( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
519 test_array[OUTPUT][0], 0, element, optype, 1 );
522 CV_MorphExTest morphex_test;
524 /////////////// generic filter ///////////////
526 static const char* filter_generic_param_names[] = { "mask_size", "size", "channels", "depth", 0 };
528 class CV_FilterTest : public CV_FilterBaseTest
534 void prepare_to_validation( int test_case_idx );
536 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
537 double get_success_error_level( int test_case_idx, int i, int j );
539 void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
540 CvSize** whole_sizes, bool *are_images );
541 void print_timing_params( int test_case_idx, char* ptr, int params_left );
542 int write_default_params(CvFileStorage* fs);
546 CV_FilterTest::CV_FilterTest()
547 : CV_FilterBaseTest( "filter-generic", "cvFilter2D", true )
549 default_timing_param_names = filter_generic_param_names;
553 int CV_FilterTest::write_default_params( CvFileStorage* fs )
555 int code = CV_FilterBaseTest::write_default_params( fs );
556 if( code >= 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
558 start_write_param( fs );
559 write_int_list( fs, "mask_size", morph_mask_size, CV_DIM(morph_mask_size) );
565 void CV_FilterTest::get_test_array_types_and_sizes( int test_case_idx,
566 CvSize** sizes, int** types )
568 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
569 CvRNG* rng = ts->get_rng();
570 int depth = cvTsRandInt(rng)%3;
571 int cn = CV_MAT_CN(types[INPUT][0]);
572 depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : CV_32F;
573 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0] = CV_MAKETYPE(depth, cn);
577 void CV_FilterTest::get_timing_test_array_types_and_sizes( int test_case_idx,
578 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
580 CV_FilterBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
581 whole_sizes, are_images );
582 aperture_size.width = cvReadInt( find_timing_param( "mask_size" ), 3 );
583 aperture_size.height = aperture_size.width;
584 anchor.x = anchor.y = aperture_size.width / 2;
585 sizes[INPUT][1] = aperture_size;
586 types[INPUT][1] = CV_32FC1;
590 void CV_FilterTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
592 sprintf( ptr, "%dx%d,", aperture_size.width, aperture_size.height );
596 CV_FilterBaseTest::print_timing_params( test_case_idx, ptr, params_left );
600 double CV_FilterTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
602 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
603 return depth <= CV_8S ? 2 : depth <= CV_32S ? 32 :
604 depth == CV_32F ? 1e-5 : 1e-10;
608 void CV_FilterTest::run_func()
610 cvFilter2D( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
611 test_array[OUTPUT][0], &test_mat[INPUT][1], anchor );
615 void CV_FilterTest::prepare_to_validation( int test_case_idx )
617 CV_FilterBaseTest::prepare_to_validation( test_case_idx );
618 cvTsConvolve2D( &test_mat[TEMP][0], &test_mat[REF_OUTPUT][0], &test_mat[INPUT][1], anchor );
621 CV_FilterTest filter;
624 ////////////////////////
626 static const int laplace_aperture[] = { 3, 5, 7 };
627 static const int sobel_aperture[] = { -1, 3, 5, 7 };
628 static const char* laplace_param_names[] = { "aperture", "size", "depth", 0 };
629 static const char* sobel_param_names[] = { "deriv_type", "aperture", "size", "depth", 0 };
630 static const char* sobel_deriv_type[] = { "dx", "dy", "d2x", "d2y", "dxdy", 0 };
632 class CV_DerivBaseTest : public CV_FilterBaseTest
635 CV_DerivBaseTest( const char* test_name, const char* test_funcs );
637 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
638 double get_success_error_level( int test_case_idx, int i, int j );
639 void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
640 CvSize** whole_sizes, bool *are_images );
645 CV_DerivBaseTest::CV_DerivBaseTest( const char* test_name, const char* test_funcs )
646 : CV_FilterBaseTest( test_name, test_funcs, true )
648 max_aperture_size = 7;
649 depth_list = morph_depths;
654 void CV_DerivBaseTest::get_test_array_types_and_sizes( int test_case_idx,
655 CvSize** sizes, int** types )
657 CvRNG* rng = ts->get_rng();
658 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
659 int depth = cvTsRandInt(rng) % 2;
660 depth = depth == 0 ? CV_8U : CV_32F;
661 types[INPUT][0] = CV_MAKETYPE(depth,1);
662 types[TEMP][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth==CV_8U?CV_16S:CV_32F,1);
663 _aperture_size = (cvTsRandInt(rng)%5)*2 - 1;
664 sizes[INPUT][1] = aperture_size = cvSize(_aperture_size, _aperture_size);
668 double CV_DerivBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
670 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
671 return depth <= CV_8S ? 2 : 5e-4;
675 void CV_DerivBaseTest::get_timing_test_array_types_and_sizes( int test_case_idx,
676 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
678 CV_FilterBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
679 whole_sizes, are_images );
680 _aperture_size = cvReadInt( find_timing_param( "aperture" ), 3 );
681 aperture_size.width = aperture_size.height = _aperture_size < 0 ? 3 : _aperture_size;
682 anchor.x = anchor.y = aperture_size.width / 2;
683 sizes[INPUT][1] = aperture_size;
684 types[INPUT][1] = CV_32FC1;
685 types[OUTPUT][0] = types[INPUT][0] == CV_8UC1 ? CV_16SC1 : types[INPUT][0];
689 /////////////// sobel ///////////////
691 class CV_SobelTest : public CV_DerivBaseTest
697 int prepare_test_case( int test_case_idx );
698 void prepare_to_validation( int test_case_idx );
700 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
701 void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
702 CvSize** whole_sizes, bool *are_images );
703 int write_default_params( CvFileStorage* fs );
704 void print_timing_params( int test_case_idx, char* ptr, int params_left );
711 CV_SobelTest::CV_SobelTest() : CV_DerivBaseTest( "filter-sobel", "cvSobel" )
714 default_timing_param_names = sobel_param_names;
718 int CV_SobelTest::write_default_params( CvFileStorage* fs )
720 int code = CV_DerivBaseTest::write_default_params( fs );
721 if( code >= 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
723 start_write_param( fs );
724 write_int_list( fs, "aperture", sobel_aperture, CV_DIM(sobel_aperture) );
725 write_string_list( fs, "deriv_type", sobel_deriv_type );
731 void CV_SobelTest::get_test_array_types_and_sizes( int test_case_idx,
732 CvSize** sizes, int** types )
734 CvRNG* rng = ts->get_rng();
735 CV_DerivBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
736 int max_d = _aperture_size > 0 ? 2 : 1;
737 origin = cvTsRandInt(rng) % 2;
738 dx = cvTsRandInt(rng) % (max_d + 1);
739 dy = cvTsRandInt(rng) % (max_d + 1 - dx);
740 if( dx == 0 && dy == 0 )
742 if( cvTsRandInt(rng) % 2 )
745 CV_SWAP( dx, dy, t );
748 if( _aperture_size < 0 )
749 aperture_size = cvSize(3, 3);
750 else if( _aperture_size == 1 )
753 aperture_size = cvSize(1, 3);
755 aperture_size = cvSize(3, 1);
759 aperture_size = cvSize(3, 3);
763 aperture_size = cvSize(_aperture_size, _aperture_size);
765 sizes[INPUT][1] = aperture_size;
766 sizes[TEMP][0].width = sizes[INPUT][0].width + aperture_size.width - 1;
767 sizes[TEMP][0].height = sizes[INPUT][0].height + aperture_size.height - 1;
768 anchor.x = aperture_size.width / 2;
769 anchor.y = aperture_size.height / 2;
773 void CV_SobelTest::get_timing_test_array_types_and_sizes( int test_case_idx,
774 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
776 CV_DerivBaseTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
777 whole_sizes, are_images );
778 //_aperture_size = cvReadInt( find_timing_param( "mask_size" ), 3 );
779 const char* mask_type = cvReadString( find_timing_param( "deriv_type" ), "dx" );
780 if( strcmp( mask_type, "dx" ) == 0 )
782 else if( strcmp( mask_type, "dy" ) == 0 )
784 else if( strcmp( mask_type, "d2x" ) == 0 )
786 else if( strcmp( mask_type, "d2y" ) == 0 )
792 aperture_size.width = aperture_size.height = _aperture_size < 0 ? 3 : _aperture_size;
793 anchor.x = anchor.y = aperture_size.width / 2;
794 sizes[INPUT][1] = aperture_size;
795 types[INPUT][1] = CV_32FC1;
796 types[OUTPUT][0] = types[INPUT][0] == CV_8UC1 ? CV_16SC1 : types[INPUT][0];
800 int CV_SobelTest::prepare_test_case( int test_case_idx )
802 int code = CV_DerivBaseTest::prepare_test_case( test_case_idx );
806 if( _aperture_size < 0 && ((dx != 1 || dy != 0) && (dx != 0 || dy != 1)) )
811 src = inplace ? &test_mat[OUTPUT][0] : &test_mat[INPUT][0];
812 cvGetImage( src, &img );
817 src = inplace ? test_array[OUTPUT][0] : test_array[INPUT][0];
823 void CV_SobelTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
825 const char* mask_type = cvReadString( find_timing_param( "deriv_type" ), "dx" );
826 sprintf( ptr, "%dx%d,%s_%s,", aperture_size.width, aperture_size.height,
827 _aperture_size > 0 ? "Sobel" : "Scharr", mask_type );
831 CV_DerivBaseTest::print_timing_params( test_case_idx, ptr, params_left );
835 void CV_SobelTest::run_func()
837 cvSobel( src, test_array[OUTPUT][0], dx, dy, _aperture_size );
841 static void cvTsCalcSobelKernel1D( int order, int _aperture_size, int size, int* kernel )
843 int i, j, oldval, newval;
845 if( _aperture_size < 0 )
847 static const int scharr[] = { 3, 10, 3, -1, 0, 1 };
849 memcpy( kernel, scharr + order*3, 3*sizeof(scharr[0]));
853 memset( kernel + 1, 0, size * sizeof(kernel[0]));
856 for( i = 0; i < size - order - 1; i++ )
859 for( j = 1; j <= size; j++ )
861 newval = kernel[j] + kernel[j-1];
862 kernel[j-1] = oldval;
867 for( i = 0; i < order; i++ )
870 for( j = 1; j <= size; j++ )
872 newval = kernel[j-1] - kernel[j];
873 kernel[j-1] = oldval;
880 void cvTsCalcSobelKernel2D( int dx, int dy, int _aperture_size, int origin, CvMat* kernel )
883 int* kx = (int*)alloca( (kernel->cols+1)*sizeof(kx[0]) );
884 int* ky = (int*)alloca( (kernel->rows+1)*sizeof(ky[0]) );
886 assert( CV_MAT_TYPE(kernel->type) == CV_32F );
888 cvTsCalcSobelKernel1D( dx, _aperture_size, kernel->cols, kx );
889 cvTsCalcSobelKernel1D( dy, _aperture_size, kernel->rows, ky );
891 for( i = 0; i < kernel->rows; i++ )
893 float* kdata = (float*)(kernel->data.ptr + i*kernel->step);
894 float ay = (float)ky[i]*(origin && (dy & 1) ? -1 : 1);
895 for( j = 0; j < kernel->cols; j++ )
903 void CV_SobelTest::prepare_to_validation( int test_case_idx )
905 CV_DerivBaseTest::prepare_to_validation( test_case_idx );
906 cvTsCalcSobelKernel2D( dx, dy, _aperture_size, origin, &test_mat[INPUT][1] );
907 cvTsConvolve2D( &test_mat[TEMP][0], &test_mat[REF_OUTPUT][0], &test_mat[INPUT][1], anchor );
910 CV_SobelTest sobel_test;
913 /////////////// laplace ///////////////
915 class CV_LaplaceTest : public CV_DerivBaseTest
921 int prepare_test_case( int test_case_idx );
922 void prepare_to_validation( int test_case_idx );
924 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
925 int write_default_params( CvFileStorage* fs );
926 void print_timing_params( int test_case_idx, char* ptr, int params_left );
930 CV_LaplaceTest::CV_LaplaceTest() : CV_DerivBaseTest( "filter-laplace", "cvLaplace" )
932 default_timing_param_names = laplace_param_names;
936 int CV_LaplaceTest::write_default_params( CvFileStorage* fs )
938 int code = CV_DerivBaseTest::write_default_params( fs );
939 if( code >= 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
941 start_write_param( fs );
942 write_int_list( fs, "aperture", laplace_aperture, CV_DIM(laplace_aperture) );
948 void CV_LaplaceTest::get_test_array_types_and_sizes( int test_case_idx,
949 CvSize** sizes, int** types )
951 CV_DerivBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
952 if( _aperture_size <= 1 )
954 if( _aperture_size < 0 )
956 aperture_size = cvSize(3, 3);
959 aperture_size = cvSize(_aperture_size, _aperture_size);
961 sizes[INPUT][1] = aperture_size;
962 sizes[TEMP][0].width = sizes[INPUT][0].width + aperture_size.width - 1;
963 sizes[TEMP][0].height = sizes[INPUT][0].height + aperture_size.height - 1;
964 anchor.x = aperture_size.width / 2;
965 anchor.y = aperture_size.height / 2;
969 void CV_LaplaceTest::run_func()
971 cvLaplace( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
972 test_array[OUTPUT][0], _aperture_size );
976 static void cvTsCalcLaplaceKernel2D( int _aperture_size, CvMat* kernel )
979 int* kx = (int*)alloca( (kernel->cols+1)*sizeof(kx[0]) );
980 int* ky = (int*)alloca( (kernel->rows+1)*sizeof(ky[0]) );
982 cvTsCalcSobelKernel1D( 2, _aperture_size, kernel->cols, kx );
983 if( _aperture_size > 1 )
984 cvTsCalcSobelKernel1D( 0, _aperture_size, kernel->rows, ky );
986 ky[0] = ky[2] = 0, ky[1] = 1;
988 for( i = 0; i < kernel->rows; i++ )
990 float* kdata = (float*)(kernel->data.ptr + i*kernel->step);
991 for( j = 0; j < kernel->cols; j++ )
993 kdata[j] = (float)(kx[j]*ky[i] + kx[i]*ky[j]);
999 int CV_LaplaceTest::prepare_test_case( int test_case_idx )
1001 int code = CV_DerivBaseTest::prepare_test_case( test_case_idx );
1002 return _aperture_size < 0 ? 0 : code;
1006 void CV_LaplaceTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1008 sprintf( ptr, "%dx%d,", aperture_size.width, aperture_size.height );
1012 CV_DerivBaseTest::print_timing_params( test_case_idx, ptr, params_left );
1016 void CV_LaplaceTest::prepare_to_validation( int test_case_idx )
1018 CV_DerivBaseTest::prepare_to_validation( test_case_idx );
1019 cvTsCalcLaplaceKernel2D( _aperture_size, &test_mat[INPUT][1] );
1020 cvTsConvolve2D( &test_mat[TEMP][0], &test_mat[REF_OUTPUT][0], &test_mat[INPUT][1], anchor );
1024 CV_LaplaceTest laplace_test;
1027 ////////////////////////////////////////////////////////////
1029 static const char* smooth_param_names[] = { "mask_size", "size", "channels", "depth", 0 };
1030 static const int smooth_depths[] = { CV_8U, CV_32F, -1 };
1032 class CV_SmoothBaseTest : public CV_FilterBaseTest
1035 CV_SmoothBaseTest( const char* test_name, const char* test_funcs );
1038 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1039 double get_success_error_level( int test_case_idx, int i, int j );
1040 void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1041 CvSize** whole_sizes, bool *are_images );
1042 int write_default_params( CvFileStorage* fs );
1043 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1044 const char* smooth_type;
1048 CV_SmoothBaseTest::CV_SmoothBaseTest( const char* test_name, const char* test_funcs )
1049 : CV_FilterBaseTest( test_name, test_funcs, true )
1051 default_timing_param_names = smooth_param_names;
1052 depth_list = smooth_depths;
1057 int CV_SmoothBaseTest::write_default_params( CvFileStorage* fs )
1059 int code = CV_FilterBaseTest::write_default_params( fs );
1060 if( code >= 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
1062 start_write_param( fs );
1063 write_int_list( fs, "mask_size", morph_mask_size, CV_DIM(morph_mask_size) );
1068 void CV_SmoothBaseTest::get_test_array_types_and_sizes( int test_case_idx,
1069 CvSize** sizes, int** types )
1071 CvRNG* rng = ts->get_rng();
1072 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1073 int depth = cvTsRandInt(rng) % 2;
1074 int cn = CV_MAT_CN(types[INPUT][0]);
1075 depth = depth == 0 ? CV_8U : CV_32F;
1076 types[INPUT][0] = types[TEMP][0] =
1077 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn);
1078 anchor.x = cvTsRandInt(rng)%(max_aperture_size/2+1);
1079 anchor.y = cvTsRandInt(rng)%(max_aperture_size/2+1);
1080 aperture_size.width = anchor.x*2 + 1;
1081 aperture_size.height = anchor.y*2 + 1;
1082 sizes[INPUT][1] = aperture_size;
1083 sizes[TEMP][0].width = sizes[INPUT][0].width + aperture_size.width - 1;
1084 sizes[TEMP][0].height = sizes[INPUT][0].height + aperture_size.height - 1;
1088 double CV_SmoothBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1090 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1091 return depth <= CV_8S ? 1 : 1e-5;
1095 void CV_SmoothBaseTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1096 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1098 CV_FilterBaseTest::get_timing_test_array_types_and_sizes( test_case_idx,
1099 sizes, types, whole_sizes, are_images );
1101 aperture_size.width = aperture_size.height = cvReadInt( find_timing_param( "mask_size" ), 3 );
1102 anchor.x = anchor.y = aperture_size.width / 2;
1103 sizes[INPUT][1] = aperture_size;
1104 types[INPUT][1] = CV_32FC1;
1108 void CV_SmoothBaseTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
1110 sprintf( ptr, "%dx%d,%s,", aperture_size.width, aperture_size.height, smooth_type );
1114 CV_FilterBaseTest::print_timing_params( test_case_idx, ptr, params_left );
1118 /////////////// blur ///////////////
1120 static const char* blur_param_names[] = { "normalize", "mask_size", "size", "channels", "depth", 0 };
1121 static const int blur_normalize[] = { 0, 1 };
1123 class CV_BlurTest : public CV_SmoothBaseTest
1129 int prepare_test_case( int test_case_idx );
1130 void prepare_to_validation( int test_case_idx );
1132 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1133 void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1134 CvSize** whole_sizes, bool *are_images );
1135 int write_default_params( CvFileStorage* fs );
1140 CV_BlurTest::CV_BlurTest() : CV_SmoothBaseTest( "filter-blur", "cvSmooth" )
1142 default_timing_param_names = blur_param_names;
1146 void CV_BlurTest::get_test_array_types_and_sizes( int test_case_idx,
1147 CvSize** sizes, int** types )
1149 CvRNG* rng = ts->get_rng();
1150 CV_SmoothBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1151 normalize = cvTsRandInt(rng) % 2 != 0;
1154 int depth = CV_MAT_DEPTH(types[INPUT][0]);
1155 types[INPUT][0] = CV_MAKETYPE(depth, 1);
1156 types[TEMP][0] = types[OUTPUT][0] =
1157 types[REF_OUTPUT][0] = CV_MAKETYPE(depth==CV_8U?CV_16S:CV_32F,1);
1162 int CV_BlurTest::write_default_params( CvFileStorage* fs )
1164 int code = CV_SmoothBaseTest::write_default_params( fs );
1165 if( code >= 0 && ts->get_testing_mode() == CvTS::TIMING_MODE )
1167 write_int_list( fs, "normalize", blur_normalize, CV_DIM(blur_normalize) );
1173 void CV_BlurTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1174 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1176 CV_SmoothBaseTest::get_timing_test_array_types_and_sizes( test_case_idx,
1177 sizes, types, whole_sizes, are_images );
1178 normalize = cvReadInt( find_timing_param( "normalize" ), 1 ) != 0;
1179 smooth_type = normalize ? "Blur" : "Blur_NoScale";
1180 sizes[INPUT][1] = aperture_size;
1181 types[INPUT][1] = CV_32FC1;
1182 if( !normalize && types[INPUT][0] == CV_8UC1 )
1183 types[OUTPUT][0] = CV_16SC1;
1187 void CV_BlurTest::run_func()
1189 cvSmooth( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
1190 test_array[OUTPUT][0], normalize ? CV_BLUR : CV_BLUR_NO_SCALE,
1191 aperture_size.width, aperture_size.height );
1195 int CV_BlurTest::prepare_test_case( int test_case_idx )
1197 int code = CV_SmoothBaseTest::prepare_test_case( test_case_idx );
1198 return code > 0 && !normalize && CV_MAT_CN(test_mat[INPUT][0].type) > 1 ? 0 : code;
1202 void CV_BlurTest::prepare_to_validation( int test_case_idx )
1204 CvMat* kernel = &test_mat[INPUT][1];
1205 CV_SmoothBaseTest::prepare_to_validation( test_case_idx );
1206 cvTsAdd( 0, cvScalarAll(0.), 0, cvScalarAll(0.),
1207 cvScalarAll(normalize ? 1./(kernel->rows*kernel->cols) : 1.), kernel, 0 );
1208 cvTsConvolve2D( &test_mat[TEMP][0], &test_mat[REF_OUTPUT][0], kernel, anchor );
1212 CV_BlurTest blur_test;
1215 /////////////// gaussian ///////////////
1217 class CV_GaussianBlurTest : public CV_SmoothBaseTest
1220 CV_GaussianBlurTest();
1223 void prepare_to_validation( int test_case_idx );
1225 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1226 double get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ );
1227 void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1228 CvSize** whole_sizes, bool *are_images );
1234 CV_GaussianBlurTest::CV_GaussianBlurTest() : CV_SmoothBaseTest( "filter-gaussian", "cvSmooth" )
1237 smooth_type = "Gaussian";
1241 double CV_GaussianBlurTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1243 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1244 return depth <= CV_8S ? 8 : 1e-5;
1248 void CV_GaussianBlurTest::get_test_array_types_and_sizes( int test_case_idx,
1249 CvSize** sizes, int** types )
1251 CvRNG* rng = ts->get_rng();
1252 int kernel_case = cvTsRandInt(rng) % 2;
1253 CV_SmoothBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1254 anchor = cvPoint(aperture_size.width/2,aperture_size.height/2);
1255 sizes[TEMP][0].width = sizes[INPUT][0].width + aperture_size.width - 1;
1256 sizes[TEMP][0].height = sizes[INPUT][0].height + aperture_size.height - 1;
1258 sigma = exp(cvTsRandReal(rng)*5-2);
1259 param1 = aperture_size.width;
1260 param2 = aperture_size.height;
1262 if( kernel_case == 0 )
1264 /*else if( kernel_case == 2 )
1266 int depth = CV_MAT_DEPTH(types[INPUT][0]);
1267 // !!! Copied from cvSmooth, if this formula is changed in cvSmooth,
1268 // make sure to update this one too.
1269 aperture_size.width = cvRound(sigma*(depth == CV_8U ? 3 : 4)*2 + 1)|1;
1270 aperture_size.width = MIN( aperture_size.width, 31 );
1271 aperture_size.height = aperture_size.width;
1272 anchor.x = aperture_size.width / 2;
1273 anchor.y = aperture_size.height / 2;
1274 sizes[INPUT][1] = aperture_size;
1275 sizes[TEMP][0].width = sizes[INPUT][0].width + aperture_size.width - 1;
1276 sizes[TEMP][0].height = sizes[INPUT][0].height + aperture_size.height - 1;
1277 param1 = aperture_size.width; param2 = aperture_size.height;
1282 void CV_GaussianBlurTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1283 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1285 CV_SmoothBaseTest::get_timing_test_array_types_and_sizes( test_case_idx,
1286 sizes, types, whole_sizes, are_images );
1287 param1 = aperture_size.width;
1288 param2 = aperture_size.height;
1292 void CV_GaussianBlurTest::run_func()
1294 cvSmooth( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
1295 test_array[OUTPUT][0], CV_GAUSSIAN, param1, param2, sigma );
1299 // !!! Copied from cvSmooth, if the code is changed in cvSmooth,
1300 // make sure to update this one too.
1301 #define SMALL_GAUSSIAN_SIZE 7
1303 icvCalcGaussianKernel( int n, double sigma, float* kernel )
1305 static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] =
1308 {0.25f, 0.5f, 0.25f},
1309 {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f},
1310 {0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125}
1313 if( n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 )
1316 memcpy( kernel, small_gaussian_tab[n>>1], n*sizeof(kernel[0]));
1320 double sigmaX = sigma > 0 ? sigma : (n/2 - 1)*0.3 + 0.8;
1321 double scale2X = -0.5/(sigmaX*sigmaX);
1324 sum = kernel[n/2] = 1.f;
1326 for( i = 1; i <= n/2; i++ )
1328 kernel[n/2+i] = kernel[n/2-i] = (float)exp(scale2X*i*i);
1329 sum += kernel[n/2+i]*2;
1333 for( i = 0; i <= n/2; i++ )
1334 kernel[n/2+i] = kernel[n/2-i] = (float)(kernel[n/2+i]*sum);
1339 static void cvTsCalcGaussianKernel2D( double sigma, CvMat* kernel )
1342 float* kx = (float*)alloca( kernel->cols*sizeof(kx[0]) );
1343 float* ky = (float*)alloca( kernel->rows*sizeof(ky[0]) );
1345 icvCalcGaussianKernel( kernel->cols, sigma, kx );
1346 icvCalcGaussianKernel( kernel->rows, sigma, ky );
1348 for( i = 0; i < kernel->rows; i++ )
1350 float* kdata = (float*)(kernel->data.ptr + i*kernel->step);
1351 for( j = 0; j < kernel->cols; j++ )
1352 kdata[j] = kx[j]*ky[i];
1357 void CV_GaussianBlurTest::prepare_to_validation( int test_case_idx )
1359 CvMat* kernel = &test_mat[INPUT][1];
1360 CV_SmoothBaseTest::prepare_to_validation( test_case_idx );
1361 cvTsCalcGaussianKernel2D( sigma, &test_mat[INPUT][1] );
1362 cvTsConvolve2D( &test_mat[TEMP][0], &test_mat[REF_OUTPUT][0], kernel, anchor );
1366 CV_GaussianBlurTest gaussianblur_test;
1369 /////////////// median ///////////////
1371 static const int smooth_median_depths[] = { CV_8U, -1 };
1373 class CV_MedianBlurTest : public CV_SmoothBaseTest
1376 CV_MedianBlurTest();
1379 void prepare_to_validation( int test_case_idx );
1380 double get_success_error_level( int test_case_idx, int i, int j );
1382 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1386 CV_MedianBlurTest::CV_MedianBlurTest() : CV_SmoothBaseTest( "filter-median", "cvSmooth" )
1388 test_array[TEMP].push(NULL);
1389 smooth_type = "Median";
1390 depth_list = smooth_median_depths;
1394 void CV_MedianBlurTest::get_test_array_types_and_sizes( int test_case_idx,
1395 CvSize** sizes, int** types )
1397 CV_SmoothBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1399 int cn = CV_MAT_CN(types[INPUT][0]);
1400 types[INPUT][0] = types[TEMP][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn);
1401 types[INPUT][1] = types[TEMP][0] = types[TEMP][1] = CV_MAKETYPE(depth,1);
1403 aperture_size.height = aperture_size.width;
1404 anchor.x = anchor.y = aperture_size.width / 2;
1405 sizes[INPUT][1] = cvSize(aperture_size.width,aperture_size.height);
1407 sizes[OUTPUT][0] = sizes[INPUT][0];
1408 sizes[REF_OUTPUT][0] = sizes[INPUT][0];
1410 sizes[TEMP][0].width = sizes[INPUT][0].width + aperture_size.width - 1;
1411 sizes[TEMP][0].height = sizes[INPUT][0].height + aperture_size.height - 1;
1413 sizes[TEMP][1] = cn > 1 ? sizes[INPUT][0] : cvSize(0,0);
1418 double CV_MedianBlurTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1424 void CV_MedianBlurTest::run_func()
1426 cvSmooth( test_array[INPUT][0], test_array[OUTPUT][0],
1427 CV_MEDIAN, aperture_size.width );
1436 median_pair( int _col, int _val ) : col(_col), val(_val) {};
1440 static void cvTsMedianFilter( const CvMat* src, CvMat* dst, int m )
1442 int i, j, k, l, m2 = m*m, n;
1443 int* col_buf = (int*)cvAlloc( (m+1)*sizeof(col_buf[0]));
1444 median_pair* buf0 = (median_pair*)cvAlloc( (m*m+1)*sizeof(buf0[0]));
1445 median_pair* buf1 = (median_pair*)cvAlloc( (m*m+1)*sizeof(buf1[0]));
1447 int step = src->step/CV_ELEM_SIZE(src->type);
1449 assert( src->rows == dst->rows + m - 1 && src->cols == dst->cols + m - 1 &&
1450 CV_ARE_TYPES_EQ(src,dst) && CV_MAT_TYPE(src->type) == CV_8UC1 );
1452 for( i = 0; i < dst->rows; i++ )
1454 uchar* dst1 = (uchar*)(dst->data.ptr + dst->step*i);
1455 for( k = 0; k < m; k++ )
1457 const uchar* src1 = (const uchar*)(src->data.ptr + (i+k)*src->step);
1458 for( j = 0; j < m-1; j++ )
1459 *buf0++ = median_pair(j, src1[j]);
1464 for( k = n-1; k > 0; k-- )
1467 for( j = 0; j < k; j++ )
1469 if( buf0[j].val > buf0[j+1].val )
1472 CV_SWAP( buf0[j], buf0[j+1], t );
1480 for( j = 0; j < dst->cols; j++ )
1482 int ins_col = j + m - 1;
1483 int del_col = j - 1;
1484 const uchar* src1 = (const uchar*)(src->data.ptr + src->step*i) + ins_col;
1485 for( k = 0; k < m; k++, src1 += step )
1487 col_buf[k] = src1[0];
1488 for( l = k-1; l >= 0; l-- )
1491 if( col_buf[l] < col_buf[l+1] )
1493 CV_SWAP( col_buf[l], col_buf[l+1], t );
1497 col_buf[m] = INT_MAX;
1499 for( k = 0, l = 0; k < n; )
1501 if( buf0[k].col == del_col )
1503 else if( buf0[k].val < col_buf[l] )
1504 *buf1++ = buf0[k++];
1507 assert( col_buf[l] < INT_MAX );
1508 *buf1++ = median_pair(ins_col,col_buf[l++]);
1513 *buf1++ = median_pair(ins_col,col_buf[l]);
1519 dst1[j] = (uchar)buf1[n/2].val;
1520 CV_SWAP( buf0, buf1, tbuf );
1530 void CV_MedianBlurTest::prepare_to_validation( int /*test_case_idx*/ )
1532 // CV_SmoothBaseTest::prepare_to_validation( test_case_idx );
1533 CvMat* src0 = &test_mat[INPUT][0];
1534 CvMat* dst0 = &test_mat[REF_OUTPUT][0];
1535 int i, cn = CV_MAT_CN(src0->type);
1536 CvMat* src = &test_mat[TEMP][0], *dst = dst0;
1538 dst = &test_mat[TEMP][1];
1540 for( i = 0; i < cn; i++ )
1545 cvTsExtract( src0, dst, i );
1548 cvTsPrepareToFilter( ptr, src, anchor, CV_TS_BORDER_REPLICATE );
1549 cvTsMedianFilter( src, dst, aperture_size.width );
1551 cvTsInsert( dst, dst0, i );
1556 CV_MedianBlurTest medianblur_test;
1559 /////////////// pyramid tests ///////////////
1561 static const char* pyramid_param_names[] = { "size", "channels", "depth", 0 };
1562 static int pyramid_channels[] = { 1, 3, -1 };
1564 class CV_PyramidBaseTest : public CV_FilterBaseTest
1567 CV_PyramidBaseTest( const char* test_name, const char* test_funcs, bool downsample );
1570 int prepare_test_case( int test_case_idx );
1571 double get_success_error_level( int test_case_idx, int i, int j );
1572 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1573 void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1574 CvSize** whole_sizes, bool *are_images );
1579 CV_PyramidBaseTest::CV_PyramidBaseTest( const char* test_name, const char* test_funcs, bool _downsample )
1580 : CV_FilterBaseTest( test_name, test_funcs, true ), downsample(_downsample)
1582 test_array[TEMP].push(NULL);
1583 size_list = filter_sizes;
1584 depth_list = smooth_depths;
1585 cn_list = pyramid_channels;
1586 default_timing_param_names = 0;
1587 if( strcmp( test_funcs, "" ) != 0 )
1589 default_timing_param_names = pyramid_param_names;
1597 double CV_PyramidBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1599 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1600 return depth <= CV_8S ? 1 : 1e-5;
1604 void CV_PyramidBaseTest::get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types )
1606 CvRNG* rng = ts->get_rng();
1608 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1610 int depth = cvTsRandInt(rng) % 2 ? CV_32F : CV_8U;
1611 int cn = cvTsRandInt(rng) & 1 ? 3 : 1;
1613 aperture_size = cvSize(5,5);
1614 anchor = cvPoint(aperture_size.width/2, aperture_size.height/2);
1616 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] =
1617 types[TEMP][0] = types[TEMP][1] = CV_MAKETYPE(depth, cn);
1619 sz.width = MAX( sizes[INPUT][0].width/2, 1 );
1620 sz.height = MAX( sizes[INPUT][0].height/2, 1 );
1624 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
1627 sizes[INPUT][0] = sizes[TEMP][1] = sz;
1631 sizes[INPUT][0] = sz;
1634 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
1635 sizes[TEMP][1] = cvSize(0,0);
1638 sizes[INPUT][1] = aperture_size;
1639 sizes[TEMP][0].width = sz.width + aperture_size.width - 1;
1640 sizes[TEMP][0].height = sz.height + aperture_size.height - 1;
1645 void CV_PyramidBaseTest::get_timing_test_array_types_and_sizes( int test_case_idx,
1646 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1648 CV_FilterBaseTest::get_timing_test_array_types_and_sizes( test_case_idx,
1649 sizes, types, whole_sizes, are_images );
1650 CvSize sz = sizes[INPUT][0];
1654 sizes[OUTPUT][0] = sz;
1656 sizes[INPUT][0] = sz;
1657 aperture_size.width = aperture_size.height = 5;
1658 anchor.x = anchor.y = aperture_size.width / 2;
1659 sizes[INPUT][1] = aperture_size;
1660 types[INPUT][1] = CV_32FC1;
1664 int CV_PyramidBaseTest::prepare_test_case( int test_case_idx )
1666 static const float kdata[] = { 1.f, 4.f, 6.f, 4.f, 1.f };
1668 double scale = 1./256;
1670 int code = CV_FilterBaseTest::prepare_test_case( test_case_idx );
1678 kernel = &test_mat[INPUT][1];
1680 for( i = 0; i < aperture_size.height; i++ )
1682 float* krow = (float*)(kernel->data.ptr + i*kernel->step);
1683 for( j = 0; j < aperture_size.width; j++ )
1684 krow[j] = (float)(scale*kdata[i]*kdata[j]);
1690 CV_PyramidBaseTest pyr_base( "pyramid", "", false );
1693 /////// pyrdown ////////
1695 static void cvTsDownsample( const CvMat* src, CvMat* dst )
1698 int elem_size = CV_ELEM_SIZE(src->type);
1699 int ncols = dst->cols*elem_size;
1700 int is_dword = elem_size % sizeof(int) == 0;
1704 elem_size /= sizeof(int);
1705 ncols /= sizeof(int);
1708 for( i = 0; i < dst->rows; i++ )
1710 const uchar* src_row = src->data.ptr + i*2*src->step;
1711 uchar* dst_row = dst->data.ptr + i*dst->step;
1715 for( j = 0; j < ncols; j += elem_size )
1717 for( k = 0; k < elem_size; k++ )
1718 dst_row[j+k] = src_row[j*2+k];
1723 for( j = 0; j < ncols; j += elem_size )
1725 for( k = 0; k < elem_size; k++ )
1726 ((int*)dst_row)[j+k] = ((const int*)src_row)[j*2+k];
1733 class CV_PyramidDownTest : public CV_PyramidBaseTest
1736 CV_PyramidDownTest();
1740 void prepare_to_validation( int );
1744 CV_PyramidDownTest::CV_PyramidDownTest()
1745 : CV_PyramidBaseTest( "pyramid-down", "cvPyrDown", true )
1750 void CV_PyramidDownTest::run_func()
1752 cvPyrDown( test_array[INPUT][0], test_array[OUTPUT][0], CV_GAUSSIAN_5x5 );
1756 void CV_PyramidDownTest::prepare_to_validation( int /*test_case_idx*/ )
1758 cvTsPrepareToFilter( &test_mat[INPUT][0], &test_mat[TEMP][0],
1759 anchor, CV_TS_BORDER_REFLECT );
1760 cvTsConvolve2D( &test_mat[TEMP][0], &test_mat[TEMP][1],
1761 &test_mat[INPUT][1], anchor );
1762 cvTsDownsample( &test_mat[TEMP][1], &test_mat[REF_OUTPUT][0] );
1766 CV_PyramidDownTest pyrdown;
1769 /////// pyrup ////////
1771 static void cvTsUpsample( const CvMat* src, CvMat* dst )
1774 int elem_size = CV_ELEM_SIZE(src->type);
1775 int ncols = src->cols*elem_size;
1776 int is_dword = elem_size % sizeof(int) == 0;
1780 elem_size /= sizeof(int);
1781 ncols /= sizeof(int);
1784 for( i = 0; i < src->rows; i++ )
1786 const uchar* src_row = src->data.ptr + i*src->step;
1787 uchar* dst_row = dst->data.ptr + i*2*dst->step;
1791 memset( dst_row + dst->step, 0, dst->cols*elem_size );
1792 for( j = 0; j < ncols; j += elem_size )
1794 for( k = 0; k < elem_size; k++ )
1796 dst_row[j*2+k] = src_row[j+k];
1797 dst_row[j*2+k+elem_size] = 0;
1803 memset( dst_row + dst->step, 0, dst->cols*elem_size*sizeof(int) );
1804 for( j = 0; j < ncols; j += elem_size )
1806 for( k = 0; k < elem_size; k++ )
1808 ((int*)dst_row)[j*2+k] = ((const int*)src_row)[j+k];
1809 ((int*)dst_row)[j*2+k+elem_size] = 0;
1817 class CV_PyramidUpTest : public CV_PyramidBaseTest
1824 void prepare_to_validation( int );
1828 CV_PyramidUpTest::CV_PyramidUpTest()
1829 : CV_PyramidBaseTest( "pyramid-up", "cvPyrUp", false )
1834 void CV_PyramidUpTest::run_func()
1836 cvPyrUp( test_array[INPUT][0], test_array[OUTPUT][0], CV_GAUSSIAN_5x5 );
1840 void CV_PyramidUpTest::prepare_to_validation( int /*test_case_idx*/ )
1844 cvTsUpsample( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0] );
1845 cvTsPrepareToFilter( &test_mat[REF_OUTPUT][0], &test_mat[TEMP][0],
1846 anchor, CV_TS_BORDER_REFLECT );
1847 cvTsConvolve2D( &test_mat[TEMP][0], &test_mat[REF_OUTPUT][0],
1848 &test_mat[INPUT][1], anchor );
1849 // currently IPP and OpenCV process right/bottom part of the image differently, so
1850 // we just patch the last two rows/columns to have consistent test results.
1851 sz = cvGetMatSize( &test_mat[REF_OUTPUT][0]);
1852 cvTsSelect( &test_mat[REF_OUTPUT][0], &src2, cvRect(sz.width-2,0,2,sz.height) );
1853 cvTsSelect( &test_mat[OUTPUT][0], &dst2, cvRect(sz.width-2,0,2,sz.height) );
1854 cvTsCopy( &src2, &dst2, 0 );
1855 cvTsSelect( &test_mat[REF_OUTPUT][0], &src2, cvRect(0,sz.height-2,sz.width,2) );
1856 cvTsSelect( &test_mat[OUTPUT][0], &dst2, cvRect(0,sz.height-2,sz.width,2) );
1857 cvTsCopy( &src2, &dst2, 0 );
1861 CV_PyramidUpTest pyrup;
1865 //////////////////////// feature selection //////////////////////////
1867 static const char* featuresel_param_names[] = { "block_size", "aperture", "size", "depth", 0 };
1868 static const int featuresel_block_size[] = { 3, 5, 11 };
1870 class CV_FeatureSelBaseTestImpl : public CvArrTest
1873 CV_FeatureSelBaseTestImpl( const char* test_name, const char* test_funcs, int width_factor );
1876 int read_params( CvFileStorage* fs );
1877 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
1878 void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
1879 double get_success_error_level( int test_case_idx, int i, int j );
1880 int write_default_params(CvFileStorage* fs);
1881 void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
1882 CvSize** whole_sizes, bool *are_images );
1883 void print_timing_params( int test_case_idx, char* ptr, int params_left );
1884 int aperture_size, block_size;
1885 int max_aperture_size;
1891 CV_FeatureSelBaseTestImpl::CV_FeatureSelBaseTestImpl( const char* test_name, const char* test_funcs, int _width_factor )
1892 : CvArrTest( test_name, test_funcs, "" )
1894 max_aperture_size = 7;
1895 max_block_size = 21;
1896 // 1 input, 1 output, temp arrays are allocated in the reference functions
1897 test_array[INPUT].push(NULL);
1898 test_array[OUTPUT].push(NULL);
1899 test_array[REF_OUTPUT].push(NULL);
1900 element_wise_relative_error = false;
1901 width_factor = _width_factor;
1903 size_list = filter_sizes;
1904 whole_size_list = filter_whole_sizes;
1905 depth_list = morph_depths;
1910 int CV_FeatureSelBaseTestImpl::read_params( CvFileStorage* fs )
1912 int code = CvTest::read_params( fs );
1916 if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1918 max_aperture_size = cvReadInt( find_param( fs, "max_aperture_size" ), max_aperture_size );
1919 max_aperture_size = cvTsClipInt( max_aperture_size, 1, 9 );
1920 max_block_size = cvReadInt( find_param( fs, "max_block_size" ), max_block_size );
1921 max_block_size = cvTsClipInt( max_aperture_size, 1, 100 );
1928 int CV_FeatureSelBaseTestImpl::write_default_params( CvFileStorage* fs )
1930 int code = CvArrTest::write_default_params( fs );
1934 if( ts->get_testing_mode() == CvTS::CORRECTNESS_CHECK_MODE )
1936 write_param( fs, "max_aperture_size", max_aperture_size );
1937 write_param( fs, "max_block_size", max_block_size );
1939 else if( ts->get_testing_mode() == CvTS::TIMING_MODE && strcmp( tested_functions, "" ) == 0 )
1941 start_write_param( fs );
1942 write_int_list( fs, "aperture", sobel_aperture, CV_DIM(sobel_aperture) );
1943 write_int_list( fs, "block_size", featuresel_block_size, CV_DIM(featuresel_block_size) );
1950 double CV_FeatureSelBaseTestImpl::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1952 int depth = CV_MAT_DEPTH(test_mat[INPUT][0].type);
1953 return depth <= CV_8S ? 3e-2 : depth == CV_32F ? 1e-3 : 1e-10;
1957 void CV_FeatureSelBaseTestImpl::get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high )
1959 CvArrTest::get_minmax_bounds( i, j, type, low, high );
1960 if( i == INPUT && CV_MAT_DEPTH(type) == CV_32F )
1962 *low = cvScalarAll(-10.);
1963 *high = cvScalarAll(10.);
1968 void CV_FeatureSelBaseTestImpl::get_test_array_types_and_sizes( int test_case_idx,
1969 CvSize** sizes, int** types )
1971 CvRNG* rng = ts->get_rng();
1972 CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1973 int depth = cvTsRandInt(rng) % 2, asz;
1975 depth = depth == 0 ? CV_8U : CV_32F;
1976 types[INPUT][0] = depth;
1977 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_32FC1;
1979 aperture_size = (cvTsRandInt(rng) % (max_aperture_size+2) - 1) | 1;
1980 if( aperture_size == 1 )
1982 if( depth == CV_8U )
1983 aperture_size = MIN( aperture_size, 5 );
1984 block_size = (cvTsRandInt(rng) % max_block_size + 1) | 1;
1985 if( block_size <= 3 )
1987 asz = aperture_size > 0 ? aperture_size : 3;
1989 sizes[INPUT][0].width = MAX( sizes[INPUT][0].width, asz + block_size );
1990 sizes[INPUT][0].height = MAX( sizes[INPUT][0].height, asz + block_size );
1991 sizes[OUTPUT][0].height = sizes[REF_OUTPUT][0].height = sizes[INPUT][0].height;
1992 sizes[OUTPUT][0].width = sizes[REF_OUTPUT][0].width = sizes[INPUT][0].width*width_factor;
1996 void CV_FeatureSelBaseTestImpl::get_timing_test_array_types_and_sizes( int test_case_idx,
1997 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
1999 CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
2000 whole_sizes, are_images );
2001 aperture_size = cvReadInt( find_timing_param( "aperture" ), 3 );
2002 block_size = cvReadInt( find_timing_param( "block_size" ), 0 );
2003 int asz = aperture_size < 0 ? 3 : aperture_size;
2005 sizes[INPUT][0].width = MAX( sizes[INPUT][0].width, asz + block_size );
2006 sizes[INPUT][0].height = MAX( sizes[INPUT][0].height, asz + block_size );
2007 whole_sizes[INPUT][0].width = MAX( whole_sizes[INPUT][0].width, asz + block_size );
2008 whole_sizes[INPUT][0].height = MAX( whole_sizes[INPUT][0].height, asz + block_size );
2009 sizes[OUTPUT][0].height = sizes[INPUT][0].height;
2010 sizes[OUTPUT][0].width = sizes[INPUT][0].width*width_factor;
2011 whole_sizes[OUTPUT][0].height = whole_sizes[INPUT][0].height;
2012 whole_sizes[OUTPUT][0].width = MAX(whole_sizes[OUTPUT][0].width,sizes[OUTPUT][0].width);
2013 types[OUTPUT][0] = CV_32FC1;
2017 void CV_FeatureSelBaseTestImpl::print_timing_params( int test_case_idx, char* ptr, int params_left )
2019 int asz = aperture_size < 0 ? 3 : aperture_size;
2020 sprintf( ptr, "%s(%dx%d),", aperture_size < 0 ? "Scharr" : "Sobel", asz, asz );
2023 if( block_size > 0 )
2025 sprintf( ptr, "block_size=%dx%d,", block_size, block_size );
2030 CvArrTest::print_timing_params( test_case_idx, ptr, params_left );
2034 CV_FeatureSelBaseTestImpl featuresel_base( "features", "", 0 );
2038 class CV_FeatureSelBaseTest : public CV_FeatureSelBaseTestImpl
2041 CV_FeatureSelBaseTest( const char* test_name, const char* test_funcs, int width_factor );
2045 CV_FeatureSelBaseTest::CV_FeatureSelBaseTest( const char* test_name, const char* test_funcs, int _width_factor )
2046 : CV_FeatureSelBaseTestImpl( test_name, test_funcs, _width_factor )
2049 size_list = whole_size_list = 0;
2050 default_timing_param_names = featuresel_param_names;
2055 cvTsCornerEigenValsVecs( const CvMat* _src, CvMat* eigenv, CvMat* ocv_eigenv,
2056 int block_size, int _aperture_size, int mode )
2058 CvMat *dx2 = 0, *dxdy = 0, *dy2 = 0;
2059 CvMat* kernel = 0, *src2 = 0;
2060 const CvMat* src = _src;
2065 CV_FUNCNAME( "cvTsCornerEigenValsVecs" );
2070 int aperture_size = _aperture_size < 0 ? 3 : _aperture_size;
2071 CvPoint anchor = { aperture_size/2, aperture_size/2 };
2073 assert( (CV_MAT_TYPE(src->type) == CV_8UC1 ||
2074 CV_MAT_TYPE(src->type) == CV_32FC1) &&
2075 CV_MAT_TYPE(eigenv->type) == CV_32FC1 );
2077 assert( src->rows == eigenv->rows &&
2078 ((mode > 0 && src->cols == eigenv->cols) ||
2079 (mode == 0 && src->cols*6 == eigenv->cols)) );
2081 type = CV_MAT_TYPE(src->type);
2084 CV_CALL( dx2 = cvCreateMat( src->rows, src->cols, ftype ));
2085 CV_CALL( dy2 = cvCreateMat( src->rows, src->cols, ftype ));
2086 CV_CALL( dxdy = cvCreateMat( src->rows, src->cols, ftype ));
2088 CV_CALL( kernel = cvCreateMat( aperture_size, aperture_size, CV_32FC1 ));
2089 CV_CALL( src2 = cvCreateMat( src->rows + aperture_size - 1,
2090 src->cols + aperture_size - 1, ftype ));
2094 cvTsAdd( src, cvScalarAll(1./255), 0, cvScalarAll(0.), cvScalarAll(0.), dx2, 0 );
2098 cvTsPrepareToFilter( src, src2, anchor, CV_TS_BORDER_REPLICATE );
2099 cvTsCalcSobelKernel2D( 1, 0, _aperture_size, 0, kernel );
2100 cvTsConvolve2D( src2, dx2, kernel, anchor );
2101 cvTsCalcSobelKernel2D( 0, 1, _aperture_size, 0, kernel );
2102 cvTsConvolve2D( src2, dy2, kernel, anchor );
2103 cvReleaseMat( &src2 );
2104 cvReleaseMat( &kernel );
2106 denom = (1 << (aperture_size-1))*block_size;
2107 denom = denom * denom;
2108 if( _aperture_size < 0 )
2112 for( i = 0; i < src->rows; i++ )
2114 float* dxdyp = (float*)(dxdy->data.ptr + i*dxdy->step);
2115 float* dx2p = (float*)(dx2->data.ptr + i*dx2->step);
2116 float* dy2p = (float*)(dy2->data.ptr + i*dy2->step);
2118 for( j = 0; j < src->cols; j++ )
2120 double xval = dx2p[j], yval = dy2p[j];
2121 dxdyp[j] = (float)(xval*yval*denom);
2122 dx2p[j] = (float)(xval*xval*denom);
2123 dy2p[j] = (float)(yval*yval*denom);
2127 CV_CALL( src2 = cvCreateMat( src->rows + block_size - 1, src->cols + block_size - 1, CV_32F ));
2128 CV_CALL( kernel = cvCreateMat( block_size, block_size, CV_32F ));
2129 cvTsAdd( 0, cvScalarAll(0), 0, cvScalarAll(0), cvScalarAll(1./*(block_size*block_size)*/), kernel, 0 );
2130 anchor = cvPoint( block_size/2, block_size/2 );
2132 cvTsPrepareToFilter( dx2, src2, anchor, CV_TS_BORDER_REPLICATE );
2133 cvTsConvolve2D( src2, dx2, kernel, anchor );
2134 cvTsPrepareToFilter( dy2, src2, anchor, CV_TS_BORDER_REPLICATE );
2135 cvTsConvolve2D( src2, dy2, kernel, anchor );
2136 cvTsPrepareToFilter( dxdy, src2, anchor, CV_TS_BORDER_REPLICATE );
2137 cvTsConvolve2D( src2, dxdy, kernel, anchor );
2141 for( i = 0; i < src->rows; i++ )
2143 float* eigenvp = (float*)(eigenv->data.ptr + i*eigenv->step);
2144 float* ocv_eigenvp = (float*)(ocv_eigenv->data.ptr + i*ocv_eigenv->step);
2145 const float* dxdyp = (float*)(dxdy->data.ptr + i*dxdy->step);
2146 const float* dx2p = (float*)(dx2->data.ptr + i*dx2->step);
2147 const float* dy2p = (float*)(dy2->data.ptr + i*dy2->step);
2149 for( j = 0; j < src->cols; j++ )
2151 double a = dx2p[j], b = dxdyp[j], c = dy2p[j];
2152 double d = sqrt((a-c)*(a-c) + 4*b*b);
2153 double l1 = 0.5*(a + c + d);
2154 double l2 = 0.5*(a + c - d);
2155 double x1, y1, x2, y2, s;
2157 if( fabs(a - l1) + fabs(b) >= 1e-3 )
2158 x1 = b, y1 = l1 - a;
2160 x1 = l1 - c, y1 = b;
2161 s = 1./(sqrt(x1*x1+y1*y1)+DBL_EPSILON);
2164 if( fabs(a - l2) + fabs(b) >= 1e-3 )
2165 x2 = b, y2 = l2 - a;
2167 x2 = l2 - c, y2 = b;
2168 s = 1./(sqrt(x2*x2+y2*y2)+DBL_EPSILON);
2171 /* the orientation of eigen vectors might be inversed relative to OpenCV function,
2173 if( (fabs(x1) >= fabs(y1) && ocv_eigenvp[j*6+2]*x1 < 0) ||
2174 (fabs(x1) < fabs(y1) && ocv_eigenvp[j*6+3]*y1 < 0) )
2177 if( (fabs(x2) >= fabs(y2) && ocv_eigenvp[j*6+4]*x2 < 0) ||
2178 (fabs(x2) < fabs(y2) && ocv_eigenvp[j*6+5]*y2 < 0) )
2181 eigenvp[j*6] = (float)l1;
2182 eigenvp[j*6+1] = (float)l2;
2183 eigenvp[j*6+2] = (float)x1;
2184 eigenvp[j*6+3] = (float)y1;
2185 eigenvp[j*6+4] = (float)x2;
2186 eigenvp[j*6+5] = (float)y2;
2190 else if( mode == 1 )
2192 for( i = 0; i < src->rows; i++ )
2194 float* eigenvp = (float*)(eigenv->data.ptr + i*eigenv->step);
2195 const float* dxdyp = (float*)(dxdy->data.ptr + i*dxdy->step);
2196 const float* dx2p = (float*)(dx2->data.ptr + i*dx2->step);
2197 const float* dy2p = (float*)(dy2->data.ptr + i*dy2->step);
2199 for( j = 0; j < src->cols; j++ )
2201 double a = dx2p[j], b = dxdyp[j], c = dy2p[j];
2202 double d = sqrt((a-c)*(a-c) + 4*b*b);
2203 eigenvp[j] = (float)(0.5*(a + c - d));
2210 cvReleaseMat( &dx2 );
2211 cvReleaseMat( &dy2 );
2212 cvReleaseMat( &dxdy );
2213 cvReleaseMat( &src2 );
2214 cvReleaseMat( &kernel );
2219 class CV_MinEigenValTest : public CV_FeatureSelBaseTest
2222 CV_MinEigenValTest();
2226 void prepare_to_validation( int );
2230 CV_MinEigenValTest::CV_MinEigenValTest()
2231 : CV_FeatureSelBaseTest( "features-mineval", "cvCornerMinEigenVal", 1 )
2236 void CV_MinEigenValTest::run_func()
2238 cvCornerMinEigenVal( test_array[INPUT][0], test_array[OUTPUT][0],
2239 block_size, aperture_size );
2243 void CV_MinEigenValTest::prepare_to_validation( int /*test_case_idx*/ )
2245 cvTsCornerEigenValsVecs( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0],
2246 &test_mat[OUTPUT][0], block_size, aperture_size, 1 );
2250 CV_MinEigenValTest features_mineval;
2253 // eigenval's & vec's
2254 class CV_EigenValVecTest : public CV_FeatureSelBaseTest
2257 CV_EigenValVecTest();
2261 void prepare_to_validation( int );
2265 CV_EigenValVecTest::CV_EigenValVecTest()
2266 : CV_FeatureSelBaseTest( "features-evalvec", "cvCornerEigenValsAndVecs", 6 )
2271 void CV_EigenValVecTest::run_func()
2273 cvCornerEigenValsAndVecs( test_array[INPUT][0], test_array[OUTPUT][0],
2274 block_size, aperture_size );
2278 void CV_EigenValVecTest::prepare_to_validation( int /*test_case_idx*/ )
2280 cvTsCornerEigenValsVecs( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0],
2281 &test_mat[OUTPUT][0], block_size, aperture_size, 0 );
2285 CV_EigenValVecTest features_evalvec;
2289 static const char* precorner_param_names[] = { "aperture", "size", "depth", 0 };
2290 static const int precorner_aperture[] = { 3, 5, 7 };
2293 class CV_PreCornerDetectTest : public CV_FeatureSelBaseTest
2296 CV_PreCornerDetectTest();
2300 void prepare_to_validation( int );
2301 int prepare_test_case( int );
2302 int write_default_params(CvFileStorage* fs);
2306 CV_PreCornerDetectTest::CV_PreCornerDetectTest()
2307 : CV_FeatureSelBaseTest( "features-precorner", "cvPreCornerDetect", 1 )
2309 default_timing_param_names = precorner_param_names;
2313 int CV_PreCornerDetectTest::write_default_params( CvFileStorage* fs )
2315 int code = CV_FeatureSelBaseTest::write_default_params( fs );
2319 if( ts->get_testing_mode() == CvTS::TIMING_MODE )
2321 start_write_param( fs );
2322 write_int_list( fs, "aperture", precorner_aperture, CV_DIM(precorner_aperture) );
2329 void CV_PreCornerDetectTest::run_func()
2331 cvPreCornerDetect( test_array[INPUT][0], test_array[OUTPUT][0], aperture_size );
2335 int CV_PreCornerDetectTest::prepare_test_case( int test_case_idx )
2337 int code = CV_FeatureSelBaseTest::prepare_test_case( test_case_idx );
2338 if( aperture_size < 0 )
2344 void CV_PreCornerDetectTest::prepare_to_validation( int /*test_case_idx*/ )
2346 /*cvTsCornerEigenValsVecs( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0],
2347 block_size, aperture_size, 0 );*/
2348 const CvMat* src = &test_mat[INPUT][0];
2349 CvMat* dst = &test_mat[REF_OUTPUT][0];
2351 int type = CV_MAT_TYPE(src->type), ftype = CV_32FC1;
2352 CvPoint anchor = { aperture_size/2, aperture_size/2 };
2356 CvMat* dx = cvCreateMat( src->rows, src->cols, ftype );
2357 CvMat* dy = cvCreateMat( src->rows, src->cols, ftype );
2358 CvMat* d2x = cvCreateMat( src->rows, src->cols, ftype );
2359 CvMat* d2y = cvCreateMat( src->rows, src->cols, ftype );
2360 CvMat* dxy = cvCreateMat( src->rows, src->cols, ftype );
2361 CvMat* tmp = cvCreateMat( src->rows + aperture_size - 1,
2362 src->cols + aperture_size - 1, ftype );
2363 CvMat* kernel = cvCreateMat( aperture_size, aperture_size, ftype );
2367 cvTsAdd( src, cvScalarAll(1./255), 0, cvScalarAll(0.), cvScalarAll(0.), dx, 0 );
2371 cvTsPrepareToFilter( src, tmp, anchor, CV_TS_BORDER_REPLICATE );
2373 cvTsCalcSobelKernel2D( 1, 0, aperture_size, 0, kernel );
2374 cvTsConvolve2D( tmp, dx, kernel, anchor );
2375 cvTsCalcSobelKernel2D( 0, 1, aperture_size, 0, kernel );
2376 cvTsConvolve2D( tmp, dy, kernel, anchor );
2377 cvTsCalcSobelKernel2D( 2, 0, aperture_size, 0, kernel );
2378 cvTsConvolve2D( tmp, d2x, kernel, anchor );
2379 cvTsCalcSobelKernel2D( 0, 2, aperture_size, 0, kernel );
2380 cvTsConvolve2D( tmp, d2y, kernel, anchor );
2381 cvTsCalcSobelKernel2D( 1, 1, aperture_size, 0, kernel );
2382 cvTsConvolve2D( tmp, dxy, kernel, anchor );
2384 denom = 1 << (aperture_size-1);
2385 denom = denom * denom * denom;
2388 for( i = 0; i < src->rows; i++ )
2390 const float* _dx = (const float*)(dx->data.ptr + i*dx->step);
2391 const float* _dy = (const float*)(dy->data.ptr + i*dy->step);
2392 const float* _d2x = (const float*)(d2x->data.ptr + i*d2x->step);
2393 const float* _d2y = (const float*)(d2y->data.ptr + i*d2y->step);
2394 const float* _dxy = (const float*)(dxy->data.ptr + i*dxy->step);
2395 float* corner = (float*)(dst->data.ptr + i*dst->step);
2397 for( j = 0; j < src->cols; j++ )
2402 corner[j] = (float)(denom*(x*x*_d2y[j] + y*y*_d2x[j] - 2*x*y*_dxy[j]));
2406 cvReleaseMat( &dx );
2407 cvReleaseMat( &dy );
2408 cvReleaseMat( &d2x );
2409 cvReleaseMat( &d2y );
2410 cvReleaseMat( &dxy );
2411 cvReleaseMat( &tmp );
2412 cvReleaseMat( &kernel );
2416 CV_PreCornerDetectTest precorner;
2419 ///////// integral /////////
2421 static const char* integral_param_names[] = { "output", "size", "channels", "sum_depth", "depth", 0 };
2422 static const int integral_sum_depth[] = { CV_32S, CV_64F, -1 };
2423 static const int integral_block_size[] = { 3, 5, 11 };
2424 static const char* integral_output[] = { "sum", "sum+sqsum", "all", 0 };
2426 class CV_IntegralTest : public CvArrTest
2432 void get_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types );
2433 void get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high );
2434 double get_success_error_level( int test_case_idx, int i, int j );
2436 void prepare_to_validation( int );
2438 int prepare_test_case( int test_case_idx );
2439 int write_default_params(CvFileStorage* fs);
2440 void get_timing_test_array_types_and_sizes( int test_case_idx, CvSize** sizes, int** types,
2441 CvSize** whole_sizes, bool *are_images );
2442 void print_timing_params( int test_case_idx, char* ptr, int params_left );
2446 CV_IntegralTest::CV_IntegralTest()
2447 : CvArrTest( "integral", "cvIntegral", "" )
2449 test_array[INPUT].push(NULL);
2450 test_array[OUTPUT].push(NULL);
2451 test_array[OUTPUT].push(NULL);
2452 test_array[OUTPUT].push(NULL);
2453 test_array[REF_OUTPUT].push(NULL);
2454 test_array[REF_OUTPUT].push(NULL);
2455 test_array[REF_OUTPUT].push(NULL);
2456 test_array[TEMP].push(NULL);
2457 test_array[TEMP].push(NULL);
2458 test_array[TEMP].push(NULL);
2459 test_array[TEMP].push(NULL);
2460 test_array[TEMP].push(NULL);
2461 element_wise_relative_error = false;
2463 size_list = filter_sizes;
2464 whole_size_list = filter_whole_sizes;
2465 default_timing_param_names = integral_param_names;
2466 depth_list = morph_depths;
2467 cn_list = filter_channels;
2471 void CV_IntegralTest::get_minmax_bounds( int i, int j, int type, CvScalar* low, CvScalar* high )
2473 CvArrTest::get_minmax_bounds( i, j, type, low, high );
2474 int depth = CV_MAT_DEPTH(type);
2475 if( depth == CV_32F )
2477 *low = cvScalarAll(-10.);
2478 *high = cvScalarAll(10.);
2483 int CV_IntegralTest::write_default_params( CvFileStorage* fs )
2485 int code = CvArrTest::write_default_params( fs );
2489 if( ts->get_testing_mode() == CvTS::TIMING_MODE )
2492 start_write_param( fs );
2494 cvStartWriteStruct( fs, "sum_depth", CV_NODE_SEQ+CV_NODE_FLOW );
2495 for( i = 0; integral_sum_depth[i] >= 0; i++ )
2496 cvWriteString( fs, 0, cvTsGetTypeName(integral_sum_depth[i]) );
2497 cvEndWriteStruct(fs);
2499 write_string_list( fs, "output", integral_output );
2506 void CV_IntegralTest::get_test_array_types_and_sizes( int test_case_idx,
2507 CvSize** sizes, int** types )
2509 CvRNG* rng = ts->get_rng();
2510 int depth = cvTsRandInt(rng) % 2, sum_depth;
2511 int cn = cvTsRandInt(rng) % 3 + 1;
2512 CvArrTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
2515 depth = depth == 0 ? CV_8U : CV_32F;
2517 sum_depth = depth == CV_8U && (cvTsRandInt(rng) & 1) == 1 ? CV_32S : CV_64F;
2519 //sizes[INPUT][0].width = 1;
2521 types[INPUT][0] = CV_MAKETYPE(depth,cn);
2522 types[OUTPUT][0] = types[REF_OUTPUT][0] =
2523 types[OUTPUT][2] = types[REF_OUTPUT][2] = CV_MAKETYPE(sum_depth, cn);
2524 types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_MAKETYPE(CV_64F, cn);
2526 sum_size.width = sizes[INPUT][0].width + 1;
2527 sum_size.height = sizes[INPUT][0].height + 1;
2529 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sum_size;
2530 sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] =
2531 sizes[OUTPUT][2] = sizes[REF_OUTPUT][2] = cvSize(0,0);
2533 if( cvTsRandInt(rng) % 3 > 0 )
2535 sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = sum_size;
2536 if( cvTsRandInt(rng) % 2 > 0 )
2537 sizes[REF_OUTPUT][2] = sizes[OUTPUT][2] = sum_size;
2540 types[TEMP][0] = CV_MAKETYPE(depth,1);
2541 types[TEMP][1] = CV_MAKETYPE(CV_32F,1);
2542 types[TEMP][2] = types[TEMP][3] = types[TEMP][4] = CV_MAKETYPE(CV_64F,1);
2544 sizes[TEMP][0] = cn > 1 ? sizes[INPUT][0] : cvSize(0,0);
2545 sizes[TEMP][1] = depth == CV_8U ? sum_size : cvSize(0,0);
2547 sizes[TEMP][2] = cn > 1 || sum_depth == CV_32S ? sizes[OUTPUT][0] : cvSize(0,0);
2548 sizes[TEMP][3] = cn > 1 ? sizes[OUTPUT][1] : cvSize(0,0);
2549 sizes[TEMP][4] = cn > 1 || sum_depth == CV_32S ? sizes[OUTPUT][2] : cvSize(0,0);
2553 double CV_IntegralTest::get_success_error_level( int /*test_case_idx*/, int i, int j )
2555 int depth = CV_MAT_DEPTH(test_mat[i][j].type);
2556 return depth == CV_32S ? 0 : FLT_EPSILON;
2560 void CV_IntegralTest::get_timing_test_array_types_and_sizes( int test_case_idx,
2561 CvSize** sizes, int** types, CvSize** whole_sizes, bool *are_images )
2563 CvArrTest::get_timing_test_array_types_and_sizes( test_case_idx, sizes, types,
2564 whole_sizes, are_images );
2565 const char* output = cvReadString( find_timing_param( "output" ), "sum" );
2566 CvSize sum_size = { sizes[INPUT][0].width + 1, sizes[INPUT][0].height + 1 };
2567 const char* _sum_depth = cvReadString( find_timing_param( "sum_depth" ), "64f" );
2568 int cn = CV_MAT_CN(types[INPUT][0]);
2569 int sum_depth = strcmp( _sum_depth, "32s" ) == 0 ? CV_32S : CV_64F;
2571 sizes[OUTPUT][0] = sizes[OUTPUT][1] = sizes[OUTPUT][2] = cvSize(0,0);
2572 whole_sizes[OUTPUT][0] = whole_sizes[OUTPUT][1] = whole_sizes[OUTPUT][2] = cvSize(0,0);
2574 if( strcmp( output, "sum" ) == 0 )
2575 sizes[OUTPUT][0] = whole_sizes[OUTPUT][0] = sum_size;
2576 else if( strcmp( output, "all" ) == 0 )
2577 sizes[OUTPUT][0] = sizes[OUTPUT][1] = sizes[OUTPUT][2] =
2578 whole_sizes[OUTPUT][0] = whole_sizes[OUTPUT][1] = whole_sizes[OUTPUT][2] = sum_size;
2580 sizes[OUTPUT][0] = sizes[OUTPUT][1] =
2581 whole_sizes[OUTPUT][0] = whole_sizes[OUTPUT][1] = sum_size;
2583 sizes[TEMP][0] = sizes[TEMP][1] = sizes[TEMP][2] = sizes[TEMP][3] = sizes[TEMP][4] = cvSize(0,0);
2585 types[OUTPUT][0] = types[OUTPUT][2] = CV_MAKETYPE( sum_depth, cn );
2586 types[OUTPUT][1] = CV_MAKETYPE( CV_64F, cn );
2590 void CV_IntegralTest::print_timing_params( int test_case_idx, char* ptr, int params_left )
2592 sprintf( ptr, "%s,", cvReadString( find_timing_param( "output" ), "sum" ) );
2596 CvArrTest::print_timing_params( test_case_idx, ptr, params_left );
2600 int CV_IntegralTest::prepare_test_case( int test_case_idx )
2602 int code = CvArrTest::prepare_test_case( test_case_idx );
2603 return code > 0 && ((test_array[OUTPUT][2] && CV_MAT_CN(test_mat[OUTPUT][2].type) > 1) ||
2604 CV_MAT_DEPTH(test_mat[OUTPUT][0].type) < CV_MAT_DEPTH(test_mat[INPUT][0].type)) ? 0 : code;
2608 void CV_IntegralTest::run_func()
2610 cvIntegral( test_array[INPUT][0], test_array[OUTPUT][0],
2611 test_array[OUTPUT][1], test_array[OUTPUT][2] );
2616 cvTsIntegral( const CvMat* img, const CvMat* sum, const CvMat* sqsum, const CvMat* tilted )
2618 const float* data = img->data.fl;
2619 double* sdata = sum->data.db;
2620 double* sqdata = sqsum ? sqsum->data.db : 0;
2621 double* tdata = tilted ? tilted->data.db : 0;
2622 int step = img->step/sizeof(data[0]);
2623 int sstep = sum->step/sizeof(sdata[0]);
2624 int sqstep = sqsum ? sqsum->step/sizeof(sqdata[0]) : 0;
2625 int tstep = tilted ? tilted->step/sizeof(tdata[0]) : 0;
2626 CvSize size = cvGetMatSize( img );
2628 memset( sdata, 0, (size.width+1)*sizeof(sdata[0]) );
2630 memset( sqdata, 0, (size.width+1)*sizeof(sqdata[0]) );
2632 memset( tdata, 0, (size.width+1)*sizeof(tdata[0]) );
2634 for( ; size.height--; data += step )
2636 double s = 0, sq = 0;
2642 for( x = 0; x <= size.width; x++ )
2644 double t = x > 0 ? data[x-1] : 0, ts = t;
2648 sdata[x] = s + sdata[x - sstep];
2650 sqdata[x] = sq + sqdata[x - sqstep];
2656 ts += tdata[-tstep+1];
2659 ts += tdata[x-tstep-1];
2660 if( data > img->data.fl )
2662 ts += data[x-step-1];
2663 if( x < size.width )
2664 ts += tdata[x-tstep+1] - tdata[x-tstep*2];
2674 void CV_IntegralTest::prepare_to_validation( int /*test_case_idx*/ )
2676 CvMat* src0 = &test_mat[INPUT][0];
2677 int i, cn = CV_MAT_CN(src0->type), depth = CV_MAT_DEPTH(src0->type);
2678 CvMat* plane = cn > 1 ? &test_mat[TEMP][0] : 0;
2679 CvMat ibuf, *plane32f = 0;
2681 CvMat* sum0 = &test_mat[REF_OUTPUT][0];
2682 CvMat* sqsum0 = test_array[REF_OUTPUT][1] ? &test_mat[REF_OUTPUT][1] : 0;
2683 CvMat* tsum0 = test_array[REF_OUTPUT][2] ? &test_mat[REF_OUTPUT][2] : 0;
2685 CvMat* sum1 = test_array[TEMP][2] ? &test_mat[TEMP][2] : sum0;
2686 CvMat* sqsum1 = test_array[TEMP][3] ? &test_mat[TEMP][3] : sqsum0;
2687 CvMat* tsum1 = test_array[TEMP][4] ? &test_mat[TEMP][4] : tsum0;
2688 CvMat buf, *ptr = 0;
2690 if( depth == CV_8U )
2692 ibuf = test_mat[TEMP][1];
2696 plane32f->type &= ~CV_MAT_CONT_FLAG;
2698 if( CV_MAT_DEPTH(sum0->type) == CV_32S && cn > 1 )
2700 // in case of 8u->32s integral transform aliase the temporary output buffer with temporary input buffer
2701 buf = test_mat[TEMP][1];
2703 ptr->type = (ptr->type & ~CV_MAT_DEPTH_MASK) | CV_32S;
2707 for( i = 0; i < cn; i++ )
2713 cvTsExtract( sptr, plane, i );
2717 if( CV_MAT_DEPTH(sptr->type) != CV_32F )
2719 cvTsConvert( sptr, plane32f );
2723 cvTsIntegral( sptr, sum1, sqsum1, tsum1 );
2729 cvTsConvert( dptr, ptr );
2733 cvTsConvert( dptr, sum0 );
2735 cvTsInsert( dptr, sum0, i );
2738 if( tsum1 != tsum0 )
2743 cvTsConvert( dptr, ptr );
2747 cvTsConvert( dptr, tsum0 );
2749 cvTsInsert( dptr, tsum0, i );
2752 if( sqsum1 != sqsum0 )
2753 cvTsInsert( sqsum1, sqsum0, i );
2758 CV_IntegralTest integral_test;