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.
42 #include "test_precomp.hpp"
47 class CV_FilterBaseTest : public cvtest::ArrayTest
50 CV_FilterBaseTest( bool _fp_kernel );
53 int prepare_test_case( int test_case_idx );
54 int read_params( CvFileStorage* fs );
55 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
56 void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
59 int max_aperture_size;
66 CV_FilterBaseTest::CV_FilterBaseTest( bool _fp_kernel ) : fp_kernel(_fp_kernel)
68 test_array[INPUT].push_back(NULL);
69 test_array[INPUT].push_back(NULL);
70 test_array[OUTPUT].push_back(NULL);
71 test_array[REF_OUTPUT].push_back(NULL);
72 max_aperture_size = 13;
74 aperture_size = cvSize(0,0);
75 anchor = cvPoint(0,0);
76 element_wise_relative_error = false;
80 int CV_FilterBaseTest::read_params( CvFileStorage* fs )
82 int code = cvtest::ArrayTest::read_params( fs );
86 max_aperture_size = cvReadInt( find_param( fs, "max_aperture_size" ), max_aperture_size );
87 max_aperture_size = cvtest::clipInt( max_aperture_size, 1, 100 );
93 void CV_FilterBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
95 cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
102 RNG& rng = ts->get_rng();
103 double val = exp( cvtest::randReal(rng)*10 - 4 );
104 low = Scalar::all(-val);
105 high = Scalar::all(val);
109 low = Scalar::all(0);
110 high = Scalar::all(2);
113 else if( CV_MAT_DEPTH(type) == CV_16U )
115 low = Scalar::all(0.);
116 high = Scalar::all(40000.);
118 else if( CV_MAT_DEPTH(type) == CV_32F )
120 low = Scalar::all(-10.);
121 high = Scalar::all(10.);
127 void CV_FilterBaseTest::get_test_array_types_and_sizes( int test_case_idx,
128 vector<vector<Size> >& sizes,
129 vector<vector<int> >& types )
131 RNG& rng = ts->get_rng();
132 int depth = cvtest::randInt(rng) % CV_32F;
133 int cn = cvtest::randInt(rng) % 3 + 1;
134 cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
135 depth += depth == CV_8S;
138 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
140 aperture_size.width = cvtest::randInt(rng) % max_aperture_size + 1;
141 aperture_size.height = cvtest::randInt(rng) % max_aperture_size + 1;
142 anchor.x = cvtest::randInt(rng) % aperture_size.width;
143 anchor.y = cvtest::randInt(rng) % aperture_size.height;
145 types[INPUT][1] = fp_kernel ? CV_32FC1 : CV_8UC1;
146 sizes[INPUT][1] = aperture_size;
148 inplace = cvtest::randInt(rng) % 2 != 0;
149 border = BORDER_REPLICATE;
153 int CV_FilterBaseTest::prepare_test_case( int test_case_idx )
155 int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
158 if( inplace && test_mat[INPUT][0].type() == test_mat[OUTPUT][0].type())
159 cvtest::copy( test_mat[INPUT][0], test_mat[OUTPUT][0] );
167 /////////////////////////
169 class CV_MorphologyBaseTest : public CV_FilterBaseTest
172 CV_MorphologyBaseTest();
175 void prepare_to_validation( int test_case_idx );
176 int prepare_test_case( int test_case_idx );
177 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
178 double get_success_error_level( int test_case_idx, int i, int j );
179 int optype, optype_min, optype_max;
181 IplConvKernel* element;
185 CV_MorphologyBaseTest::CV_MorphologyBaseTest() : CV_FilterBaseTest( false )
189 optype = optype_min = optype_max = -1;
193 void CV_MorphologyBaseTest::get_test_array_types_and_sizes( int test_case_idx,
194 vector<vector<Size> >& sizes, vector<vector<int> >& types )
196 RNG& rng = ts->get_rng();
197 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
198 int depth = cvtest::randInt(rng) % 4;
199 depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : depth == 2 ? CV_16S : CV_32F;
200 int cn = CV_MAT_CN(types[INPUT][0]);
202 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
203 shape = cvtest::randInt(rng) % 4;
205 shape = CV_SHAPE_CUSTOM;
207 sizes[INPUT][1] = cvSize(0,0);
208 optype = cvtest::randInt(rng) % (optype_max - optype_min + 1) + optype_min;
212 double CV_MorphologyBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
214 return test_mat[INPUT][0].depth() < CV_32F ||
215 (optype == CV_MOP_ERODE || optype == CV_MOP_DILATE ||
216 optype == CV_MOP_OPEN || optype == CV_MOP_CLOSE) ? 0 : 1e-5;
220 int CV_MorphologyBaseTest::prepare_test_case( int test_case_idx )
222 int code = CV_FilterBaseTest::prepare_test_case( test_case_idx );
228 if( shape == CV_SHAPE_CUSTOM )
230 eldata.resize(aperture_size.width*aperture_size.height);
231 const uchar* src = test_mat[INPUT][1].data;
232 int srcstep = (int)test_mat[INPUT][1].step;
233 int i, j, nonzero = 0;
235 for( i = 0; i < aperture_size.height; i++ )
237 for( j = 0; j < aperture_size.width; j++ )
239 eldata[i*aperture_size.width + j] = src[i*srcstep + j];
240 nonzero += src[i*srcstep + j] != 0;
245 eldata[anchor.y*aperture_size.width + anchor.x] = 1;
248 cvReleaseStructuringElement( &element );
249 element = cvCreateStructuringElementEx( aperture_size.width, aperture_size.height,
250 anchor.x, anchor.y, shape, eldata.empty() ? 0 : &eldata[0] );
255 void CV_MorphologyBaseTest::prepare_to_validation( int /*test_case_idx*/ )
257 Mat& src = test_mat[INPUT][0], &dst = test_mat[REF_OUTPUT][0];
258 Mat _ielement(element->nRows, element->nCols, CV_32S, element->values);
260 _ielement.convertTo(_element, CV_8U);
261 Point _anchor(element->anchorX, element->anchorY);
262 int _border = BORDER_REPLICATE;
264 if( optype == CV_MOP_ERODE )
266 cvtest::erode( src, dst, _element, _anchor, _border );
268 else if( optype == CV_MOP_DILATE )
270 cvtest::dilate( src, dst, _element, _anchor, _border );
275 if( optype == CV_MOP_OPEN )
277 cvtest::erode( src, temp, _element, _anchor, _border );
278 cvtest::dilate( temp, dst, _element, _anchor, _border );
280 else if( optype == CV_MOP_CLOSE )
282 cvtest::dilate( src, temp, _element, _anchor, _border );
283 cvtest::erode( temp, dst, _element, _anchor, _border );
285 else if( optype == CV_MOP_GRADIENT )
287 cvtest::erode( src, temp, _element, _anchor, _border );
288 cvtest::dilate( src, dst, _element, _anchor, _border );
289 cvtest::add( dst, 1, temp, -1, Scalar::all(0), dst, dst.type() );
291 else if( optype == CV_MOP_TOPHAT )
293 cvtest::erode( src, temp, _element, _anchor, _border );
294 cvtest::dilate( temp, dst, _element, _anchor, _border );
295 cvtest::add( src, 1, dst, -1, Scalar::all(0), dst, dst.type() );
297 else if( optype == CV_MOP_BLACKHAT )
299 cvtest::dilate( src, temp, _element, _anchor, _border );
300 cvtest::erode( temp, dst, _element, _anchor, _border );
301 cvtest::add( dst, 1, src, -1, Scalar::all(0), dst, dst.type() );
304 CV_Error( CV_StsBadArg, "Unknown operation" );
307 cvReleaseStructuringElement( &element );
311 /////////////// erode ///////////////
313 class CV_ErodeTest : public CV_MorphologyBaseTest
322 CV_ErodeTest::CV_ErodeTest()
324 optype_min = optype_max = CV_MOP_ERODE;
328 void CV_ErodeTest::run_func()
330 cvErode( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
331 test_array[OUTPUT][0], element, 1 );
335 /////////////// dilate ///////////////
337 class CV_DilateTest : public CV_MorphologyBaseTest
346 CV_DilateTest::CV_DilateTest()
348 optype_min = optype_max = CV_MOP_DILATE;
352 void CV_DilateTest::run_func()
354 cvDilate( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
355 test_array[OUTPUT][0], element, 1 );
358 /////////////// morphEx ///////////////
360 class CV_MorphExTest : public CV_MorphologyBaseTest
369 CV_MorphExTest::CV_MorphExTest()
371 optype_min = CV_MOP_ERODE;
372 optype_max = CV_MOP_BLACKHAT;
376 void CV_MorphExTest::run_func()
378 cvMorphologyEx( test_array[inplace ? OUTPUT : INPUT][0],
379 test_array[OUTPUT][0], 0, element, optype, 1 );
382 /////////////// generic filter ///////////////
384 class CV_FilterTest : public CV_FilterBaseTest
390 void prepare_to_validation( int test_case_idx );
392 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
393 double get_success_error_level( int test_case_idx, int i, int j );
397 CV_FilterTest::CV_FilterTest() : CV_FilterBaseTest( true )
402 void CV_FilterTest::get_test_array_types_and_sizes( int test_case_idx,
403 vector<vector<Size> >& sizes, vector<vector<int> >& types )
405 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
406 RNG& rng = ts->get_rng();
407 int depth = cvtest::randInt(rng)%3;
408 int cn = CV_MAT_CN(types[INPUT][0]);
409 depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : CV_32F;
410 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
414 double CV_FilterTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
416 int depth = test_mat[INPUT][0].depth();
417 return depth <= CV_8S ? 2 : depth <= CV_32S ? 32 :
418 depth == CV_32F ? 1e-4 : 1e-10;
422 void CV_FilterTest::run_func()
424 CvMat kernel = test_mat[INPUT][1];
425 cvFilter2D( test_array[inplace ? OUTPUT : INPUT][0],
426 test_array[OUTPUT][0], &kernel, anchor );
430 void CV_FilterTest::prepare_to_validation( int /*test_case_idx*/ )
432 cvtest::filter2D( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].type(),
433 test_mat[INPUT][1], anchor, 0, BORDER_REPLICATE );
437 ////////////////////////
439 class CV_DerivBaseTest : public CV_FilterBaseTest
444 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
445 double get_success_error_level( int test_case_idx, int i, int j );
450 CV_DerivBaseTest::CV_DerivBaseTest() : CV_FilterBaseTest( true )
452 max_aperture_size = 7;
456 void CV_DerivBaseTest::get_test_array_types_and_sizes( int test_case_idx,
457 vector<vector<Size> >& sizes, vector<vector<int> >& types )
459 RNG& rng = ts->get_rng();
460 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
461 int depth = cvtest::randInt(rng) % 2;
462 depth = depth == 0 ? CV_8U : CV_32F;
463 types[INPUT][0] = CV_MAKETYPE(depth,1);
464 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth==CV_8U?CV_16S:CV_32F,1);
465 _aperture_size = (cvtest::randInt(rng)%5)*2 - 1;
466 sizes[INPUT][1] = aperture_size = cvSize(_aperture_size, _aperture_size);
470 double CV_DerivBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
472 int depth = test_mat[INPUT][0].depth();
473 return depth <= CV_8S ? 2 : 5e-4;
477 /////////////// sobel ///////////////
479 class CV_SobelTest : public CV_DerivBaseTest
485 void prepare_to_validation( int test_case_idx );
487 void get_test_array_types_and_sizes( int test_case_idx,
488 vector<vector<Size> >& sizes, vector<vector<int> >& types );
493 CV_SobelTest::CV_SobelTest() {}
496 void CV_SobelTest::get_test_array_types_and_sizes( int test_case_idx,
497 vector<vector<Size> >& sizes,
498 vector<vector<int> >& types )
500 RNG& rng = ts->get_rng();
501 CV_DerivBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
502 int max_d = _aperture_size > 0 ? 2 : 1;
503 origin = cvtest::randInt(rng) % 2;
504 dx = cvtest::randInt(rng) % (max_d + 1);
505 dy = cvtest::randInt(rng) % (max_d + 1 - dx);
506 if( dx == 0 && dy == 0 )
508 if( cvtest::randInt(rng) % 2 )
511 CV_SWAP( dx, dy, t );
514 if( _aperture_size < 0 )
515 aperture_size = cvSize(3, 3);
516 else if( _aperture_size == 1 )
519 aperture_size = cvSize(1, 3);
521 aperture_size = cvSize(3, 1);
525 aperture_size = cvSize(3, 3);
529 aperture_size = cvSize(_aperture_size, _aperture_size);
531 sizes[INPUT][1] = aperture_size;
532 anchor.x = aperture_size.width / 2;
533 anchor.y = aperture_size.height / 2;
537 void CV_SobelTest::run_func()
539 cvSobel( test_array[inplace ? OUTPUT : INPUT][0],
540 test_array[OUTPUT][0], dx, dy, _aperture_size );
541 /*cv::Sobel( test_mat[inplace ? OUTPUT : INPUT][0],
542 test_mat[OUTPUT][0], test_mat[OUTPUT][0].depth(),
543 dx, dy, _aperture_size, 1, 0, border );*/
547 void CV_SobelTest::prepare_to_validation( int /*test_case_idx*/ )
549 Mat kernel = cvtest::calcSobelKernel2D( dx, dy, _aperture_size, 0 );
550 cvtest::filter2D( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].depth(),
551 kernel, anchor, 0, BORDER_REPLICATE);
555 /////////////// laplace ///////////////
557 class CV_LaplaceTest : public CV_DerivBaseTest
563 int prepare_test_case( int test_case_idx );
564 void prepare_to_validation( int test_case_idx );
566 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
570 CV_LaplaceTest::CV_LaplaceTest()
575 void CV_LaplaceTest::get_test_array_types_and_sizes( int test_case_idx,
576 vector<vector<Size> >& sizes, vector<vector<int> >& types )
578 CV_DerivBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
579 if( _aperture_size <= 1 )
581 if( _aperture_size < 0 )
583 aperture_size = cvSize(3, 3);
586 aperture_size = cvSize(_aperture_size, _aperture_size);
588 sizes[INPUT][1] = aperture_size;
589 anchor.x = aperture_size.width / 2;
590 anchor.y = aperture_size.height / 2;
594 void CV_LaplaceTest::run_func()
596 cvLaplace( test_array[inplace ? OUTPUT : INPUT][0],
597 test_array[OUTPUT][0], _aperture_size );
601 int CV_LaplaceTest::prepare_test_case( int test_case_idx )
603 int code = CV_DerivBaseTest::prepare_test_case( test_case_idx );
604 return _aperture_size < 0 ? 0 : code;
608 void CV_LaplaceTest::prepare_to_validation( int /*test_case_idx*/ )
610 Mat kernel = cvtest::calcLaplaceKernel2D( _aperture_size );
611 cvtest::filter2D( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].depth(),
612 kernel, anchor, 0, BORDER_REPLICATE );
616 ////////////////////////////////////////////////////////////
618 class CV_SmoothBaseTest : public CV_FilterBaseTest
624 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
625 double get_success_error_level( int test_case_idx, int i, int j );
626 const char* smooth_type;
630 CV_SmoothBaseTest::CV_SmoothBaseTest() : CV_FilterBaseTest( true )
636 void CV_SmoothBaseTest::get_test_array_types_and_sizes( int test_case_idx,
637 vector<vector<Size> >& sizes, vector<vector<int> >& types )
639 RNG& rng = ts->get_rng();
640 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
641 int depth = cvtest::randInt(rng) % 2;
642 int cn = CV_MAT_CN(types[INPUT][0]);
643 depth = depth == 0 ? CV_8U : CV_32F;
644 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn);
645 anchor.x = cvtest::randInt(rng)%(max_aperture_size/2+1);
646 anchor.y = cvtest::randInt(rng)%(max_aperture_size/2+1);
647 aperture_size.width = anchor.x*2 + 1;
648 aperture_size.height = anchor.y*2 + 1;
649 sizes[INPUT][1] = aperture_size;
653 double CV_SmoothBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
655 int depth = test_mat[INPUT][0].depth();
656 return depth <= CV_8S ? 1 : 1e-5;
660 /////////////// blur ///////////////
662 class CV_BlurTest : public CV_SmoothBaseTest
668 int prepare_test_case( int test_case_idx );
669 void prepare_to_validation( int test_case_idx );
671 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
676 CV_BlurTest::CV_BlurTest()
681 void CV_BlurTest::get_test_array_types_and_sizes( int test_case_idx,
682 vector<vector<Size> >& sizes, vector<vector<int> >& types )
684 RNG& rng = ts->get_rng();
685 CV_SmoothBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
686 int depth = cvtest::randInt(rng) % 4;
687 int cn = (cvtest::randInt(rng) % 4) + 1;
688 depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : depth == 2 ? CV_16S : CV_32F;
689 types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][0] = CV_MAKETYPE(depth, cn);
690 normalize = cvtest::randInt(rng) % 2 != 0;
693 types[INPUT][0] = CV_MAKETYPE(depth, 1);
694 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth==CV_8U?CV_16S:CV_32F,1);
699 void CV_BlurTest::run_func()
701 cvSmooth( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
702 test_array[OUTPUT][0], normalize ? CV_BLUR : CV_BLUR_NO_SCALE,
703 aperture_size.width, aperture_size.height );
707 int CV_BlurTest::prepare_test_case( int test_case_idx )
709 int code = CV_SmoothBaseTest::prepare_test_case( test_case_idx );
710 return code > 0 && !normalize && test_mat[INPUT][0].channels() > 1 ? 0 : code;
714 void CV_BlurTest::prepare_to_validation( int /*test_case_idx*/ )
716 Mat kernel(aperture_size, CV_64F);
717 kernel.setTo(Scalar::all(normalize ? 1./(aperture_size.width*aperture_size.height) : 1.));
718 cvtest::filter2D( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].depth(),
719 kernel, anchor, 0, BORDER_REPLICATE );
723 /////////////// gaussian ///////////////
725 class CV_GaussianBlurTest : public CV_SmoothBaseTest
728 CV_GaussianBlurTest();
731 void prepare_to_validation( int test_case_idx );
733 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
734 double get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ );
740 CV_GaussianBlurTest::CV_GaussianBlurTest() : CV_SmoothBaseTest()
743 smooth_type = "Gaussian";
747 double CV_GaussianBlurTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
749 int depth = test_mat[INPUT][0].depth();
750 return depth <= CV_8S ? 8 : 1e-5;
754 void CV_GaussianBlurTest::get_test_array_types_and_sizes( int test_case_idx,
755 vector<vector<Size> >& sizes, vector<vector<int> >& types )
757 RNG& rng = ts->get_rng();
758 int kernel_case = cvtest::randInt(rng) % 2;
759 CV_SmoothBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
760 anchor = cvPoint(aperture_size.width/2,aperture_size.height/2);
762 sigma = exp(cvtest::randReal(rng)*5-2);
763 param1 = aperture_size.width;
764 param2 = aperture_size.height;
766 if( kernel_case == 0 )
770 void CV_GaussianBlurTest::run_func()
772 cvSmooth( test_array[inplace ? OUTPUT : INPUT][0],
773 test_array[OUTPUT][0], CV_GAUSSIAN,
774 param1, param2, sigma, sigma );
778 // !!! Copied from cvSmooth, if the code is changed in cvSmooth,
779 // make sure to update this one too.
780 #define SMALL_GAUSSIAN_SIZE 7
782 calcGaussianKernel( int n, double sigma, vector<float>& kernel )
784 static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] =
787 {0.25f, 0.5f, 0.25f},
788 {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f},
789 {0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125}
793 if( n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 )
796 memcpy( &kernel[0], small_gaussian_tab[n>>1], n*sizeof(kernel[0]));
800 double sigmaX = sigma > 0 ? sigma : (n/2 - 1)*0.3 + 0.8;
801 double scale2X = -0.5/(sigmaX*sigmaX);
804 sum = kernel[n/2] = 1.f;
806 for( i = 1; i <= n/2; i++ )
808 kernel[n/2+i] = kernel[n/2-i] = (float)exp(scale2X*i*i);
809 sum += kernel[n/2+i]*2;
813 for( i = 0; i <= n/2; i++ )
814 kernel[n/2+i] = kernel[n/2-i] = (float)(kernel[n/2+i]*sum);
819 static Mat calcGaussianKernel2D( Size ksize, double sigma )
821 vector<float> kx, ky;
822 Mat kernel(ksize, CV_32F);
824 calcGaussianKernel( kernel.cols, sigma, kx );
825 calcGaussianKernel( kernel.rows, sigma, ky );
827 for( int i = 0; i < kernel.rows; i++ )
828 for( int j = 0; j < kernel.cols; j++ )
829 kernel.at<float>(i, j) = kx[j]*ky[i];
834 void CV_GaussianBlurTest::prepare_to_validation( int /*test_case_idx*/ )
836 Mat kernel = calcGaussianKernel2D( aperture_size, sigma );
837 cvtest::filter2D( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].depth(),
838 kernel, anchor, 0, border & ~BORDER_ISOLATED );
842 /////////////// median ///////////////
844 class CV_MedianBlurTest : public CV_SmoothBaseTest
850 void prepare_to_validation( int test_case_idx );
851 double get_success_error_level( int test_case_idx, int i, int j );
853 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
857 CV_MedianBlurTest::CV_MedianBlurTest()
859 smooth_type = "Median";
863 void CV_MedianBlurTest::get_test_array_types_and_sizes( int test_case_idx,
864 vector<vector<Size> >& sizes, vector<vector<int> >& types )
866 CV_SmoothBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
868 int cn = CV_MAT_CN(types[INPUT][0]);
869 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn);
870 types[INPUT][1] = CV_MAKETYPE(depth,1);
872 aperture_size.height = aperture_size.width;
873 anchor.x = anchor.y = aperture_size.width / 2;
874 sizes[INPUT][1] = cvSize(aperture_size.width,aperture_size.height);
876 sizes[OUTPUT][0] = sizes[INPUT][0];
877 sizes[REF_OUTPUT][0] = sizes[INPUT][0];
880 border = BORDER_REPLICATE | BORDER_ISOLATED;
884 double CV_MedianBlurTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
890 void CV_MedianBlurTest::run_func()
892 cvSmooth( test_array[INPUT][0], test_array[OUTPUT][0],
893 CV_MEDIAN, aperture_size.width );
902 median_pair( int _col, int _val ) : col(_col), val(_val) { }
906 static void test_medianFilter( const Mat& src, Mat& dst, int m )
908 int i, j, k, l, m2 = m*m, n;
909 vector<int> col_buf(m+1);
910 vector<median_pair> _buf0(m*m+1), _buf1(m*m+1);
911 median_pair *buf0 = &_buf0[0], *buf1 = &_buf1[0];
912 int step = (int)(src.step/src.elemSize());
914 assert( src.rows == dst.rows + m - 1 && src.cols == dst.cols + m - 1 &&
915 src.type() == dst.type() && src.type() == CV_8UC1 );
917 for( i = 0; i < dst.rows; i++ )
919 uchar* dst1 = dst.ptr<uchar>(i);
920 for( k = 0; k < m; k++ )
922 const uchar* src1 = src.ptr<uchar>(i+k);
923 for( j = 0; j < m-1; j++ )
924 *buf0++ = median_pair(j, src1[j]);
929 for( k = n-1; k > 0; k-- )
932 for( j = 0; j < k; j++ )
934 if( buf0[j].val > buf0[j+1].val )
937 CV_SWAP( buf0[j], buf0[j+1], t );
945 for( j = 0; j < dst.cols; j++ )
947 int ins_col = j + m - 1;
949 const uchar* src1 = src.ptr<uchar>(i) + ins_col;
950 for( k = 0; k < m; k++, src1 += step )
952 col_buf[k] = src1[0];
953 for( l = k-1; l >= 0; l-- )
956 if( col_buf[l] < col_buf[l+1] )
958 CV_SWAP( col_buf[l], col_buf[l+1], t );
962 col_buf[m] = INT_MAX;
964 for( k = 0, l = 0; k < n; )
966 if( buf0[k].col == del_col )
968 else if( buf0[k].val < col_buf[l] )
972 assert( col_buf[l] < INT_MAX );
973 *buf1++ = median_pair(ins_col,col_buf[l++]);
978 *buf1++ = median_pair(ins_col,col_buf[l]);
984 dst1[j] = (uchar)buf1[n/2].val;
986 CV_SWAP( buf0, buf1, tbuf );
992 void CV_MedianBlurTest::prepare_to_validation( int /*test_case_idx*/ )
994 // CV_SmoothBaseTest::prepare_to_validation( test_case_idx );
995 const Mat& src0 = test_mat[INPUT][0];
996 Mat& dst0 = test_mat[REF_OUTPUT][0];
997 int i, cn = src0.channels();
998 int m = aperture_size.width;
999 Mat src(src0.rows + m - 1, src0.cols + m - 1, src0.depth());
1004 dst.create(src0.size(), src0.depth());
1006 for( i = 0; i < cn; i++ )
1011 cvtest::extract( src0, dst, i );
1014 cvtest::copyMakeBorder( ptr, src, m/2, m/2, m/2, m/2, border & ~BORDER_ISOLATED );
1015 test_medianFilter( src, dst, m );
1017 cvtest::insert( dst, dst0, i );
1022 /////////////// pyramid tests ///////////////
1024 class CV_PyramidBaseTest : public CV_FilterBaseTest
1027 CV_PyramidBaseTest( bool downsample );
1030 double get_success_error_level( int test_case_idx, int i, int j );
1031 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1037 CV_PyramidBaseTest::CV_PyramidBaseTest( bool _downsample ) : CV_FilterBaseTest(true)
1039 static float kdata[] = { 1.f, 4.f, 6.f, 4.f, 1.f };
1040 downsample = _downsample;
1041 Mat kernel1d(1, 5, CV_32F, kdata);
1042 kernel = (kernel1d.t()*kernel1d)*((downsample ? 1 : 4)/256.);
1046 double CV_PyramidBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1048 int depth = test_mat[INPUT][0].depth();
1049 return depth < CV_32F ? 1 : 1e-5;
1053 void CV_PyramidBaseTest::get_test_array_types_and_sizes( int test_case_idx,
1054 vector<vector<Size> >& sizes,
1055 vector<vector<int> >& types )
1057 const int channels[] = {1, 3, 4};
1058 const int depthes[] = {CV_8U, CV_16S, CV_16U, CV_32F};
1060 RNG& rng = ts->get_rng();
1062 CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1064 int depth = depthes[cvtest::randInt(rng) % (sizeof(depthes)/sizeof(depthes[0]))];
1065 int cn = channels[cvtest::randInt(rng) % (sizeof(channels)/sizeof(channels[0]))];
1067 aperture_size = cvSize(5,5);
1068 anchor = cvPoint(aperture_size.width/2, aperture_size.height/2);
1070 types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
1072 sz.width = MAX( sizes[INPUT][0].width/2, 1 );
1073 sz.height = MAX( sizes[INPUT][0].height/2, 1 );
1077 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
1080 sizes[INPUT][0] = sz;
1084 sizes[INPUT][0] = sz;
1087 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
1090 sizes[INPUT][1] = aperture_size;
1095 /////// pyrdown ////////
1097 class CV_PyramidDownTest : public CV_PyramidBaseTest
1100 CV_PyramidDownTest();
1104 void prepare_to_validation( int );
1108 CV_PyramidDownTest::CV_PyramidDownTest() : CV_PyramidBaseTest( true )
1113 void CV_PyramidDownTest::run_func()
1115 cvPyrDown( test_array[INPUT][0], test_array[OUTPUT][0], CV_GAUSSIAN_5x5 );
1119 void CV_PyramidDownTest::prepare_to_validation( int /*test_case_idx*/ )
1121 Mat& src = test_mat[INPUT][0], &dst = test_mat[REF_OUTPUT][0];
1123 cvtest::filter2D(src, temp, src.depth(),
1124 kernel, Point(kernel.cols/2, kernel.rows/2),
1125 0, BORDER_REFLECT_101);
1127 size_t elem_size = temp.elemSize();
1128 size_t ncols = dst.cols*elem_size;
1130 for( int i = 0; i < dst.rows; i++ )
1132 const uchar* src_row = temp.ptr(i*2);
1133 uchar* dst_row = dst.ptr(i);
1135 for( size_t j = 0; j < ncols; j += elem_size )
1137 for( size_t k = 0; k < elem_size; k++ )
1138 dst_row[j+k] = src_row[j*2+k];
1144 /////// pyrup ////////
1146 class CV_PyramidUpTest : public CV_PyramidBaseTest
1153 void prepare_to_validation( int );
1157 CV_PyramidUpTest::CV_PyramidUpTest() : CV_PyramidBaseTest( false )
1162 void CV_PyramidUpTest::run_func()
1164 cvPyrUp( test_array[INPUT][0], test_array[OUTPUT][0], CV_GAUSSIAN_5x5 );
1168 void CV_PyramidUpTest::prepare_to_validation( int /*test_case_idx*/ )
1170 Mat& src = test_mat[INPUT][0], &dst = test_mat[REF_OUTPUT][0];
1171 Mat temp(dst.size(), dst.type());
1173 size_t elem_size = src.elemSize();
1174 size_t ncols = src.cols*elem_size;
1176 for( int i = 0; i < src.rows; i++ )
1178 const uchar* src_row = src.ptr(i);
1179 uchar* dst_row = temp.ptr(i*2);
1181 if( i*2 + 1 < temp.rows )
1182 memset( temp.ptr(i*2+1), 0, temp.cols*elem_size );
1183 for( size_t j = 0; j < ncols; j += elem_size )
1185 for( size_t k = 0; k < elem_size; k++ )
1187 dst_row[j*2+k] = src_row[j+k];
1188 dst_row[j*2+k+elem_size] = 0;
1193 cvtest::filter2D(temp, dst, dst.depth(),
1194 kernel, Point(kernel.cols/2, kernel.rows/2),
1195 0, BORDER_REFLECT_101);
1199 //////////////////////// feature selection //////////////////////////
1201 class CV_FeatureSelBaseTest : public cvtest::ArrayTest
1204 CV_FeatureSelBaseTest( int width_factor );
1207 int read_params( CvFileStorage* fs );
1208 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1209 void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
1210 double get_success_error_level( int test_case_idx, int i, int j );
1211 int aperture_size, block_size;
1212 int max_aperture_size;
1218 CV_FeatureSelBaseTest::CV_FeatureSelBaseTest( int _width_factor )
1220 max_aperture_size = 7;
1221 max_block_size = 21;
1222 // 1 input, 1 output, temp arrays are allocated in the reference functions
1223 test_array[INPUT].push_back(NULL);
1224 test_array[OUTPUT].push_back(NULL);
1225 test_array[REF_OUTPUT].push_back(NULL);
1226 element_wise_relative_error = false;
1227 width_factor = _width_factor;
1231 int CV_FeatureSelBaseTest::read_params( CvFileStorage* fs )
1233 int code = cvtest::BaseTest::read_params( fs );
1237 max_aperture_size = cvReadInt( find_param( fs, "max_aperture_size" ), max_aperture_size );
1238 max_aperture_size = cvtest::clipInt( max_aperture_size, 1, 9 );
1239 max_block_size = cvReadInt( find_param( fs, "max_block_size" ), max_block_size );
1240 max_block_size = cvtest::clipInt( max_aperture_size, 1, 100 );
1246 double CV_FeatureSelBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1248 int depth = test_mat[INPUT][0].depth();
1249 return depth <= CV_8S ? 3e-2 : depth == CV_32F ? 1e-3 : 1e-10;
1253 void CV_FeatureSelBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
1255 cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
1256 if( i == INPUT && CV_MAT_DEPTH(type) == CV_32F )
1258 low = Scalar::all(-10.);
1259 high = Scalar::all(10.);
1264 void CV_FeatureSelBaseTest::get_test_array_types_and_sizes( int test_case_idx,
1265 vector<vector<Size> >& sizes, vector<vector<int> >& types )
1267 RNG& rng = ts->get_rng();
1268 cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1269 int depth = cvtest::randInt(rng) % 2, asz;
1271 depth = depth == 0 ? CV_8U : CV_32F;
1272 types[INPUT][0] = depth;
1273 types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_32FC1;
1275 aperture_size = (cvtest::randInt(rng) % (max_aperture_size+2) - 1) | 1;
1276 if( aperture_size == 1 )
1278 if( depth == CV_8U )
1279 aperture_size = MIN( aperture_size, 5 );
1280 block_size = (cvtest::randInt(rng) % max_block_size + 1) | 1;
1281 if( block_size <= 3 )
1283 asz = aperture_size > 0 ? aperture_size : 3;
1285 sizes[INPUT][0].width = MAX( sizes[INPUT][0].width, asz + block_size );
1286 sizes[INPUT][0].height = MAX( sizes[INPUT][0].height, asz + block_size );
1287 sizes[OUTPUT][0].height = sizes[REF_OUTPUT][0].height = sizes[INPUT][0].height;
1288 sizes[OUTPUT][0].width = sizes[REF_OUTPUT][0].width = sizes[INPUT][0].width*width_factor;
1293 test_cornerEigenValsVecs( const Mat& src, Mat& eigenv, Mat& ocv_eigenv,
1294 int block_size, int _aperture_size, int mode )
1297 int aperture_size = _aperture_size < 0 ? 3 : _aperture_size;
1298 Point anchor( aperture_size/2, aperture_size/2 );
1300 CV_Assert( src.type() == CV_8UC1 || src.type() == CV_32FC1 );
1301 CV_Assert( eigenv.type() == CV_32FC1 );
1302 CV_Assert( src.rows == eigenv.rows &&
1303 ((mode > 0 && src.cols == eigenv.cols) ||
1304 (mode == 0 && src.cols*6 == eigenv.cols)) );
1306 int type = src.type();
1307 int ftype = CV_32FC1;
1308 double kernel_scale = type != ftype ? 1./255 : 1;
1310 Mat dx2, dy2, dxdy(src.size(), CV_32F), kernel;
1312 kernel = cvtest::calcSobelKernel2D( 1, 0, _aperture_size );
1313 cvtest::filter2D( src, dx2, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE );
1314 kernel = cvtest::calcSobelKernel2D( 0, 1, _aperture_size );
1315 cvtest::filter2D( src, dy2, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE );
1317 double denom = (1 << (aperture_size-1))*block_size;
1318 denom = denom * denom;
1319 if( _aperture_size < 0 )
1323 for( i = 0; i < src.rows; i++ )
1325 float* dxdyp = dxdy.ptr<float>(i);
1326 float* dx2p = dx2.ptr<float>(i);
1327 float* dy2p = dy2.ptr<float>(i);
1329 for( j = 0; j < src.cols; j++ )
1331 double xval = dx2p[j], yval = dy2p[j];
1332 dxdyp[j] = (float)(xval*yval*denom);
1333 dx2p[j] = (float)(xval*xval*denom);
1334 dy2p[j] = (float)(yval*yval*denom);
1338 kernel = Mat::ones(block_size, block_size, CV_32F);
1339 anchor = Point(block_size/2, block_size/2);
1341 cvtest::filter2D( dx2, dx2, ftype, kernel, anchor, 0, BORDER_REPLICATE );
1342 cvtest::filter2D( dy2, dy2, ftype, kernel, anchor, 0, BORDER_REPLICATE );
1343 cvtest::filter2D( dxdy, dxdy, ftype, kernel, anchor, 0, BORDER_REPLICATE );
1347 for( i = 0; i < src.rows; i++ )
1349 float* eigenvp = eigenv.ptr<float>(i);
1350 float* ocv_eigenvp = ocv_eigenv.ptr<float>(i);
1351 const float* dxdyp = dxdy.ptr<float>(i);
1352 const float* dx2p = dx2.ptr<float>(i);
1353 const float* dy2p = dy2.ptr<float>(i);
1355 for( j = 0; j < src.cols; j++ )
1357 double a = dx2p[j], b = dxdyp[j], c = dy2p[j];
1358 double d = sqrt((a-c)*(a-c) + 4*b*b);
1359 double l1 = 0.5*(a + c + d);
1360 double l2 = 0.5*(a + c - d);
1361 double x1, y1, x2, y2, s;
1363 if( fabs(a - l1) + fabs(b) >= 1e-3 )
1364 x1 = b, y1 = l1 - a;
1366 x1 = l1 - c, y1 = b;
1367 s = 1./(sqrt(x1*x1+y1*y1)+DBL_EPSILON);
1370 if( fabs(a - l2) + fabs(b) >= 1e-3 )
1371 x2 = b, y2 = l2 - a;
1373 x2 = l2 - c, y2 = b;
1374 s = 1./(sqrt(x2*x2+y2*y2)+DBL_EPSILON);
1377 /* the orientation of eigen vectors might be inversed relative to OpenCV function,
1379 if( (fabs(x1) >= fabs(y1) && ocv_eigenvp[j*6+2]*x1 < 0) ||
1380 (fabs(x1) < fabs(y1) && ocv_eigenvp[j*6+3]*y1 < 0) )
1383 if( (fabs(x2) >= fabs(y2) && ocv_eigenvp[j*6+4]*x2 < 0) ||
1384 (fabs(x2) < fabs(y2) && ocv_eigenvp[j*6+5]*y2 < 0) )
1387 eigenvp[j*6] = (float)l1;
1388 eigenvp[j*6+1] = (float)l2;
1389 eigenvp[j*6+2] = (float)x1;
1390 eigenvp[j*6+3] = (float)y1;
1391 eigenvp[j*6+4] = (float)x2;
1392 eigenvp[j*6+5] = (float)y2;
1396 else if( mode == 1 )
1398 for( i = 0; i < src.rows; i++ )
1400 float* eigenvp = eigenv.ptr<float>(i);
1401 const float* dxdyp = dxdy.ptr<float>(i);
1402 const float* dx2p = dx2.ptr<float>(i);
1403 const float* dy2p = dy2.ptr<float>(i);
1405 for( j = 0; j < src.cols; j++ )
1407 double a = dx2p[j], b = dxdyp[j], c = dy2p[j];
1408 double d = sqrt((a-c)*(a-c) + 4*b*b);
1409 eigenvp[j] = (float)(0.5*(a + c - d));
1417 class CV_MinEigenValTest : public CV_FeatureSelBaseTest
1420 CV_MinEigenValTest();
1424 void prepare_to_validation( int );
1428 CV_MinEigenValTest::CV_MinEigenValTest() : CV_FeatureSelBaseTest( 1 )
1433 void CV_MinEigenValTest::run_func()
1435 cvCornerMinEigenVal( test_array[INPUT][0], test_array[OUTPUT][0],
1436 block_size, aperture_size );
1440 void CV_MinEigenValTest::prepare_to_validation( int /*test_case_idx*/ )
1442 test_cornerEigenValsVecs( test_mat[INPUT][0], test_mat[REF_OUTPUT][0],
1443 test_mat[OUTPUT][0], block_size, aperture_size, 1 );
1447 // eigenval's & vec's
1448 class CV_EigenValVecTest : public CV_FeatureSelBaseTest
1451 CV_EigenValVecTest();
1455 void prepare_to_validation( int );
1459 CV_EigenValVecTest::CV_EigenValVecTest() : CV_FeatureSelBaseTest( 6 )
1464 void CV_EigenValVecTest::run_func()
1466 cvCornerEigenValsAndVecs( test_array[INPUT][0], test_array[OUTPUT][0],
1467 block_size, aperture_size );
1471 void CV_EigenValVecTest::prepare_to_validation( int /*test_case_idx*/ )
1473 test_cornerEigenValsVecs( test_mat[INPUT][0], test_mat[REF_OUTPUT][0],
1474 test_mat[OUTPUT][0], block_size, aperture_size, 0 );
1479 class CV_PreCornerDetectTest : public CV_FeatureSelBaseTest
1482 CV_PreCornerDetectTest();
1486 void prepare_to_validation( int );
1487 int prepare_test_case( int );
1491 CV_PreCornerDetectTest::CV_PreCornerDetectTest() : CV_FeatureSelBaseTest( 1 )
1496 void CV_PreCornerDetectTest::run_func()
1498 cvPreCornerDetect( test_array[INPUT][0], test_array[OUTPUT][0], aperture_size );
1502 int CV_PreCornerDetectTest::prepare_test_case( int test_case_idx )
1504 int code = CV_FeatureSelBaseTest::prepare_test_case( test_case_idx );
1505 if( aperture_size < 0 )
1511 void CV_PreCornerDetectTest::prepare_to_validation( int /*test_case_idx*/ )
1513 /*cvTsCornerEigenValsVecs( test_mat[INPUT][0], test_mat[REF_OUTPUT][0],
1514 block_size, aperture_size, 0 );*/
1515 const Mat& src = test_mat[INPUT][0];
1516 Mat& dst = test_mat[REF_OUTPUT][0];
1518 int type = src.type(), ftype = CV_32FC1;
1519 Point anchor(aperture_size/2, aperture_size/2);
1521 double kernel_scale = type != ftype ? 1./255 : 1.;
1523 Mat dx, dy, d2x, d2y, dxy, kernel;
1525 kernel = cvtest::calcSobelKernel2D(1, 0, aperture_size);
1526 cvtest::filter2D(src, dx, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE);
1527 kernel = cvtest::calcSobelKernel2D(2, 0, aperture_size);
1528 cvtest::filter2D(src, d2x, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE);
1529 kernel = cvtest::calcSobelKernel2D(0, 1, aperture_size);
1530 cvtest::filter2D(src, dy, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE);
1531 kernel = cvtest::calcSobelKernel2D(0, 2, aperture_size);
1532 cvtest::filter2D(src, d2y, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE);
1533 kernel = cvtest::calcSobelKernel2D(1, 1, aperture_size);
1534 cvtest::filter2D(src, dxy, ftype, kernel*kernel_scale, anchor, 0, BORDER_REPLICATE);
1536 double denom = 1 << (aperture_size-1);
1537 denom = denom * denom * denom;
1540 for( int i = 0; i < src.rows; i++ )
1542 const float* _dx = dx.ptr<float>(i);
1543 const float* _dy = dy.ptr<float>(i);
1544 const float* _d2x = d2x.ptr<float>(i);
1545 const float* _d2y = d2y.ptr<float>(i);
1546 const float* _dxy = dxy.ptr<float>(i);
1547 float* corner = dst.ptr<float>(i);
1549 for( int j = 0; j < src.cols; j++ )
1554 corner[j] = (float)(denom*(x*x*_d2y[j] + y*y*_d2x[j] - 2*x*y*_dxy[j]));
1560 ///////// integral /////////
1562 class CV_IntegralTest : public cvtest::ArrayTest
1568 void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1569 void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
1570 double get_success_error_level( int test_case_idx, int i, int j );
1572 void prepare_to_validation( int );
1574 int prepare_test_case( int test_case_idx );
1578 CV_IntegralTest::CV_IntegralTest()
1580 test_array[INPUT].push_back(NULL);
1581 test_array[OUTPUT].push_back(NULL);
1582 test_array[OUTPUT].push_back(NULL);
1583 test_array[OUTPUT].push_back(NULL);
1584 test_array[REF_OUTPUT].push_back(NULL);
1585 test_array[REF_OUTPUT].push_back(NULL);
1586 test_array[REF_OUTPUT].push_back(NULL);
1587 element_wise_relative_error = true;
1591 void CV_IntegralTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
1593 cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
1594 int depth = CV_MAT_DEPTH(type);
1595 if( depth == CV_32F )
1597 low = Scalar::all(-10.);
1598 high = Scalar::all(10.);
1603 void CV_IntegralTest::get_test_array_types_and_sizes( int test_case_idx,
1604 vector<vector<Size> >& sizes, vector<vector<int> >& types )
1606 RNG& rng = ts->get_rng();
1607 int depth = cvtest::randInt(rng) % 2, sum_depth;
1608 int cn = cvtest::randInt(rng) % 3 + 1;
1609 cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1612 depth = depth == 0 ? CV_8U : CV_32F;
1614 int b = (cvtest::randInt(rng) & 1) != 0;
1615 sum_depth = depth == CV_8U && b ? CV_32S : b ? CV_32F : CV_64F;
1617 types[INPUT][0] = CV_MAKETYPE(depth,cn);
1618 types[OUTPUT][0] = types[REF_OUTPUT][0] =
1619 types[OUTPUT][2] = types[REF_OUTPUT][2] = CV_MAKETYPE(sum_depth, cn);
1620 types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_MAKETYPE(CV_64F, cn);
1622 sum_size.width = sizes[INPUT][0].width + 1;
1623 sum_size.height = sizes[INPUT][0].height + 1;
1625 sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sum_size;
1626 sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] =
1627 sizes[OUTPUT][2] = sizes[REF_OUTPUT][2] = Size(0,0);
1629 if( cvtest::randInt(rng) % 3 > 0 )
1631 sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = sum_size;
1632 if( cvtest::randInt(rng) % 2 > 0 )
1633 sizes[REF_OUTPUT][2] = sizes[OUTPUT][2] = sum_size;
1638 double CV_IntegralTest::get_success_error_level( int, int i, int j )
1640 int depth = test_mat[i][j].depth();
1641 return depth == CV_32S ? 0 : depth == CV_64F ? FLT_EPSILON : 5e-3;
1645 int CV_IntegralTest::prepare_test_case( int test_case_idx )
1647 int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
1648 return code > 0 && ((test_array[OUTPUT][2] && test_mat[OUTPUT][2].channels() > 1) ||
1649 test_mat[OUTPUT][0].depth() < test_mat[INPUT][0].depth()) ? 0 : code;
1653 void CV_IntegralTest::run_func()
1655 cvIntegral( test_array[INPUT][0], test_array[OUTPUT][0],
1656 test_array[OUTPUT][1], test_array[OUTPUT][2] );
1660 static void test_integral( const Mat& img, Mat* sum, Mat* sqsum, Mat* tilted )
1662 CV_Assert( img.depth() == CV_32F );
1664 sum->create(img.rows+1, img.cols+1, CV_64F);
1666 sqsum->create(img.rows+1, img.cols+1, CV_64F);
1668 tilted->create(img.rows+1, img.cols+1, CV_64F);
1670 const float* data = img.ptr<float>();
1671 double* sdata = sum->ptr<double>();
1672 double* sqdata = sqsum ? sqsum->ptr<double>() : 0;
1673 double* tdata = tilted ? tilted->ptr<double>() : 0;
1674 int step = (int)(img.step/sizeof(data[0]));
1675 int sstep = (int)(sum->step/sizeof(sdata[0]));
1676 int sqstep = sqsum ? (int)(sqsum->step/sizeof(sqdata[0])) : 0;
1677 int tstep = tilted ? (int)(tilted->step/sizeof(tdata[0])) : 0;
1678 Size size = img.size();
1680 memset( sdata, 0, (size.width+1)*sizeof(sdata[0]) );
1682 memset( sqdata, 0, (size.width+1)*sizeof(sqdata[0]) );
1684 memset( tdata, 0, (size.width+1)*sizeof(tdata[0]) );
1686 for( ; size.height--; data += step )
1688 double s = 0, sq = 0;
1694 for( x = 0; x <= size.width; x++ )
1696 double t = x > 0 ? data[x-1] : 0, ts = t;
1700 sdata[x] = s + sdata[x - sstep];
1702 sqdata[x] = sq + sqdata[x - sqstep];
1708 ts += tdata[-tstep+1];
1711 ts += tdata[x-tstep-1];
1712 if( data > img.ptr<float>() )
1714 ts += data[x-step-1];
1715 if( x < size.width )
1716 ts += tdata[x-tstep+1] - tdata[x-tstep*2];
1726 void CV_IntegralTest::prepare_to_validation( int /*test_case_idx*/ )
1728 Mat& src = test_mat[INPUT][0];
1729 int cn = src.channels();
1731 Mat* sum0 = &test_mat[REF_OUTPUT][0];
1732 Mat* sqsum0 = test_array[REF_OUTPUT][1] ? &test_mat[REF_OUTPUT][1] : 0;
1733 Mat* tsum0 = test_array[REF_OUTPUT][2] ? &test_mat[REF_OUTPUT][2] : 0;
1735 Mat plane, srcf, psum, psqsum, ptsum, psum2, psqsum2, ptsum2;
1740 psqsum2 = sqsum0 ? *sqsum0 : Mat();
1741 ptsum2 = tsum0 ? *tsum0 : Mat();
1744 for( int i = 0; i < cn; i++ )
1747 cvtest::extract(src, plane, i);
1748 plane.convertTo(srcf, CV_32F);
1750 test_integral( srcf, &psum, sqsum0 ? &psqsum : 0, tsum0 ? &ptsum : 0 );
1751 psum.convertTo(psum2, sum0->depth());
1753 psqsum.convertTo(psqsum2, sqsum0->depth());
1755 ptsum.convertTo(ptsum2, tsum0->depth());
1759 cvtest::insert(psum2, *sum0, i);
1761 cvtest::insert(psqsum2, *sqsum0, i);
1763 cvtest::insert(ptsum2, *tsum0, i);
1769 ///////////////////////////////////////////////////////////////////////////////////
1771 TEST(Imgproc_Erode, accuracy) { CV_ErodeTest test; test.safe_run(); }
1772 TEST(Imgproc_Dilate, accuracy) { CV_DilateTest test; test.safe_run(); }
1773 TEST(Imgproc_MorphologyEx, accuracy) { CV_MorphExTest test; test.safe_run(); }
1774 TEST(Imgproc_Filter2D, accuracy) { CV_FilterTest test; test.safe_run(); }
1775 TEST(Imgproc_Sobel, accuracy) { CV_SobelTest test; test.safe_run(); }
1776 TEST(Imgproc_Laplace, accuracy) { CV_LaplaceTest test; test.safe_run(); }
1777 TEST(Imgproc_Blur, accuracy) { CV_BlurTest test; test.safe_run(); }
1778 TEST(Imgproc_GaussianBlur, accuracy) { CV_GaussianBlurTest test; test.safe_run(); }
1779 TEST(Imgproc_MedianBlur, accuracy) { CV_MedianBlurTest test; test.safe_run(); }
1780 TEST(Imgproc_PyramidDown, accuracy) { CV_PyramidDownTest test; test.safe_run(); }
1781 TEST(Imgproc_PyramidUp, accuracy) { CV_PyramidUpTest test; test.safe_run(); }
1782 TEST(Imgproc_MinEigenVal, accuracy) { CV_MinEigenValTest test; test.safe_run(); }
1783 TEST(Imgproc_EigenValsVecs, accuracy) { CV_EigenValVecTest test; test.safe_run(); }
1784 TEST(Imgproc_PreCornerDetect, accuracy) { CV_PreCornerDetectTest test; test.safe_run(); }
1785 TEST(Imgproc_Integral, accuracy) { CV_IntegralTest test; test.safe_run(); }
1787 //////////////////////////////////////////////////////////////////////////////////
1789 class CV_FilterSupportedFormatsTest : public cvtest::BaseTest
1792 CV_FilterSupportedFormatsTest() {}
1793 ~CV_FilterSupportedFormatsTest() {}
1797 const int depths[][2] =
1816 volatile int fidx = -1;
1819 // use some "odd" size to do yet another smoke
1820 // testing of the non-SIMD loop tails
1822 Mat small_kernel(5, 5, CV_32F), big_kernel(21, 21, CV_32F);
1823 Mat kernelX(11, 1, CV_32F), kernelY(7, 1, CV_32F);
1824 Mat symkernelX(11, 1, CV_32F), symkernelY(7, 1, CV_32F);
1825 randu(small_kernel, -10, 10);
1826 randu(big_kernel, -1, 1);
1827 randu(kernelX, -1, 1);
1828 randu(kernelY, -1, 1);
1829 flip(kernelX, symkernelX, 0);
1830 symkernelX += kernelX;
1831 flip(kernelY, symkernelY, 0);
1832 symkernelY += kernelY;
1834 Mat elem_ellipse = getStructuringElement(MORPH_ELLIPSE, Size(7, 7));
1835 Mat elem_rect = getStructuringElement(MORPH_RECT, Size(7, 7));
1837 for( i = 0; depths[i][0] >= 0; i++ )
1839 int sdepth = depths[i][0];
1840 int ddepth = depths[i][1];
1841 Mat src(sz, CV_MAKETYPE(sdepth, 5)), dst;
1843 // non-separable filtering with a small kernel
1845 filter2D(src, dst, ddepth, small_kernel);
1847 filter2D(src, dst, ddepth, big_kernel);
1849 sepFilter2D(src, dst, ddepth, kernelX, kernelY);
1851 sepFilter2D(src, dst, ddepth, symkernelX, symkernelY);
1853 Sobel(src, dst, ddepth, 2, 0, 5);
1855 Scharr(src, dst, ddepth, 0, 1);
1856 if( sdepth != ddepth )
1859 GaussianBlur(src, dst, Size(5, 5), 1.2, 1.2);
1861 blur(src, dst, Size(11, 11));
1863 morphologyEx(src, dst, MORPH_GRADIENT, elem_ellipse);
1865 morphologyEx(src, dst, MORPH_GRADIENT, elem_rect);
1870 ts->printf(cvtest::TS::LOG, "Combination of depths %d => %d in %s is not supported (yet it should be)",
1871 depths[i][0], depths[i][1],
1872 fidx == 0 ? "filter2D (small kernel)" :
1873 fidx == 1 ? "filter2D (large kernel)" :
1874 fidx == 2 ? "sepFilter2D" :
1875 fidx == 3 ? "sepFilter2D (symmetrical/asymmetrical kernel)" :
1876 fidx == 4 ? "Sobel" :
1877 fidx == 5 ? "Scharr" :
1878 fidx == 6 ? "GaussianBlur" :
1879 fidx == 7 ? "blur" :
1880 fidx == 8 || fidx == 9 ? "morphologyEx" :
1883 ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
1888 TEST(Imgproc_Filtering, supportedFormats) { CV_FilterSupportedFormatsTest test; test.safe_run(); }
1890 TEST(Imgproc_Blur, borderTypes)
1892 Size kernelSize(3, 3);
1894 /// ksize > src_roi.size()
1895 Mat src(3, 3, CV_8UC1, cv::Scalar::all(255)), dst;
1896 Mat src_roi = src(Rect(1, 1, 1, 1));
1897 src_roi.setTo(cv::Scalar::all(0));
1899 // should work like !BORDER_ISOLATED
1900 blur(src_roi, dst, kernelSize, Point(-1, -1), BORDER_REPLICATE);
1901 EXPECT_EQ(227, dst.at<uchar>(0, 0));
1903 // should work like BORDER_ISOLATED
1904 blur(src_roi, dst, kernelSize, Point(-1, -1), BORDER_REPLICATE | BORDER_ISOLATED);
1905 EXPECT_EQ(0, dst.at<uchar>(0, 0));
1907 /// ksize <= src_roi.size()
1908 src = Mat(5, 5, CV_8UC1, cv::Scalar(255));
1909 src_roi = src(Rect(1, 1, 3, 3));
1911 src.at<uchar>(2, 2) = 255;
1913 // should work like !BORDER_ISOLATED
1914 blur(src_roi, dst, kernelSize, Point(-1, -1), BORDER_REPLICATE);
1916 (Mat_<uchar>(3, 3) << 170, 113, 170, 113, 28, 113, 170, 113, 170);
1917 EXPECT_EQ(expected_dst.type(), dst.type());
1918 EXPECT_EQ(expected_dst.size(), dst.size());
1919 EXPECT_DOUBLE_EQ(0.0, cvtest::norm(expected_dst, dst, NORM_INF));