Home | History | Annotate | Download | only in test
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 #include "test_precomp.hpp"
     43 
     44 using namespace cv;
     45 using namespace std;
     46 
     47 class CV_FilterBaseTest : public cvtest::ArrayTest
     48 {
     49 public:
     50     CV_FilterBaseTest( bool _fp_kernel );
     51 
     52 protected:
     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 );
     57     CvSize aperture_size;
     58     CvPoint anchor;
     59     int max_aperture_size;
     60     bool fp_kernel;
     61     bool inplace;
     62     int border;
     63 };
     64 
     65 
     66 CV_FilterBaseTest::CV_FilterBaseTest( bool _fp_kernel ) : fp_kernel(_fp_kernel)
     67 {
     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;
     73     inplace = false;
     74     aperture_size = cvSize(0,0);
     75     anchor = cvPoint(0,0);
     76     element_wise_relative_error = false;
     77 }
     78 
     79 
     80 int CV_FilterBaseTest::read_params( CvFileStorage* fs )
     81 {
     82     int code = cvtest::ArrayTest::read_params( fs );
     83     if( code < 0 )
     84         return code;
     85 
     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 );
     88 
     89     return code;
     90 }
     91 
     92 
     93 void CV_FilterBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
     94 {
     95     cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
     96     if( i == INPUT )
     97     {
     98         if( j == 1 )
     99         {
    100             if( fp_kernel )
    101             {
    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);
    106             }
    107             else
    108             {
    109                 low = Scalar::all(0);
    110                 high = Scalar::all(2);
    111             }
    112         }
    113         else if( CV_MAT_DEPTH(type) == CV_16U )
    114         {
    115             low = Scalar::all(0.);
    116             high = Scalar::all(40000.);
    117         }
    118         else if( CV_MAT_DEPTH(type) == CV_32F )
    119         {
    120             low = Scalar::all(-10.);
    121             high = Scalar::all(10.);
    122         }
    123     }
    124 }
    125 
    126 
    127 void CV_FilterBaseTest::get_test_array_types_and_sizes( int test_case_idx,
    128                                                         vector<vector<Size> >& sizes,
    129                                                         vector<vector<int> >& types )
    130 {
    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;
    136     cn += cn == 2;
    137 
    138     types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
    139 
    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;
    144 
    145     types[INPUT][1] = fp_kernel ? CV_32FC1 : CV_8UC1;
    146     sizes[INPUT][1] = aperture_size;
    147 
    148     inplace = cvtest::randInt(rng) % 2 != 0;
    149     border = BORDER_REPLICATE;
    150 }
    151 
    152 
    153 int CV_FilterBaseTest::prepare_test_case( int test_case_idx )
    154 {
    155     int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
    156     if( code > 0 )
    157     {
    158         if( inplace && test_mat[INPUT][0].type() == test_mat[OUTPUT][0].type())
    159             cvtest::copy( test_mat[INPUT][0], test_mat[OUTPUT][0] );
    160         else
    161             inplace = false;
    162     }
    163     return code;
    164 }
    165 
    166 
    167 /////////////////////////
    168 
    169 class CV_MorphologyBaseTest : public CV_FilterBaseTest
    170 {
    171 public:
    172     CV_MorphologyBaseTest();
    173 
    174 protected:
    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;
    180     int shape;
    181     IplConvKernel* element;
    182 };
    183 
    184 
    185 CV_MorphologyBaseTest::CV_MorphologyBaseTest() : CV_FilterBaseTest( false )
    186 {
    187     shape = -1;
    188     element = 0;
    189     optype = optype_min = optype_max = -1;
    190 }
    191 
    192 
    193 void CV_MorphologyBaseTest::get_test_array_types_and_sizes( int test_case_idx,
    194                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
    195 {
    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]);
    201 
    202     types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
    203     shape = cvtest::randInt(rng) % 4;
    204     if( shape >= 3 )
    205         shape = CV_SHAPE_CUSTOM;
    206     else
    207         sizes[INPUT][1] = cvSize(0,0);
    208     optype = cvtest::randInt(rng) % (optype_max - optype_min + 1) + optype_min;
    209 }
    210 
    211 
    212 double CV_MorphologyBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
    213 {
    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;
    217 }
    218 
    219 
    220 int CV_MorphologyBaseTest::prepare_test_case( int test_case_idx )
    221 {
    222     int code = CV_FilterBaseTest::prepare_test_case( test_case_idx );
    223     vector<int> eldata;
    224 
    225     if( code <= 0 )
    226         return code;
    227 
    228     if( shape == CV_SHAPE_CUSTOM )
    229     {
    230         eldata.resize(aperture_size.width*aperture_size.height);
    231         const uchar* src = test_mat[INPUT][1].ptr();
    232         int srcstep = (int)test_mat[INPUT][1].step;
    233         int i, j, nonzero = 0;
    234 
    235         for( i = 0; i < aperture_size.height; i++ )
    236         {
    237             for( j = 0; j < aperture_size.width; j++ )
    238             {
    239                 eldata[i*aperture_size.width + j] = src[i*srcstep + j];
    240                 nonzero += src[i*srcstep + j] != 0;
    241             }
    242         }
    243 
    244         if( nonzero == 0 )
    245             eldata[anchor.y*aperture_size.width + anchor.x] = 1;
    246     }
    247 
    248     cvReleaseStructuringElement( &element );
    249     element = cvCreateStructuringElementEx( aperture_size.width, aperture_size.height,
    250                                            anchor.x, anchor.y, shape, eldata.empty() ? 0 : &eldata[0] );
    251     return code;
    252 }
    253 
    254 
    255 void CV_MorphologyBaseTest::prepare_to_validation( int /*test_case_idx*/ )
    256 {
    257     Mat& src = test_mat[INPUT][0], &dst = test_mat[REF_OUTPUT][0];
    258     Mat _ielement(element->nRows, element->nCols, CV_32S, element->values);
    259     Mat _element;
    260     _ielement.convertTo(_element, CV_8U);
    261     Point _anchor(element->anchorX, element->anchorY);
    262     int _border = BORDER_REPLICATE;
    263 
    264     if( optype == CV_MOP_ERODE )
    265     {
    266         cvtest::erode( src, dst, _element, _anchor, _border );
    267     }
    268     else if( optype == CV_MOP_DILATE )
    269     {
    270         cvtest::dilate( src, dst, _element, _anchor, _border );
    271     }
    272     else
    273     {
    274         Mat temp;
    275         if( optype == CV_MOP_OPEN )
    276         {
    277             cvtest::erode( src, temp, _element, _anchor, _border );
    278             cvtest::dilate( temp, dst, _element, _anchor, _border );
    279         }
    280         else if( optype == CV_MOP_CLOSE )
    281         {
    282             cvtest::dilate( src, temp, _element, _anchor, _border );
    283             cvtest::erode( temp, dst, _element, _anchor, _border );
    284         }
    285         else if( optype == CV_MOP_GRADIENT )
    286         {
    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() );
    290         }
    291         else if( optype == CV_MOP_TOPHAT )
    292         {
    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() );
    296         }
    297         else if( optype == CV_MOP_BLACKHAT )
    298         {
    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() );
    302         }
    303         else
    304             CV_Error( CV_StsBadArg, "Unknown operation" );
    305     }
    306 
    307     cvReleaseStructuringElement( &element );
    308 }
    309 
    310 
    311 /////////////// erode ///////////////
    312 
    313 class CV_ErodeTest : public CV_MorphologyBaseTest
    314 {
    315 public:
    316     CV_ErodeTest();
    317 protected:
    318     void run_func();
    319 };
    320 
    321 
    322 CV_ErodeTest::CV_ErodeTest()
    323 {
    324     optype_min = optype_max = CV_MOP_ERODE;
    325 }
    326 
    327 
    328 void CV_ErodeTest::run_func()
    329 {
    330     cvErode( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
    331              test_array[OUTPUT][0], element, 1 );
    332 }
    333 
    334 
    335 /////////////// dilate ///////////////
    336 
    337 class CV_DilateTest : public CV_MorphologyBaseTest
    338 {
    339 public:
    340     CV_DilateTest();
    341 protected:
    342     void run_func();
    343 };
    344 
    345 
    346 CV_DilateTest::CV_DilateTest()
    347 {
    348     optype_min = optype_max = CV_MOP_DILATE;
    349 }
    350 
    351 
    352 void CV_DilateTest::run_func()
    353 {
    354     cvDilate( inplace ? test_array[OUTPUT][0] : test_array[INPUT][0],
    355              test_array[OUTPUT][0], element, 1 );
    356 }
    357 
    358 /////////////// morphEx ///////////////
    359 
    360 class CV_MorphExTest : public CV_MorphologyBaseTest
    361 {
    362 public:
    363     CV_MorphExTest();
    364 protected:
    365     void run_func();
    366 };
    367 
    368 
    369 CV_MorphExTest::CV_MorphExTest()
    370 {
    371     optype_min = CV_MOP_ERODE;
    372     optype_max = CV_MOP_BLACKHAT;
    373 }
    374 
    375 
    376 void CV_MorphExTest::run_func()
    377 {
    378     cvMorphologyEx( test_array[inplace ? OUTPUT : INPUT][0],
    379              test_array[OUTPUT][0], 0, element, optype, 1 );
    380 }
    381 
    382 /////////////// generic filter ///////////////
    383 
    384 class CV_FilterTest : public CV_FilterBaseTest
    385 {
    386 public:
    387     CV_FilterTest();
    388 
    389 protected:
    390     void prepare_to_validation( int test_case_idx );
    391     void run_func();
    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 );
    394 };
    395 
    396 
    397 CV_FilterTest::CV_FilterTest() : CV_FilterBaseTest( true )
    398 {
    399 }
    400 
    401 
    402 void CV_FilterTest::get_test_array_types_and_sizes( int test_case_idx,
    403                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
    404 {
    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);
    411 }
    412 
    413 
    414 double CV_FilterTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
    415 {
    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;
    419 }
    420 
    421 
    422 void CV_FilterTest::run_func()
    423 {
    424     CvMat kernel = test_mat[INPUT][1];
    425     cvFilter2D( test_array[inplace ? OUTPUT : INPUT][0],
    426                 test_array[OUTPUT][0], &kernel, anchor );
    427 }
    428 
    429 
    430 void CV_FilterTest::prepare_to_validation( int /*test_case_idx*/ )
    431 {
    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 );
    434 }
    435 
    436 
    437 ////////////////////////
    438 
    439 class CV_DerivBaseTest : public CV_FilterBaseTest
    440 {
    441 public:
    442     CV_DerivBaseTest();
    443 protected:
    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 );
    446     int _aperture_size;
    447 };
    448 
    449 
    450 CV_DerivBaseTest::CV_DerivBaseTest() : CV_FilterBaseTest( true )
    451 {
    452     max_aperture_size = 7;
    453 }
    454 
    455 
    456 void CV_DerivBaseTest::get_test_array_types_and_sizes( int test_case_idx,
    457                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
    458 {
    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);
    467 }
    468 
    469 
    470 double CV_DerivBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
    471 {
    472     int depth = test_mat[INPUT][0].depth();
    473     return depth <= CV_8S ? 2 : 5e-4;
    474 }
    475 
    476 
    477 /////////////// sobel ///////////////
    478 
    479 class CV_SobelTest : public CV_DerivBaseTest
    480 {
    481 public:
    482     CV_SobelTest();
    483 
    484 protected:
    485     void prepare_to_validation( int test_case_idx );
    486     void run_func();
    487     void get_test_array_types_and_sizes( int test_case_idx,
    488         vector<vector<Size> >& sizes, vector<vector<int> >& types );
    489     int dx, dy, origin;
    490 };
    491 
    492 
    493 CV_SobelTest::CV_SobelTest() {}
    494 
    495 
    496 void CV_SobelTest::get_test_array_types_and_sizes( int test_case_idx,
    497                                                    vector<vector<Size> >& sizes,
    498                                                    vector<vector<int> >& types )
    499 {
    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 )
    507         dx = 1;
    508     if( cvtest::randInt(rng) % 2 )
    509     {
    510         int t;
    511         CV_SWAP( dx, dy, t );
    512     }
    513 
    514     if( _aperture_size < 0 )
    515         aperture_size = cvSize(3, 3);
    516     else if( _aperture_size == 1 )
    517     {
    518         if( dx == 0 )
    519             aperture_size = cvSize(1, 3);
    520         else if( dy == 0 )
    521             aperture_size = cvSize(3, 1);
    522         else
    523         {
    524             _aperture_size = 3;
    525             aperture_size = cvSize(3, 3);
    526         }
    527     }
    528     else
    529         aperture_size = cvSize(_aperture_size, _aperture_size);
    530 
    531     sizes[INPUT][1] = aperture_size;
    532     anchor.x = aperture_size.width / 2;
    533     anchor.y = aperture_size.height / 2;
    534 }
    535 
    536 
    537 void CV_SobelTest::run_func()
    538 {
    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 );*/
    544 }
    545 
    546 
    547 void CV_SobelTest::prepare_to_validation( int /*test_case_idx*/ )
    548 {
    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);
    552 }
    553 
    554 
    555 /////////////// laplace ///////////////
    556 
    557 class CV_LaplaceTest : public CV_DerivBaseTest
    558 {
    559 public:
    560     CV_LaplaceTest();
    561 
    562 protected:
    563     int prepare_test_case( int test_case_idx );
    564     void prepare_to_validation( int test_case_idx );
    565     void run_func();
    566     void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
    567 };
    568 
    569 
    570 CV_LaplaceTest::CV_LaplaceTest()
    571 {
    572 }
    573 
    574 
    575 void CV_LaplaceTest::get_test_array_types_and_sizes( int test_case_idx,
    576                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
    577 {
    578     CV_DerivBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
    579     if( _aperture_size <= 1 )
    580     {
    581         if( _aperture_size < 0 )
    582             _aperture_size = 1;
    583         aperture_size = cvSize(3, 3);
    584     }
    585     else
    586         aperture_size = cvSize(_aperture_size, _aperture_size);
    587 
    588     sizes[INPUT][1] = aperture_size;
    589     anchor.x = aperture_size.width / 2;
    590     anchor.y = aperture_size.height / 2;
    591 }
    592 
    593 
    594 void CV_LaplaceTest::run_func()
    595 {
    596     cvLaplace( test_array[inplace ? OUTPUT : INPUT][0],
    597                test_array[OUTPUT][0], _aperture_size );
    598 }
    599 
    600 
    601 int CV_LaplaceTest::prepare_test_case( int test_case_idx )
    602 {
    603     int code = CV_DerivBaseTest::prepare_test_case( test_case_idx );
    604     return _aperture_size < 0 ? 0 : code;
    605 }
    606 
    607 
    608 void CV_LaplaceTest::prepare_to_validation( int /*test_case_idx*/ )
    609 {
    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 );
    613 }
    614 
    615 
    616 ////////////////////////////////////////////////////////////
    617 
    618 class CV_SmoothBaseTest : public CV_FilterBaseTest
    619 {
    620 public:
    621     CV_SmoothBaseTest();
    622 
    623 protected:
    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;
    627 };
    628 
    629 
    630 CV_SmoothBaseTest::CV_SmoothBaseTest() : CV_FilterBaseTest( true )
    631 {
    632     smooth_type = "";
    633 }
    634 
    635 
    636 void CV_SmoothBaseTest::get_test_array_types_and_sizes( int test_case_idx,
    637                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
    638 {
    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;
    650 }
    651 
    652 
    653 double CV_SmoothBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
    654 {
    655     int depth = test_mat[INPUT][0].depth();
    656     return depth <= CV_8S ? 1 : 1e-5;
    657 }
    658 
    659 
    660 /////////////// blur ///////////////
    661 
    662 class CV_BlurTest : public CV_SmoothBaseTest
    663 {
    664 public:
    665     CV_BlurTest();
    666 
    667 protected:
    668     int prepare_test_case( int test_case_idx );
    669     void prepare_to_validation( int test_case_idx );
    670     void run_func();
    671     void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
    672     bool normalize;
    673 };
    674 
    675 
    676 CV_BlurTest::CV_BlurTest()
    677 {
    678 }
    679 
    680 
    681 void CV_BlurTest::get_test_array_types_and_sizes( int test_case_idx,
    682                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
    683 {
    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;
    691     if( !normalize )
    692     {
    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);
    695     }
    696 }
    697 
    698 
    699 void CV_BlurTest::run_func()
    700 {
    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 );
    704 }
    705 
    706 
    707 int CV_BlurTest::prepare_test_case( int test_case_idx )
    708 {
    709     int code = CV_SmoothBaseTest::prepare_test_case( test_case_idx );
    710     return code > 0 && !normalize && test_mat[INPUT][0].channels() > 1 ? 0 : code;
    711 }
    712 
    713 
    714 void CV_BlurTest::prepare_to_validation( int /*test_case_idx*/ )
    715 {
    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 );
    720 }
    721 
    722 
    723 /////////////// gaussian ///////////////
    724 
    725 class CV_GaussianBlurTest : public CV_SmoothBaseTest
    726 {
    727 public:
    728     CV_GaussianBlurTest();
    729 
    730 protected:
    731     void prepare_to_validation( int test_case_idx );
    732     void run_func();
    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*/ );
    735     double sigma;
    736     int param1, param2;
    737 };
    738 
    739 
    740 CV_GaussianBlurTest::CV_GaussianBlurTest() : CV_SmoothBaseTest()
    741 {
    742     sigma = 0.;
    743     smooth_type = "Gaussian";
    744 }
    745 
    746 
    747 double CV_GaussianBlurTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
    748 {
    749     int depth = test_mat[INPUT][0].depth();
    750     return depth <= CV_8S ? 8 : 1e-5;
    751 }
    752 
    753 
    754 void CV_GaussianBlurTest::get_test_array_types_and_sizes( int test_case_idx,
    755                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
    756 {
    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);
    761 
    762     sigma = exp(cvtest::randReal(rng)*5-2);
    763     param1 = aperture_size.width;
    764     param2 = aperture_size.height;
    765 
    766     if( kernel_case == 0 )
    767         sigma = 0.;
    768 }
    769 
    770 void CV_GaussianBlurTest::run_func()
    771 {
    772     cvSmooth( test_array[inplace ? OUTPUT : INPUT][0],
    773               test_array[OUTPUT][0], CV_GAUSSIAN,
    774               param1, param2, sigma, sigma );
    775 }
    776 
    777 
    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
    781 static void
    782 calcGaussianKernel( int n, double sigma, vector<float>& kernel )
    783 {
    784     static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] =
    785     {
    786         {1.f},
    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}
    790     };
    791 
    792     kernel.resize(n);
    793     if( n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 )
    794     {
    795         assert( n%2 == 1 );
    796         memcpy( &kernel[0], small_gaussian_tab[n>>1], n*sizeof(kernel[0]));
    797     }
    798     else
    799     {
    800         double sigmaX = sigma > 0 ? sigma : (n/2 - 1)*0.3 + 0.8;
    801         double scale2X = -0.5/(sigmaX*sigmaX);
    802         double sum = 1.;
    803         int i;
    804         sum = kernel[n/2] = 1.f;
    805 
    806         for( i = 1; i <= n/2; i++ )
    807         {
    808             kernel[n/2+i] = kernel[n/2-i] = (float)exp(scale2X*i*i);
    809             sum += kernel[n/2+i]*2;
    810         }
    811 
    812         sum = 1./sum;
    813         for( i = 0; i <= n/2; i++ )
    814             kernel[n/2+i] = kernel[n/2-i] = (float)(kernel[n/2+i]*sum);
    815     }
    816 }
    817 
    818 
    819 static Mat calcGaussianKernel2D( Size ksize, double sigma )
    820 {
    821     vector<float> kx, ky;
    822     Mat kernel(ksize, CV_32F);
    823 
    824     calcGaussianKernel( kernel.cols, sigma, kx );
    825     calcGaussianKernel( kernel.rows, sigma, ky );
    826 
    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];
    830     return kernel;
    831 }
    832 
    833 
    834 void CV_GaussianBlurTest::prepare_to_validation( int /*test_case_idx*/ )
    835 {
    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 );
    839 }
    840 
    841 
    842 /////////////// median ///////////////
    843 
    844 class CV_MedianBlurTest : public CV_SmoothBaseTest
    845 {
    846 public:
    847     CV_MedianBlurTest();
    848 
    849 protected:
    850     void prepare_to_validation( int test_case_idx );
    851     double get_success_error_level( int test_case_idx, int i, int j );
    852     void run_func();
    853     void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
    854 };
    855 
    856 
    857 CV_MedianBlurTest::CV_MedianBlurTest()
    858 {
    859     smooth_type = "Median";
    860 }
    861 
    862 
    863 void CV_MedianBlurTest::get_test_array_types_and_sizes( int test_case_idx,
    864                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
    865 {
    866     CV_SmoothBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
    867     int depth = CV_8U;
    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);
    871 
    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);
    875 
    876     sizes[OUTPUT][0] = sizes[INPUT][0];
    877     sizes[REF_OUTPUT][0] = sizes[INPUT][0];
    878 
    879     inplace = false;
    880     border = BORDER_REPLICATE | BORDER_ISOLATED;
    881 }
    882 
    883 
    884 double CV_MedianBlurTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
    885 {
    886     return 0;
    887 }
    888 
    889 
    890 void CV_MedianBlurTest::run_func()
    891 {
    892     cvSmooth( test_array[INPUT][0], test_array[OUTPUT][0],
    893               CV_MEDIAN, aperture_size.width );
    894 }
    895 
    896 
    897 struct median_pair
    898 {
    899     int col;
    900     int val;
    901     median_pair() { }
    902     median_pair( int _col, int _val ) : col(_col), val(_val) { }
    903 };
    904 
    905 
    906 static void test_medianFilter( const Mat& src, Mat& dst, int m )
    907 {
    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());
    913 
    914     assert( src.rows == dst.rows + m - 1 && src.cols == dst.cols + m - 1 &&
    915             src.type() == dst.type() && src.type() == CV_8UC1 );
    916 
    917     for( i = 0; i < dst.rows; i++ )
    918     {
    919         uchar* dst1 = dst.ptr<uchar>(i);
    920         for( k = 0; k < m; k++ )
    921         {
    922             const uchar* src1 = src.ptr<uchar>(i+k);
    923             for( j = 0; j < m-1; j++ )
    924                 *buf0++ = median_pair(j, src1[j]);
    925         }
    926 
    927         n = m2 - m;
    928         buf0 -= n;
    929         for( k = n-1; k > 0; k-- )
    930         {
    931             int f = 0;
    932             for( j = 0; j < k; j++ )
    933             {
    934                 if( buf0[j].val > buf0[j+1].val )
    935                 {
    936                     median_pair t;
    937                     CV_SWAP( buf0[j], buf0[j+1], t );
    938                     f = 1;
    939                 }
    940             }
    941             if( !f )
    942                 break;
    943         }
    944 
    945         for( j = 0; j < dst.cols; j++ )
    946         {
    947             int ins_col = j + m - 1;
    948             int del_col = j - 1;
    949             const uchar* src1 = src.ptr<uchar>(i) + ins_col;
    950             for( k = 0; k < m; k++, src1 += step )
    951             {
    952                 col_buf[k] = src1[0];
    953                 for( l = k-1; l >= 0; l-- )
    954                 {
    955                     int t;
    956                     if( col_buf[l] < col_buf[l+1] )
    957                         break;
    958                     CV_SWAP( col_buf[l], col_buf[l+1], t );
    959                 }
    960             }
    961 
    962             col_buf[m] = INT_MAX;
    963 
    964             for( k = 0, l = 0; k < n; )
    965             {
    966                 if( buf0[k].col == del_col )
    967                     k++;
    968                 else if( buf0[k].val < col_buf[l] )
    969                     *buf1++ = buf0[k++];
    970                 else
    971                 {
    972                     assert( col_buf[l] < INT_MAX );
    973                     *buf1++ = median_pair(ins_col,col_buf[l++]);
    974                 }
    975             }
    976 
    977             for( ; l < m; l++ )
    978                 *buf1++ = median_pair(ins_col,col_buf[l]);
    979 
    980             if( del_col < 0 )
    981                 n += m;
    982             buf1 -= n;
    983             assert( n == m2 );
    984             dst1[j] = (uchar)buf1[n/2].val;
    985             median_pair* tbuf;
    986             CV_SWAP( buf0, buf1, tbuf );
    987         }
    988     }
    989 }
    990 
    991 
    992 void CV_MedianBlurTest::prepare_to_validation( int /*test_case_idx*/ )
    993 {
    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());
   1000     Mat dst;
   1001     if( cn == 1 )
   1002         dst = dst0;
   1003     else
   1004         dst.create(src0.size(), src0.depth());
   1005 
   1006     for( i = 0; i < cn; i++ )
   1007     {
   1008         Mat ptr = src0;
   1009         if( cn > 1 )
   1010         {
   1011             cvtest::extract( src0, dst, i );
   1012             ptr = dst;
   1013         }
   1014         cvtest::copyMakeBorder( ptr, src, m/2, m/2, m/2, m/2, border & ~BORDER_ISOLATED );
   1015         test_medianFilter( src, dst, m );
   1016         if( cn > 1 )
   1017             cvtest::insert( dst, dst0, i );
   1018     }
   1019 }
   1020 
   1021 
   1022 /////////////// pyramid tests ///////////////
   1023 
   1024 class CV_PyramidBaseTest : public CV_FilterBaseTest
   1025 {
   1026 public:
   1027     CV_PyramidBaseTest( bool downsample );
   1028 
   1029 protected:
   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 );
   1032     bool downsample;
   1033     Mat kernel;
   1034 };
   1035 
   1036 
   1037 CV_PyramidBaseTest::CV_PyramidBaseTest( bool _downsample ) : CV_FilterBaseTest(true)
   1038 {
   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.);
   1043 }
   1044 
   1045 
   1046 double CV_PyramidBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
   1047 {
   1048     int depth = test_mat[INPUT][0].depth();
   1049     return depth < CV_32F ? 1 : 1e-5;
   1050 }
   1051 
   1052 
   1053 void CV_PyramidBaseTest::get_test_array_types_and_sizes( int test_case_idx,
   1054                                                          vector<vector<Size> >& sizes,
   1055                                                          vector<vector<int> >& types )
   1056 {
   1057     const int channels[] = {1, 3, 4};
   1058     const int depthes[] = {CV_8U, CV_16S, CV_16U, CV_32F};
   1059 
   1060     RNG& rng = ts->get_rng();
   1061     CvSize sz;
   1062     CV_FilterBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
   1063 
   1064     int depth = depthes[cvtest::randInt(rng) % (sizeof(depthes)/sizeof(depthes[0]))];
   1065     int cn = channels[cvtest::randInt(rng) % (sizeof(channels)/sizeof(channels[0]))];
   1066 
   1067     aperture_size = cvSize(5,5);
   1068     anchor = cvPoint(aperture_size.width/2, aperture_size.height/2);
   1069 
   1070     types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
   1071 
   1072     sz.width = MAX( sizes[INPUT][0].width/2, 1 );
   1073     sz.height = MAX( sizes[INPUT][0].height/2, 1 );
   1074 
   1075     if( downsample )
   1076     {
   1077         sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
   1078         sz.width *= 2;
   1079         sz.height *= 2;
   1080         sizes[INPUT][0] = sz;
   1081     }
   1082     else
   1083     {
   1084         sizes[INPUT][0] = sz;
   1085         sz.width *= 2;
   1086         sz.height *= 2;
   1087         sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
   1088     }
   1089 
   1090     sizes[INPUT][1] = aperture_size;
   1091     inplace = false;
   1092 }
   1093 
   1094 
   1095 /////// pyrdown ////////
   1096 
   1097 class CV_PyramidDownTest : public CV_PyramidBaseTest
   1098 {
   1099 public:
   1100     CV_PyramidDownTest();
   1101 
   1102 protected:
   1103     void run_func();
   1104     void prepare_to_validation( int );
   1105 };
   1106 
   1107 
   1108 CV_PyramidDownTest::CV_PyramidDownTest() : CV_PyramidBaseTest( true )
   1109 {
   1110 }
   1111 
   1112 
   1113 void CV_PyramidDownTest::run_func()
   1114 {
   1115     cvPyrDown( test_array[INPUT][0], test_array[OUTPUT][0], CV_GAUSSIAN_5x5 );
   1116 }
   1117 
   1118 
   1119 void CV_PyramidDownTest::prepare_to_validation( int /*test_case_idx*/ )
   1120 {
   1121     Mat& src = test_mat[INPUT][0], &dst = test_mat[REF_OUTPUT][0];
   1122     Mat temp;
   1123     cvtest::filter2D(src, temp, src.depth(),
   1124                      kernel, Point(kernel.cols/2, kernel.rows/2),
   1125                      0, BORDER_REFLECT_101);
   1126 
   1127     size_t elem_size = temp.elemSize();
   1128     size_t ncols = dst.cols*elem_size;
   1129 
   1130     for( int i = 0; i < dst.rows; i++ )
   1131     {
   1132         const uchar* src_row = temp.ptr(i*2);
   1133         uchar* dst_row = dst.ptr(i);
   1134 
   1135         for( size_t j = 0; j < ncols; j += elem_size )
   1136         {
   1137             for( size_t k = 0; k < elem_size; k++ )
   1138                 dst_row[j+k] = src_row[j*2+k];
   1139         }
   1140     }
   1141 }
   1142 
   1143 
   1144 /////// pyrup ////////
   1145 
   1146 class CV_PyramidUpTest : public CV_PyramidBaseTest
   1147 {
   1148 public:
   1149     CV_PyramidUpTest();
   1150 
   1151 protected:
   1152     void run_func();
   1153     void prepare_to_validation( int );
   1154 };
   1155 
   1156 
   1157 CV_PyramidUpTest::CV_PyramidUpTest() : CV_PyramidBaseTest( false )
   1158 {
   1159 }
   1160 
   1161 
   1162 void CV_PyramidUpTest::run_func()
   1163 {
   1164     cvPyrUp( test_array[INPUT][0], test_array[OUTPUT][0], CV_GAUSSIAN_5x5 );
   1165 }
   1166 
   1167 
   1168 void CV_PyramidUpTest::prepare_to_validation( int /*test_case_idx*/ )
   1169 {
   1170     Mat& src = test_mat[INPUT][0], &dst = test_mat[REF_OUTPUT][0];
   1171     Mat temp(dst.size(), dst.type());
   1172 
   1173     size_t elem_size = src.elemSize();
   1174     size_t ncols = src.cols*elem_size;
   1175 
   1176     for( int i = 0; i < src.rows; i++ )
   1177     {
   1178         const uchar* src_row = src.ptr(i);
   1179         uchar* dst_row = temp.ptr(i*2);
   1180 
   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 )
   1184         {
   1185             for( size_t k = 0; k < elem_size; k++ )
   1186             {
   1187                 dst_row[j*2+k] = src_row[j+k];
   1188                 dst_row[j*2+k+elem_size] = 0;
   1189             }
   1190         }
   1191     }
   1192 
   1193     cvtest::filter2D(temp, dst, dst.depth(),
   1194                      kernel, Point(kernel.cols/2, kernel.rows/2),
   1195                      0, BORDER_REFLECT_101);
   1196 }
   1197 
   1198 
   1199 //////////////////////// feature selection //////////////////////////
   1200 
   1201 class CV_FeatureSelBaseTest : public cvtest::ArrayTest
   1202 {
   1203 public:
   1204     CV_FeatureSelBaseTest( int width_factor );
   1205 
   1206 protected:
   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;
   1213     int max_block_size;
   1214     int width_factor;
   1215 };
   1216 
   1217 
   1218 CV_FeatureSelBaseTest::CV_FeatureSelBaseTest( int _width_factor )
   1219 {
   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;
   1228 }
   1229 
   1230 
   1231 int CV_FeatureSelBaseTest::read_params( CvFileStorage* fs )
   1232 {
   1233     int code = cvtest::BaseTest::read_params( fs );
   1234     if( code < 0 )
   1235         return code;
   1236 
   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 );
   1241 
   1242     return code;
   1243 }
   1244 
   1245 
   1246 double CV_FeatureSelBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
   1247 {
   1248     int depth = test_mat[INPUT][0].depth();
   1249     return depth <= CV_8S ? 3e-2 : depth == CV_32F ? 1e-3 : 1e-10;
   1250 }
   1251 
   1252 
   1253 void CV_FeatureSelBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
   1254 {
   1255     cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
   1256     if( i == INPUT && CV_MAT_DEPTH(type) == CV_32F )
   1257     {
   1258         low = Scalar::all(-10.);
   1259         high = Scalar::all(10.);
   1260     }
   1261 }
   1262 
   1263 
   1264 void CV_FeatureSelBaseTest::get_test_array_types_and_sizes( int test_case_idx,
   1265                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
   1266 {
   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;
   1270 
   1271     depth = depth == 0 ? CV_8U : CV_32F;
   1272     types[INPUT][0] = depth;
   1273     types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_32FC1;
   1274 
   1275     aperture_size = (cvtest::randInt(rng) % (max_aperture_size+2) - 1) | 1;
   1276     if( aperture_size == 1 )
   1277         aperture_size = 3;
   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 )
   1282         block_size = 3;
   1283     asz = aperture_size > 0 ? aperture_size : 3;
   1284 
   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;
   1289 }
   1290 
   1291 
   1292 static void
   1293 test_cornerEigenValsVecs( const Mat& src, Mat& eigenv, Mat& ocv_eigenv,
   1294                           int block_size, int _aperture_size, int mode )
   1295 {
   1296     int i, j;
   1297     int aperture_size = _aperture_size < 0 ? 3 : _aperture_size;
   1298     Point anchor( aperture_size/2, aperture_size/2 );
   1299 
   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)) );
   1305 
   1306     int type = src.type();
   1307     int ftype = CV_32FC1;
   1308     double kernel_scale = type != ftype ? 1./255 : 1;
   1309 
   1310     Mat dx2, dy2, dxdy(src.size(), CV_32F), kernel;
   1311 
   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 );
   1316 
   1317     double denom = (1 << (aperture_size-1))*block_size;
   1318     denom = denom * denom;
   1319     if( _aperture_size < 0 )
   1320         denom *= 4;
   1321     denom = 1./denom;
   1322 
   1323     for( i = 0; i < src.rows; i++ )
   1324     {
   1325         float* dxdyp = dxdy.ptr<float>(i);
   1326         float* dx2p = dx2.ptr<float>(i);
   1327         float* dy2p = dy2.ptr<float>(i);
   1328 
   1329         for( j = 0; j < src.cols; j++ )
   1330         {
   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);
   1335         }
   1336     }
   1337 
   1338     kernel = Mat::ones(block_size, block_size, CV_32F);
   1339     anchor = Point(block_size/2, block_size/2);
   1340 
   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 );
   1344 
   1345     if( mode == 0 )
   1346     {
   1347         for( i = 0; i < src.rows; i++ )
   1348         {
   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);
   1354 
   1355             for( j = 0; j < src.cols; j++ )
   1356             {
   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;
   1362 
   1363                 if( fabs(a - l1) + fabs(b) >= 1e-3 )
   1364                     x1 = b, y1 = l1 - a;
   1365                 else
   1366                     x1 = l1 - c, y1 = b;
   1367                 s = 1./(sqrt(x1*x1+y1*y1)+DBL_EPSILON);
   1368                 x1 *= s; y1 *= s;
   1369 
   1370                 if( fabs(a - l2) + fabs(b) >= 1e-3 )
   1371                     x2 = b, y2 = l2 - a;
   1372                 else
   1373                     x2 = l2 - c, y2 = b;
   1374                 s = 1./(sqrt(x2*x2+y2*y2)+DBL_EPSILON);
   1375                 x2 *= s; y2 *= s;
   1376 
   1377                 /* the orientation of eigen vectors might be inversed relative to OpenCV function,
   1378                    which is normal */
   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) )
   1381                     x1 = -x1, y1 = -y1;
   1382 
   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) )
   1385                     x2 = -x2, y2 = -y2;
   1386 
   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;
   1393             }
   1394         }
   1395     }
   1396     else if( mode == 1 )
   1397     {
   1398         for( i = 0; i < src.rows; i++ )
   1399         {
   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);
   1404 
   1405             for( j = 0; j < src.cols; j++ )
   1406             {
   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));
   1410             }
   1411         }
   1412     }
   1413 }
   1414 
   1415 
   1416 // min eigenval
   1417 class CV_MinEigenValTest : public CV_FeatureSelBaseTest
   1418 {
   1419 public:
   1420     CV_MinEigenValTest();
   1421 
   1422 protected:
   1423     void run_func();
   1424     void prepare_to_validation( int );
   1425 };
   1426 
   1427 
   1428 CV_MinEigenValTest::CV_MinEigenValTest() : CV_FeatureSelBaseTest( 1 )
   1429 {
   1430 }
   1431 
   1432 
   1433 void CV_MinEigenValTest::run_func()
   1434 {
   1435     cvCornerMinEigenVal( test_array[INPUT][0], test_array[OUTPUT][0],
   1436                          block_size, aperture_size );
   1437 }
   1438 
   1439 
   1440 void CV_MinEigenValTest::prepare_to_validation( int /*test_case_idx*/ )
   1441 {
   1442     test_cornerEigenValsVecs( test_mat[INPUT][0], test_mat[REF_OUTPUT][0],
   1443                     test_mat[OUTPUT][0], block_size, aperture_size, 1 );
   1444 }
   1445 
   1446 
   1447 // eigenval's & vec's
   1448 class CV_EigenValVecTest : public CV_FeatureSelBaseTest
   1449 {
   1450 public:
   1451     CV_EigenValVecTest();
   1452 
   1453 protected:
   1454     void run_func();
   1455     void prepare_to_validation( int );
   1456 };
   1457 
   1458 
   1459 CV_EigenValVecTest::CV_EigenValVecTest() : CV_FeatureSelBaseTest( 6 )
   1460 {
   1461 }
   1462 
   1463 
   1464 void CV_EigenValVecTest::run_func()
   1465 {
   1466     cvCornerEigenValsAndVecs( test_array[INPUT][0], test_array[OUTPUT][0],
   1467                               block_size, aperture_size );
   1468 }
   1469 
   1470 
   1471 void CV_EigenValVecTest::prepare_to_validation( int /*test_case_idx*/ )
   1472 {
   1473     test_cornerEigenValsVecs( test_mat[INPUT][0], test_mat[REF_OUTPUT][0],
   1474                     test_mat[OUTPUT][0], block_size, aperture_size, 0 );
   1475 }
   1476 
   1477 
   1478 // precornerdetect
   1479 class CV_PreCornerDetectTest : public CV_FeatureSelBaseTest
   1480 {
   1481 public:
   1482     CV_PreCornerDetectTest();
   1483 
   1484 protected:
   1485     void run_func();
   1486     void prepare_to_validation( int );
   1487     int prepare_test_case( int );
   1488 };
   1489 
   1490 
   1491 CV_PreCornerDetectTest::CV_PreCornerDetectTest() : CV_FeatureSelBaseTest( 1 )
   1492 {
   1493 }
   1494 
   1495 
   1496 void CV_PreCornerDetectTest::run_func()
   1497 {
   1498     cvPreCornerDetect( test_array[INPUT][0], test_array[OUTPUT][0], aperture_size );
   1499 }
   1500 
   1501 
   1502 int CV_PreCornerDetectTest::prepare_test_case( int test_case_idx )
   1503 {
   1504     int code = CV_FeatureSelBaseTest::prepare_test_case( test_case_idx );
   1505     if( aperture_size < 0 )
   1506         aperture_size = 3;
   1507     return code;
   1508 }
   1509 
   1510 
   1511 void CV_PreCornerDetectTest::prepare_to_validation( int /*test_case_idx*/ )
   1512 {
   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];
   1517 
   1518     int type = src.type(), ftype = CV_32FC1;
   1519     Point anchor(aperture_size/2, aperture_size/2);
   1520 
   1521     double kernel_scale = type != ftype ? 1./255 : 1.;
   1522 
   1523     Mat dx, dy, d2x, d2y, dxy, kernel;
   1524 
   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);
   1535 
   1536     double denom = 1 << (aperture_size-1);
   1537     denom = denom * denom * denom;
   1538     denom = 1./denom;
   1539 
   1540     for( int i = 0; i < src.rows; i++ )
   1541     {
   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);
   1548 
   1549         for( int j = 0; j < src.cols; j++ )
   1550         {
   1551             double x = _dx[j];
   1552             double y = _dy[j];
   1553 
   1554             corner[j] = (float)(denom*(x*x*_d2y[j] + y*y*_d2x[j] - 2*x*y*_dxy[j]));
   1555         }
   1556     }
   1557 }
   1558 
   1559 
   1560 ///////// integral /////////
   1561 
   1562 class CV_IntegralTest : public cvtest::ArrayTest
   1563 {
   1564 public:
   1565     CV_IntegralTest();
   1566 
   1567 protected:
   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 );
   1571     void run_func();
   1572     void prepare_to_validation( int );
   1573 
   1574     int prepare_test_case( int test_case_idx );
   1575 };
   1576 
   1577 
   1578 CV_IntegralTest::CV_IntegralTest()
   1579 {
   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;
   1588 }
   1589 
   1590 
   1591 void CV_IntegralTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
   1592 {
   1593     cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
   1594     int depth = CV_MAT_DEPTH(type);
   1595     if( depth == CV_32F )
   1596     {
   1597         low = Scalar::all(-10.);
   1598         high = Scalar::all(10.);
   1599     }
   1600 }
   1601 
   1602 
   1603 void CV_IntegralTest::get_test_array_types_and_sizes( int test_case_idx,
   1604                                                 vector<vector<Size> >& sizes, vector<vector<int> >& types )
   1605 {
   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 );
   1610     Size sum_size;
   1611 
   1612     depth = depth == 0 ? CV_8U : CV_32F;
   1613     cn += cn == 2;
   1614     int b = (cvtest::randInt(rng) & 1) != 0;
   1615     sum_depth = depth == CV_8U && b ? CV_32S : b ? CV_32F : CV_64F;
   1616 
   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);
   1621 
   1622     sum_size.width = sizes[INPUT][0].width + 1;
   1623     sum_size.height = sizes[INPUT][0].height + 1;
   1624 
   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);
   1628 
   1629     if( cvtest::randInt(rng) % 3 > 0 )
   1630     {
   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;
   1634     }
   1635 }
   1636 
   1637 
   1638 double CV_IntegralTest::get_success_error_level( int, int i, int j )
   1639 {
   1640     int depth = test_mat[i][j].depth();
   1641     return depth == CV_32S ? 0 : depth == CV_64F ? FLT_EPSILON : 5e-3;
   1642 }
   1643 
   1644 
   1645 int CV_IntegralTest::prepare_test_case( int test_case_idx )
   1646 {
   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;
   1650 }
   1651 
   1652 
   1653 void CV_IntegralTest::run_func()
   1654 {
   1655     cvIntegral( test_array[INPUT][0], test_array[OUTPUT][0],
   1656                 test_array[OUTPUT][1], test_array[OUTPUT][2] );
   1657 }
   1658 
   1659 
   1660 static void test_integral( const Mat& img, Mat* sum, Mat* sqsum, Mat* tilted )
   1661 {
   1662     CV_Assert( img.depth() == CV_32F );
   1663 
   1664     sum->create(img.rows+1, img.cols+1, CV_64F);
   1665     if( sqsum )
   1666         sqsum->create(img.rows+1, img.cols+1, CV_64F);
   1667     if( tilted )
   1668         tilted->create(img.rows+1, img.cols+1, CV_64F);
   1669 
   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();
   1679 
   1680     memset( sdata, 0, (size.width+1)*sizeof(sdata[0]) );
   1681     if( sqsum )
   1682         memset( sqdata, 0, (size.width+1)*sizeof(sqdata[0]) );
   1683     if( tilted )
   1684         memset( tdata, 0, (size.width+1)*sizeof(tdata[0]) );
   1685 
   1686     for( ; size.height--; data += step )
   1687     {
   1688         double s = 0, sq = 0;
   1689         int x;
   1690         sdata += sstep;
   1691         sqdata += sqstep;
   1692         tdata += tstep;
   1693 
   1694         for( x = 0; x <= size.width; x++ )
   1695         {
   1696             double t = x > 0 ? data[x-1] : 0, ts = t;
   1697             s += t;
   1698             sq += t*t;
   1699 
   1700             sdata[x] = s + sdata[x - sstep];
   1701             if( sqdata )
   1702                 sqdata[x] = sq + sqdata[x - sqstep];
   1703 
   1704             if( !tdata )
   1705                 continue;
   1706 
   1707             if( x == 0 )
   1708                 ts += tdata[-tstep+1];
   1709             else
   1710             {
   1711                 ts += tdata[x-tstep-1];
   1712                 if( data > img.ptr<float>() )
   1713                 {
   1714                     ts += data[x-step-1];
   1715                     if( x < size.width )
   1716                         ts += tdata[x-tstep+1] - tdata[x-tstep*2];
   1717                 }
   1718             }
   1719 
   1720             tdata[x] = ts;
   1721         }
   1722     }
   1723 }
   1724 
   1725 
   1726 void CV_IntegralTest::prepare_to_validation( int /*test_case_idx*/ )
   1727 {
   1728     Mat& src = test_mat[INPUT][0];
   1729     int cn = src.channels();
   1730 
   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;
   1734 
   1735     Mat plane, srcf, psum, psqsum, ptsum, psum2, psqsum2, ptsum2;
   1736     if( cn == 1 )
   1737     {
   1738         plane = src;
   1739         psum2 = *sum0;
   1740         psqsum2 = sqsum0 ? *sqsum0 : Mat();
   1741         ptsum2 = tsum0 ? *tsum0 : Mat();
   1742     }
   1743 
   1744     for( int i = 0; i < cn; i++ )
   1745     {
   1746         if( cn > 1 )
   1747             cvtest::extract(src, plane, i);
   1748         plane.convertTo(srcf, CV_32F);
   1749 
   1750         test_integral( srcf, &psum, sqsum0 ? &psqsum : 0, tsum0 ? &ptsum : 0 );
   1751         psum.convertTo(psum2, sum0->depth());
   1752         if( sqsum0 )
   1753             psqsum.convertTo(psqsum2, sqsum0->depth());
   1754         if( tsum0 )
   1755             ptsum.convertTo(ptsum2, tsum0->depth());
   1756 
   1757         if( cn > 1 )
   1758         {
   1759             cvtest::insert(psum2, *sum0, i);
   1760             if( sqsum0 )
   1761                 cvtest::insert(psqsum2, *sqsum0, i);
   1762             if( tsum0 )
   1763                 cvtest::insert(ptsum2, *tsum0, i);
   1764         }
   1765     }
   1766 }
   1767 
   1768 
   1769 ///////////////////////////////////////////////////////////////////////////////////
   1770 
   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(); }
   1786 
   1787 //////////////////////////////////////////////////////////////////////////////////
   1788 
   1789 class CV_FilterSupportedFormatsTest : public cvtest::BaseTest
   1790 {
   1791 public:
   1792     CV_FilterSupportedFormatsTest() {}
   1793     ~CV_FilterSupportedFormatsTest() {}
   1794 protected:
   1795     void run(int)
   1796     {
   1797         const int depths[][2] =
   1798         {
   1799             {CV_8U, CV_8U},
   1800             {CV_8U, CV_16U},
   1801             {CV_8U, CV_16S},
   1802             {CV_8U, CV_32F},
   1803             {CV_8U, CV_64F},
   1804             {CV_16U, CV_16U},
   1805             {CV_16U, CV_32F},
   1806             {CV_16U, CV_64F},
   1807             {CV_16S, CV_16S},
   1808             {CV_16S, CV_32F},
   1809             {CV_16S, CV_64F},
   1810             {CV_32F, CV_32F},
   1811             {CV_64F, CV_64F},
   1812             {-1, -1}
   1813         };
   1814 
   1815         int i = 0;
   1816         volatile int fidx = -1;
   1817         try
   1818         {
   1819             // use some "odd" size to do yet another smoke
   1820             // testing of the non-SIMD loop tails
   1821             Size sz(163, 117);
   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;
   1833 
   1834             Mat elem_ellipse = getStructuringElement(MORPH_ELLIPSE, Size(7, 7));
   1835             Mat elem_rect = getStructuringElement(MORPH_RECT, Size(7, 7));
   1836 
   1837             for( i = 0; depths[i][0] >= 0; i++ )
   1838             {
   1839                 int sdepth = depths[i][0];
   1840                 int ddepth = depths[i][1];
   1841                 Mat src(sz, CV_MAKETYPE(sdepth, 5)), dst;
   1842                 randu(src, 0, 100);
   1843                 // non-separable filtering with a small kernel
   1844                 fidx = 0;
   1845                 filter2D(src, dst, ddepth, small_kernel);
   1846                 fidx++;
   1847                 filter2D(src, dst, ddepth, big_kernel);
   1848                 fidx++;
   1849                 sepFilter2D(src, dst, ddepth, kernelX, kernelY);
   1850                 fidx++;
   1851                 sepFilter2D(src, dst, ddepth, symkernelX, symkernelY);
   1852                 fidx++;
   1853                 Sobel(src, dst, ddepth, 2, 0, 5);
   1854                 fidx++;
   1855                 Scharr(src, dst, ddepth, 0, 1);
   1856                 if( sdepth != ddepth )
   1857                     continue;
   1858                 fidx++;
   1859                 GaussianBlur(src, dst, Size(5, 5), 1.2, 1.2);
   1860                 fidx++;
   1861                 blur(src, dst, Size(11, 11));
   1862                 fidx++;
   1863                 morphologyEx(src, dst, MORPH_GRADIENT, elem_ellipse);
   1864                 fidx++;
   1865                 morphologyEx(src, dst, MORPH_GRADIENT, elem_rect);
   1866             }
   1867         }
   1868         catch(...)
   1869         {
   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" :
   1881                        "unknown???");
   1882 
   1883             ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
   1884         }
   1885     }
   1886 };
   1887 
   1888 TEST(Imgproc_Filtering, supportedFormats) { CV_FilterSupportedFormatsTest test; test.safe_run(); }
   1889 
   1890 TEST(Imgproc_Blur, borderTypes)
   1891 {
   1892     Size kernelSize(3, 3);
   1893 
   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));
   1898 
   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));
   1902 
   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));
   1906 
   1907     /// ksize <= src_roi.size()
   1908     src = Mat(5, 5, CV_8UC1, cv::Scalar(255));
   1909     src_roi = src(Rect(1, 1, 3, 3));
   1910     src_roi.setTo(0);
   1911     src.at<uchar>(2, 2) = 255;
   1912 
   1913     // should work like !BORDER_ISOLATED
   1914     blur(src_roi, dst, kernelSize, Point(-1, -1), BORDER_REPLICATE);
   1915     Mat expected_dst =
   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));
   1920 }
   1921 
   1922 TEST(Imgproc_Morphology, iterated)
   1923 {
   1924     RNG& rng = theRNG();
   1925     for( int iter = 0; iter < 30; iter++ )
   1926     {
   1927         int width = rng.uniform(5, 33);
   1928         int height = rng.uniform(5, 33);
   1929         int cn = rng.uniform(1, 5);
   1930         int iterations = rng.uniform(1, 11);
   1931         int op = rng.uniform(0, 2);
   1932         Mat src(height, width, CV_8UC(cn)), dst0, dst1, dst2;
   1933 
   1934         randu(src, 0, 256);
   1935         if( op == 0 )
   1936             dilate(src, dst0, Mat(), Point(-1,-1), iterations);
   1937         else
   1938             erode(src, dst0, Mat(), Point(-1,-1), iterations);
   1939 
   1940         for( int i = 0; i < iterations; i++ )
   1941             if( op == 0 )
   1942                 dilate(i == 0 ? src : dst1, dst1, Mat(), Point(-1,-1), 1);
   1943             else
   1944                 erode(i == 0 ? src : dst1, dst1, Mat(), Point(-1,-1), 1);
   1945 
   1946         Mat kern = getStructuringElement(MORPH_RECT, Size(3,3));
   1947         if( op == 0 )
   1948             dilate(src, dst2, kern, Point(-1,-1), iterations);
   1949         else
   1950             erode(src, dst2, kern, Point(-1,-1), iterations);
   1951         ASSERT_EQ(0.0, norm(dst0, dst1, NORM_INF));
   1952         ASSERT_EQ(0.0, norm(dst0, dst2, NORM_INF));
   1953     }
   1954 }
   1955