Home | History | Annotate | Download | only in test
      1 #include "test_precomp.hpp"
      2 
      3 #include <map>
      4 
      5 using namespace cv;
      6 using namespace std;
      7 
      8 
      9 class Core_ReduceTest : public cvtest::BaseTest
     10 {
     11 public:
     12     Core_ReduceTest() {}
     13 protected:
     14     void run( int);
     15     int checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim );
     16     int checkCase( int srcType, int dstType, int dim, Size sz );
     17     int checkDim( int dim, Size sz );
     18     int checkSize( Size sz );
     19 };
     20 
     21 template<class Type>
     22 void testReduce( const Mat& src, Mat& sum, Mat& avg, Mat& max, Mat& min, int dim )
     23 {
     24     assert( src.channels() == 1 );
     25     if( dim == 0 ) // row
     26     {
     27         sum.create( 1, src.cols, CV_64FC1 );
     28         max.create( 1, src.cols, CV_64FC1 );
     29         min.create( 1, src.cols, CV_64FC1 );
     30     }
     31     else
     32     {
     33         sum.create( src.rows, 1, CV_64FC1 );
     34         max.create( src.rows, 1, CV_64FC1 );
     35         min.create( src.rows, 1, CV_64FC1 );
     36     }
     37     sum.setTo(Scalar(0));
     38     max.setTo(Scalar(-DBL_MAX));
     39     min.setTo(Scalar(DBL_MAX));
     40 
     41     const Mat_<Type>& src_ = src;
     42     Mat_<double>& sum_ = (Mat_<double>&)sum;
     43     Mat_<double>& min_ = (Mat_<double>&)min;
     44     Mat_<double>& max_ = (Mat_<double>&)max;
     45 
     46     if( dim == 0 )
     47     {
     48         for( int ri = 0; ri < src.rows; ri++ )
     49         {
     50             for( int ci = 0; ci < src.cols; ci++ )
     51             {
     52                 sum_(0, ci) += src_(ri, ci);
     53                 max_(0, ci) = std::max( max_(0, ci), (double)src_(ri, ci) );
     54                 min_(0, ci) = std::min( min_(0, ci), (double)src_(ri, ci) );
     55             }
     56         }
     57     }
     58     else
     59     {
     60         for( int ci = 0; ci < src.cols; ci++ )
     61         {
     62             for( int ri = 0; ri < src.rows; ri++ )
     63             {
     64                 sum_(ri, 0) += src_(ri, ci);
     65                 max_(ri, 0) = std::max( max_(ri, 0), (double)src_(ri, ci) );
     66                 min_(ri, 0) = std::min( min_(ri, 0), (double)src_(ri, ci) );
     67             }
     68         }
     69     }
     70     sum.convertTo( avg, CV_64FC1 );
     71     avg = avg * (1.0 / (dim==0 ? (double)src.rows : (double)src.cols));
     72 }
     73 
     74 void getMatTypeStr( int type, string& str)
     75 {
     76     str = type == CV_8UC1 ? "CV_8UC1" :
     77     type == CV_8SC1 ? "CV_8SC1" :
     78     type == CV_16UC1 ? "CV_16UC1" :
     79     type == CV_16SC1 ? "CV_16SC1" :
     80     type == CV_32SC1 ? "CV_32SC1" :
     81     type == CV_32FC1 ? "CV_32FC1" :
     82     type == CV_64FC1 ? "CV_64FC1" : "unsupported matrix type";
     83 }
     84 
     85 int Core_ReduceTest::checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim )
     86 {
     87     int srcType = src.type();
     88     bool support = false;
     89     if( opType == CV_REDUCE_SUM || opType == CV_REDUCE_AVG )
     90     {
     91         if( srcType == CV_8U && (dstType == CV_32S || dstType == CV_32F || dstType == CV_64F) )
     92             support = true;
     93         if( srcType == CV_16U && (dstType == CV_32F || dstType == CV_64F) )
     94             support = true;
     95         if( srcType == CV_16S && (dstType == CV_32F || dstType == CV_64F) )
     96             support = true;
     97         if( srcType == CV_32F && (dstType == CV_32F || dstType == CV_64F) )
     98             support = true;
     99         if( srcType == CV_64F && dstType == CV_64F)
    100             support = true;
    101     }
    102     else if( opType == CV_REDUCE_MAX )
    103     {
    104         if( srcType == CV_8U && dstType == CV_8U )
    105             support = true;
    106         if( srcType == CV_32F && dstType == CV_32F )
    107             support = true;
    108         if( srcType == CV_64F && dstType == CV_64F )
    109             support = true;
    110     }
    111     else if( opType == CV_REDUCE_MIN )
    112     {
    113         if( srcType == CV_8U && dstType == CV_8U)
    114             support = true;
    115         if( srcType == CV_32F && dstType == CV_32F)
    116             support = true;
    117         if( srcType == CV_64F && dstType == CV_64F)
    118             support = true;
    119     }
    120     if( !support )
    121         return cvtest::TS::OK;
    122 
    123     double eps = 0.0;
    124     if ( opType == CV_REDUCE_SUM || opType == CV_REDUCE_AVG )
    125     {
    126         if ( dstType == CV_32F )
    127             eps = 1.e-5;
    128         else if( dstType == CV_64F )
    129             eps = 1.e-8;
    130         else if ( dstType == CV_32S )
    131             eps = 0.6;
    132     }
    133 
    134     assert( opRes.type() == CV_64FC1 );
    135     Mat _dst, dst, diff;
    136     reduce( src, _dst, dim, opType, dstType );
    137     _dst.convertTo( dst, CV_64FC1 );
    138 
    139     absdiff( opRes,dst,diff );
    140     bool check = false;
    141     if (dstType == CV_32F || dstType == CV_64F)
    142         check = countNonZero(diff>eps*dst) > 0;
    143     else
    144         check = countNonZero(diff>eps) > 0;
    145     if( check )
    146     {
    147         char msg[100];
    148         const char* opTypeStr = opType == CV_REDUCE_SUM ? "CV_REDUCE_SUM" :
    149         opType == CV_REDUCE_AVG ? "CV_REDUCE_AVG" :
    150         opType == CV_REDUCE_MAX ? "CV_REDUCE_MAX" :
    151         opType == CV_REDUCE_MIN ? "CV_REDUCE_MIN" : "unknown operation type";
    152         string srcTypeStr, dstTypeStr;
    153         getMatTypeStr( src.type(), srcTypeStr );
    154         getMatTypeStr( dstType, dstTypeStr );
    155         const char* dimStr = dim == 0 ? "ROWS" : "COLS";
    156 
    157         sprintf( msg, "bad accuracy with srcType = %s, dstType = %s, opType = %s, dim = %s",
    158                 srcTypeStr.c_str(), dstTypeStr.c_str(), opTypeStr, dimStr );
    159         ts->printf( cvtest::TS::LOG, msg );
    160         return cvtest::TS::FAIL_BAD_ACCURACY;
    161     }
    162     return cvtest::TS::OK;
    163 }
    164 
    165 int Core_ReduceTest::checkCase( int srcType, int dstType, int dim, Size sz )
    166 {
    167     int code = cvtest::TS::OK, tempCode;
    168     Mat src, sum, avg, max, min;
    169 
    170     src.create( sz, srcType );
    171     randu( src, Scalar(0), Scalar(100) );
    172 
    173     if( srcType == CV_8UC1 )
    174         testReduce<uchar>( src, sum, avg, max, min, dim );
    175     else if( srcType == CV_8SC1 )
    176         testReduce<char>( src, sum, avg, max, min, dim );
    177     else if( srcType == CV_16UC1 )
    178         testReduce<unsigned short int>( src, sum, avg, max, min, dim );
    179     else if( srcType == CV_16SC1 )
    180         testReduce<short int>( src, sum, avg, max, min, dim );
    181     else if( srcType == CV_32SC1 )
    182         testReduce<int>( src, sum, avg, max, min, dim );
    183     else if( srcType == CV_32FC1 )
    184         testReduce<float>( src, sum, avg, max, min, dim );
    185     else if( srcType == CV_64FC1 )
    186         testReduce<double>( src, sum, avg, max, min, dim );
    187     else
    188         assert( 0 );
    189 
    190     // 1. sum
    191     tempCode = checkOp( src, dstType, CV_REDUCE_SUM, sum, dim );
    192     code = tempCode != cvtest::TS::OK ? tempCode : code;
    193 
    194     // 2. avg
    195     tempCode = checkOp( src, dstType, CV_REDUCE_AVG, avg, dim );
    196     code = tempCode != cvtest::TS::OK ? tempCode : code;
    197 
    198     // 3. max
    199     tempCode = checkOp( src, dstType, CV_REDUCE_MAX, max, dim );
    200     code = tempCode != cvtest::TS::OK ? tempCode : code;
    201 
    202     // 4. min
    203     tempCode = checkOp( src, dstType, CV_REDUCE_MIN, min, dim );
    204     code = tempCode != cvtest::TS::OK ? tempCode : code;
    205 
    206     return code;
    207 }
    208 
    209 int Core_ReduceTest::checkDim( int dim, Size sz )
    210 {
    211     int code = cvtest::TS::OK, tempCode;
    212 
    213     // CV_8UC1
    214     tempCode = checkCase( CV_8UC1, CV_8UC1, dim, sz );
    215     code = tempCode != cvtest::TS::OK ? tempCode : code;
    216 
    217     tempCode = checkCase( CV_8UC1, CV_32SC1, dim, sz );
    218     code = tempCode != cvtest::TS::OK ? tempCode : code;
    219 
    220     tempCode = checkCase( CV_8UC1, CV_32FC1, dim, sz );
    221     code = tempCode != cvtest::TS::OK ? tempCode : code;
    222 
    223     tempCode = checkCase( CV_8UC1, CV_64FC1, dim, sz );
    224     code = tempCode != cvtest::TS::OK ? tempCode : code;
    225 
    226     // CV_16UC1
    227     tempCode = checkCase( CV_16UC1, CV_32FC1, dim, sz );
    228     code = tempCode != cvtest::TS::OK ? tempCode : code;
    229 
    230     tempCode = checkCase( CV_16UC1, CV_64FC1, dim, sz );
    231     code = tempCode != cvtest::TS::OK ? tempCode : code;
    232 
    233     // CV_16SC1
    234     tempCode = checkCase( CV_16SC1, CV_32FC1, dim, sz );
    235     code = tempCode != cvtest::TS::OK ? tempCode : code;
    236 
    237     tempCode = checkCase( CV_16SC1, CV_64FC1, dim, sz );
    238     code = tempCode != cvtest::TS::OK ? tempCode : code;
    239 
    240     // CV_32FC1
    241     tempCode = checkCase( CV_32FC1, CV_32FC1, dim, sz );
    242     code = tempCode != cvtest::TS::OK ? tempCode : code;
    243 
    244     tempCode = checkCase( CV_32FC1, CV_64FC1, dim, sz );
    245     code = tempCode != cvtest::TS::OK ? tempCode : code;
    246 
    247     // CV_64FC1
    248     tempCode = checkCase( CV_64FC1, CV_64FC1, dim, sz );
    249     code = tempCode != cvtest::TS::OK ? tempCode : code;
    250 
    251     return code;
    252 }
    253 
    254 int Core_ReduceTest::checkSize( Size sz )
    255 {
    256     int code = cvtest::TS::OK, tempCode;
    257 
    258     tempCode = checkDim( 0, sz ); // rows
    259     code = tempCode != cvtest::TS::OK ? tempCode : code;
    260 
    261     tempCode = checkDim( 1, sz ); // cols
    262     code = tempCode != cvtest::TS::OK ? tempCode : code;
    263 
    264     return code;
    265 }
    266 
    267 void Core_ReduceTest::run( int )
    268 {
    269     int code = cvtest::TS::OK, tempCode;
    270 
    271     tempCode = checkSize( Size(1,1) );
    272     code = tempCode != cvtest::TS::OK ? tempCode : code;
    273 
    274     tempCode = checkSize( Size(1,100) );
    275     code = tempCode != cvtest::TS::OK ? tempCode : code;
    276 
    277     tempCode = checkSize( Size(100,1) );
    278     code = tempCode != cvtest::TS::OK ? tempCode : code;
    279 
    280     tempCode = checkSize( Size(1000,500) );
    281     code = tempCode != cvtest::TS::OK ? tempCode : code;
    282 
    283     ts->set_failed_test_info( code );
    284 }
    285 
    286 
    287 #define CHECK_C
    288 
    289 class Core_PCATest : public cvtest::BaseTest
    290 {
    291 public:
    292     Core_PCATest() {}
    293 protected:
    294     void run(int)
    295     {
    296         const Size sz(200, 500);
    297 
    298         double diffPrjEps, diffBackPrjEps,
    299         prjEps, backPrjEps,
    300         evalEps, evecEps;
    301         int maxComponents = 100;
    302         double retainedVariance = 0.95;
    303         Mat rPoints(sz, CV_32FC1), rTestPoints(sz, CV_32FC1);
    304         RNG& rng = ts->get_rng();
    305 
    306         rng.fill( rPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) );
    307         rng.fill( rTestPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) );
    308 
    309         PCA rPCA( rPoints, Mat(), CV_PCA_DATA_AS_ROW, maxComponents ), cPCA;
    310 
    311         // 1. check C++ PCA & ROW
    312         Mat rPrjTestPoints = rPCA.project( rTestPoints );
    313         Mat rBackPrjTestPoints = rPCA.backProject( rPrjTestPoints );
    314 
    315         Mat avg(1, sz.width, CV_32FC1 );
    316         reduce( rPoints, avg, 0, CV_REDUCE_AVG );
    317         Mat Q = rPoints - repeat( avg, rPoints.rows, 1 ), Qt = Q.t(), eval, evec;
    318         Q = Qt * Q;
    319         Q = Q /(float)rPoints.rows;
    320 
    321         eigen( Q, eval, evec );
    322         /*SVD svd(Q);
    323          evec = svd.vt;
    324          eval = svd.w;*/
    325 
    326         Mat subEval( maxComponents, 1, eval.type(), eval.ptr() ),
    327         subEvec( maxComponents, evec.cols, evec.type(), evec.ptr() );
    328 
    329     #ifdef CHECK_C
    330         Mat prjTestPoints, backPrjTestPoints, cPoints = rPoints.t(), cTestPoints = rTestPoints.t();
    331         CvMat _points, _testPoints, _avg, _eval, _evec, _prjTestPoints, _backPrjTestPoints;
    332     #endif
    333 
    334         // check eigen()
    335         double eigenEps = 1e-6;
    336         double err;
    337         for(int i = 0; i < Q.rows; i++ )
    338         {
    339             Mat v = evec.row(i).t();
    340             Mat Qv = Q * v;
    341 
    342             Mat lv = eval.at<float>(i,0) * v;
    343             err = cvtest::norm( Qv, lv, NORM_L2 );
    344             if( err > eigenEps )
    345             {
    346                 ts->printf( cvtest::TS::LOG, "bad accuracy of eigen(); err = %f\n", err );
    347                 ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    348                 return;
    349             }
    350         }
    351         // check pca eigenvalues
    352         evalEps = 1e-6, evecEps = 1e-3;
    353         err = cvtest::norm( rPCA.eigenvalues, subEval, NORM_L2 );
    354         if( err > evalEps )
    355         {
    356             ts->printf( cvtest::TS::LOG, "pca.eigenvalues is incorrect (CV_PCA_DATA_AS_ROW); err = %f\n", err );
    357             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    358             return;
    359         }
    360         // check pca eigenvectors
    361         for(int i = 0; i < subEvec.rows; i++)
    362         {
    363             Mat r0 = rPCA.eigenvectors.row(i);
    364             Mat r1 = subEvec.row(i);
    365             err = cvtest::norm( r0, r1, CV_L2 );
    366             if( err > evecEps )
    367             {
    368                 r1 *= -1;
    369                 double err2 = cvtest::norm(r0, r1, CV_L2);
    370                 if( err2 > evecEps )
    371                 {
    372                     Mat tmp;
    373                     absdiff(rPCA.eigenvectors, subEvec, tmp);
    374                     double mval = 0; Point mloc;
    375                     minMaxLoc(tmp, 0, &mval, 0, &mloc);
    376 
    377                     ts->printf( cvtest::TS::LOG, "pca.eigenvectors is incorrect (CV_PCA_DATA_AS_ROW); err = %f\n", err );
    378                     ts->printf( cvtest::TS::LOG, "max diff is %g at (i=%d, j=%d) (%g vs %g)\n",
    379                                mval, mloc.y, mloc.x, rPCA.eigenvectors.at<float>(mloc.y, mloc.x),
    380                                subEvec.at<float>(mloc.y, mloc.x));
    381                     ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    382                     return;
    383                 }
    384             }
    385         }
    386 
    387         prjEps = 1.265, backPrjEps = 1.265;
    388         for( int i = 0; i < rTestPoints.rows; i++ )
    389         {
    390             // check pca project
    391             Mat subEvec_t = subEvec.t();
    392             Mat prj = rTestPoints.row(i) - avg; prj *= subEvec_t;
    393             err = cvtest::norm(rPrjTestPoints.row(i), prj, CV_RELATIVE_L2);
    394             if( err > prjEps )
    395             {
    396                 ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
    397                 ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    398                 return;
    399             }
    400             // check pca backProject
    401             Mat backPrj = rPrjTestPoints.row(i) * subEvec + avg;
    402             err = cvtest::norm( rBackPrjTestPoints.row(i), backPrj, CV_RELATIVE_L2 );
    403             if( err > backPrjEps )
    404             {
    405                 ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
    406                 ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    407                 return;
    408             }
    409         }
    410 
    411         // 2. check C++ PCA & COL
    412         cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, maxComponents );
    413         diffPrjEps = 1, diffBackPrjEps = 1;
    414         Mat ocvPrjTestPoints = cPCA.project(rTestPoints.t());
    415         err = cvtest::norm(cv::abs(ocvPrjTestPoints), cv::abs(rPrjTestPoints.t()), CV_RELATIVE_L2 );
    416         if( err > diffPrjEps )
    417         {
    418             ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_COL); err = %f\n", err );
    419             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    420             return;
    421         }
    422         err = cvtest::norm(cPCA.backProject(ocvPrjTestPoints), rBackPrjTestPoints.t(), CV_RELATIVE_L2 );
    423         if( err > diffBackPrjEps )
    424         {
    425             ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); err = %f\n", err );
    426             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    427             return;
    428         }
    429 
    430         // 3. check C++ PCA w/retainedVariance
    431         cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, retainedVariance );
    432         diffPrjEps = 1, diffBackPrjEps = 1;
    433         Mat rvPrjTestPoints = cPCA.project(rTestPoints.t());
    434 
    435         if( cPCA.eigenvectors.rows > maxComponents)
    436             err = cvtest::norm(cv::abs(rvPrjTestPoints.rowRange(0,maxComponents)), cv::abs(rPrjTestPoints.t()), CV_RELATIVE_L2 );
    437         else
    438             err = cvtest::norm(cv::abs(rvPrjTestPoints), cv::abs(rPrjTestPoints.colRange(0,cPCA.eigenvectors.rows).t()), CV_RELATIVE_L2 );
    439 
    440         if( err > diffPrjEps )
    441         {
    442             ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_COL); retainedVariance=0.95; err = %f\n", err );
    443             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    444             return;
    445         }
    446         err = cvtest::norm(cPCA.backProject(rvPrjTestPoints), rBackPrjTestPoints.t(), CV_RELATIVE_L2 );
    447         if( err > diffBackPrjEps )
    448         {
    449             ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); retainedVariance=0.95; err = %f\n", err );
    450             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    451             return;
    452         }
    453 
    454     #ifdef CHECK_C
    455         // 4. check C PCA & ROW
    456         _points = rPoints;
    457         _testPoints = rTestPoints;
    458         _avg = avg;
    459         _eval = eval;
    460         _evec = evec;
    461         prjTestPoints.create(rTestPoints.rows, maxComponents, rTestPoints.type() );
    462         backPrjTestPoints.create(rPoints.size(), rPoints.type() );
    463         _prjTestPoints = prjTestPoints;
    464         _backPrjTestPoints = backPrjTestPoints;
    465 
    466         cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_ROW );
    467         cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
    468         cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
    469 
    470         err = cvtest::norm(prjTestPoints, rPrjTestPoints, CV_RELATIVE_L2);
    471         if( err > diffPrjEps )
    472         {
    473             ts->printf( cvtest::TS::LOG, "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
    474             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    475             return;
    476         }
    477         err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints, CV_RELATIVE_L2);
    478         if( err > diffBackPrjEps )
    479         {
    480             ts->printf( cvtest::TS::LOG, "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
    481             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    482             return;
    483         }
    484 
    485         // 5. check C PCA & COL
    486         _points = cPoints;
    487         _testPoints = cTestPoints;
    488         avg = avg.t(); _avg = avg;
    489         eval = eval.t(); _eval = eval;
    490         evec = evec.t(); _evec = evec;
    491         prjTestPoints = prjTestPoints.t(); _prjTestPoints = prjTestPoints;
    492         backPrjTestPoints = backPrjTestPoints.t(); _backPrjTestPoints = backPrjTestPoints;
    493 
    494         cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_COL );
    495         cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
    496         cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
    497 
    498         err = cvtest::norm(cv::abs(prjTestPoints), cv::abs(rPrjTestPoints.t()), CV_RELATIVE_L2 );
    499         if( err > diffPrjEps )
    500         {
    501             ts->printf( cvtest::TS::LOG, "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_COL); err = %f\n", err );
    502             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    503             return;
    504         }
    505         err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints.t(), CV_RELATIVE_L2);
    506         if( err > diffBackPrjEps )
    507         {
    508             ts->printf( cvtest::TS::LOG, "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_COL); err = %f\n", err );
    509             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    510             return;
    511         }
    512     #endif
    513         // Test read and write
    514         FileStorage fs( "PCA_store.yml", FileStorage::WRITE );
    515         rPCA.write( fs );
    516         fs.release();
    517 
    518         PCA lPCA;
    519         fs.open( "PCA_store.yml", FileStorage::READ );
    520         lPCA.read( fs.root() );
    521         err = cvtest::norm( rPCA.eigenvectors, lPCA.eigenvectors, CV_RELATIVE_L2 );
    522         if( err > 0 )
    523         {
    524             ts->printf( cvtest::TS::LOG, "bad accuracy of write/load functions (YML); err = %f\n", err );
    525             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    526         }
    527         err = cvtest::norm( rPCA.eigenvalues, lPCA.eigenvalues, CV_RELATIVE_L2 );
    528         if( err > 0 )
    529         {
    530             ts->printf( cvtest::TS::LOG, "bad accuracy of write/load functions (YML); err = %f\n", err );
    531             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    532         }
    533         err = cvtest::norm( rPCA.mean, lPCA.mean, CV_RELATIVE_L2 );
    534         if( err > 0 )
    535         {
    536             ts->printf( cvtest::TS::LOG, "bad accuracy of write/load functions (YML); err = %f\n", err );
    537             ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
    538         }
    539     }
    540 };
    541 
    542 class Core_ArrayOpTest : public cvtest::BaseTest
    543 {
    544 public:
    545     Core_ArrayOpTest();
    546     ~Core_ArrayOpTest();
    547 protected:
    548     void run(int);
    549 };
    550 
    551 
    552 Core_ArrayOpTest::Core_ArrayOpTest()
    553 {
    554 }
    555 Core_ArrayOpTest::~Core_ArrayOpTest() {}
    556 
    557 static string idx2string(const int* idx, int dims)
    558 {
    559     char buf[256];
    560     char* ptr = buf;
    561     for( int k = 0; k < dims; k++ )
    562     {
    563         sprintf(ptr, "%4d ", idx[k]);
    564         ptr += strlen(ptr);
    565     }
    566     ptr[-1] = '\0';
    567     return string(buf);
    568 }
    569 
    570 static const int* string2idx(const string& s, int* idx, int dims)
    571 {
    572     const char* ptr = s.c_str();
    573     for( int k = 0; k < dims; k++ )
    574     {
    575         int n = 0;
    576         sscanf(ptr, "%d%n", idx + k, &n);
    577         ptr += n;
    578     }
    579     return idx;
    580 }
    581 
    582 static double getValue(SparseMat& M, const int* idx, RNG& rng)
    583 {
    584     int d = M.dims();
    585     size_t hv = 0, *phv = 0;
    586     if( (unsigned)rng % 2 )
    587     {
    588         hv = d == 2 ? M.hash(idx[0], idx[1]) :
    589         d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
    590         phv = &hv;
    591     }
    592 
    593     const uchar* ptr = d == 2 ? M.ptr(idx[0], idx[1], false, phv) :
    594     d == 3 ? M.ptr(idx[0], idx[1], idx[2], false, phv) :
    595     M.ptr(idx, false, phv);
    596     return !ptr ? 0 : M.type() == CV_32F ? *(float*)ptr : M.type() == CV_64F ? *(double*)ptr : 0;
    597 }
    598 
    599 static double getValue(const CvSparseMat* M, const int* idx)
    600 {
    601     int type = 0;
    602     const uchar* ptr = cvPtrND(M, idx, &type, 0);
    603     return !ptr ? 0 : type == CV_32F ? *(float*)ptr : type == CV_64F ? *(double*)ptr : 0;
    604 }
    605 
    606 static void eraseValue(SparseMat& M, const int* idx, RNG& rng)
    607 {
    608     int d = M.dims();
    609     size_t hv = 0, *phv = 0;
    610     if( (unsigned)rng % 2 )
    611     {
    612         hv = d == 2 ? M.hash(idx[0], idx[1]) :
    613         d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
    614         phv = &hv;
    615     }
    616 
    617     if( d == 2 )
    618         M.erase(idx[0], idx[1], phv);
    619     else if( d == 3 )
    620         M.erase(idx[0], idx[1], idx[2], phv);
    621     else
    622         M.erase(idx, phv);
    623 }
    624 
    625 static void eraseValue(CvSparseMat* M, const int* idx)
    626 {
    627     cvClearND(M, idx);
    628 }
    629 
    630 static void setValue(SparseMat& M, const int* idx, double value, RNG& rng)
    631 {
    632     int d = M.dims();
    633     size_t hv = 0, *phv = 0;
    634     if( (unsigned)rng % 2 )
    635     {
    636         hv = d == 2 ? M.hash(idx[0], idx[1]) :
    637         d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
    638         phv = &hv;
    639     }
    640 
    641     uchar* ptr = d == 2 ? M.ptr(idx[0], idx[1], true, phv) :
    642     d == 3 ? M.ptr(idx[0], idx[1], idx[2], true, phv) :
    643     M.ptr(idx, true, phv);
    644     if( M.type() == CV_32F )
    645         *(float*)ptr = (float)value;
    646     else if( M.type() == CV_64F )
    647         *(double*)ptr = value;
    648     else
    649         CV_Error(CV_StsUnsupportedFormat, "");
    650 }
    651 
    652 template<typename Pixel>
    653 struct InitializerFunctor{
    654     /// Initializer for cv::Mat::forEach test
    655     void operator()(Pixel & pixel, const int * idx) const {
    656         pixel.x = idx[0];
    657         pixel.y = idx[1];
    658         pixel.z = idx[2];
    659     }
    660 };
    661 
    662 void Core_ArrayOpTest::run( int /* start_from */)
    663 {
    664     int errcount = 0;
    665 
    666     // dense matrix operations
    667     {
    668         int sz3[] = {5, 10, 15};
    669         MatND A(3, sz3, CV_32F), B(3, sz3, CV_16SC4);
    670         CvMatND matA = A, matB = B;
    671         RNG rng;
    672         rng.fill(A, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
    673         rng.fill(B, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
    674 
    675         int idx0[] = {3,4,5}, idx1[] = {0, 9, 7};
    676         float val0 = 130;
    677         Scalar val1(-1000, 30, 3, 8);
    678         cvSetRealND(&matA, idx0, val0);
    679         cvSetReal3D(&matA, idx1[0], idx1[1], idx1[2], -val0);
    680         cvSetND(&matB, idx0, val1);
    681         cvSet3D(&matB, idx1[0], idx1[1], idx1[2], -val1);
    682         Ptr<CvMatND> matC(cvCloneMatND(&matB));
    683 
    684         if( A.at<float>(idx0[0], idx0[1], idx0[2]) != val0 ||
    685            A.at<float>(idx1[0], idx1[1], idx1[2]) != -val0 ||
    686            cvGetReal3D(&matA, idx0[0], idx0[1], idx0[2]) != val0 ||
    687            cvGetRealND(&matA, idx1) != -val0 ||
    688 
    689            Scalar(B.at<Vec4s>(idx0[0], idx0[1], idx0[2])) != val1 ||
    690            Scalar(B.at<Vec4s>(idx1[0], idx1[1], idx1[2])) != -val1 ||
    691            Scalar(cvGet3D(matC, idx0[0], idx0[1], idx0[2])) != val1 ||
    692            Scalar(cvGetND(matC, idx1)) != -val1 )
    693         {
    694             ts->printf(cvtest::TS::LOG, "one of cvSetReal3D, cvSetRealND, cvSet3D, cvSetND "
    695                        "or the corresponding *Get* functions is not correct\n");
    696             errcount++;
    697         }
    698     }
    699     // test cv::Mat::forEach
    700     {
    701         const int dims[3] = { 101, 107, 7 };
    702         typedef cv::Point3i Pixel;
    703 
    704         cv::Mat a = cv::Mat::zeros(3, dims, CV_32SC3);
    705         InitializerFunctor<Pixel> initializer;
    706 
    707         a.forEach<Pixel>(initializer);
    708 
    709         uint64 total = 0;
    710         bool error_reported = false;
    711         for (int i0 = 0; i0 < dims[0]; ++i0) {
    712             for (int i1 = 0; i1 < dims[1]; ++i1) {
    713                 for (int i2 = 0; i2 < dims[2]; ++i2) {
    714                     Pixel& pixel = a.at<Pixel>(i0, i1, i2);
    715                     if (pixel.x != i0 || pixel.y != i1 || pixel.z != i2) {
    716                         if (!error_reported) {
    717                             ts->printf(cvtest::TS::LOG, "forEach is not correct.\n"
    718                                 "First error detected at (%d, %d, %d).\n", pixel.x, pixel.y, pixel.z);
    719                             error_reported = true;
    720                         }
    721                         errcount++;
    722                     }
    723                     total += pixel.x;
    724                     total += pixel.y;
    725                     total += pixel.z;
    726                 }
    727             }
    728         }
    729         uint64 total2 = 0;
    730         for (size_t i = 0; i < sizeof(dims) / sizeof(dims[0]); ++i) {
    731             total2 += ((dims[i] - 1) * dims[i] / 2) * dims[0] * dims[1] * dims[2] / dims[i];
    732         }
    733         if (total != total2) {
    734             ts->printf(cvtest::TS::LOG, "forEach is not correct because total is invalid.\n");
    735             errcount++;
    736         }
    737     }
    738 
    739     RNG rng;
    740     const int MAX_DIM = 5, MAX_DIM_SZ = 10;
    741     // sparse matrix operations
    742     for( int si = 0; si < 10; si++ )
    743     {
    744         int depth = (unsigned)rng % 2 == 0 ? CV_32F : CV_64F;
    745         int dims = ((unsigned)rng % MAX_DIM) + 1;
    746         int i, k, size[MAX_DIM]={0}, idx[MAX_DIM]={0};
    747         vector<string> all_idxs;
    748         vector<double> all_vals;
    749         vector<double> all_vals2;
    750         string sidx, min_sidx, max_sidx;
    751         double min_val=0, max_val=0;
    752 
    753         int p = 1;
    754         for( k = 0; k < dims; k++ )
    755         {
    756             size[k] = ((unsigned)rng % MAX_DIM_SZ) + 1;
    757             p *= size[k];
    758         }
    759         SparseMat M( dims, size, depth );
    760         map<string, double> M0;
    761 
    762         int nz0 = (unsigned)rng % max(p/5,10);
    763         nz0 = min(max(nz0, 1), p);
    764         all_vals.resize(nz0);
    765         all_vals2.resize(nz0);
    766         Mat_<double> _all_vals(all_vals), _all_vals2(all_vals2);
    767         rng.fill(_all_vals, CV_RAND_UNI, Scalar(-1000), Scalar(1000));
    768         if( depth == CV_32F )
    769         {
    770             Mat _all_vals_f;
    771             _all_vals.convertTo(_all_vals_f, CV_32F);
    772             _all_vals_f.convertTo(_all_vals, CV_64F);
    773         }
    774         _all_vals.convertTo(_all_vals2, _all_vals2.type(), 2);
    775         if( depth == CV_32F )
    776         {
    777             Mat _all_vals2_f;
    778             _all_vals2.convertTo(_all_vals2_f, CV_32F);
    779             _all_vals2_f.convertTo(_all_vals2, CV_64F);
    780         }
    781 
    782         minMaxLoc(_all_vals, &min_val, &max_val);
    783         double _norm0 = cvtest::norm(_all_vals, CV_C);
    784         double _norm1 = cvtest::norm(_all_vals, CV_L1);
    785         double _norm2 = cvtest::norm(_all_vals, CV_L2);
    786 
    787         for( i = 0; i < nz0; i++ )
    788         {
    789             for(;;)
    790             {
    791                 for( k = 0; k < dims; k++ )
    792                     idx[k] = (unsigned)rng % size[k];
    793                 sidx = idx2string(idx, dims);
    794                 if( M0.count(sidx) == 0 )
    795                     break;
    796             }
    797             all_idxs.push_back(sidx);
    798             M0[sidx] = all_vals[i];
    799             if( all_vals[i] == min_val )
    800                 min_sidx = sidx;
    801             if( all_vals[i] == max_val )
    802                 max_sidx = sidx;
    803             setValue(M, idx, all_vals[i], rng);
    804             double v = getValue(M, idx, rng);
    805             if( v != all_vals[i] )
    806             {
    807                 ts->printf(cvtest::TS::LOG, "%d. immediately after SparseMat[%s]=%.20g the current value is %.20g\n",
    808                            i, sidx.c_str(), all_vals[i], v);
    809                 errcount++;
    810                 break;
    811             }
    812         }
    813 
    814         Ptr<CvSparseMat> M2(cvCreateSparseMat(M));
    815         MatND Md;
    816         M.copyTo(Md);
    817         SparseMat M3; SparseMat(Md).convertTo(M3, Md.type(), 2);
    818 
    819         int nz1 = (int)M.nzcount(), nz2 = (int)M3.nzcount();
    820         double norm0 = norm(M, CV_C);
    821         double norm1 = norm(M, CV_L1);
    822         double norm2 = norm(M, CV_L2);
    823         double eps = depth == CV_32F ? FLT_EPSILON*100 : DBL_EPSILON*1000;
    824 
    825         if( nz1 != nz0 || nz2 != nz0)
    826         {
    827             errcount++;
    828             ts->printf(cvtest::TS::LOG, "%d: The number of non-zero elements before/after converting to/from dense matrix is not correct: %d/%d (while it should be %d)\n",
    829                        si, nz1, nz2, nz0 );
    830             break;
    831         }
    832 
    833         if( fabs(norm0 - _norm0) > fabs(_norm0)*eps ||
    834            fabs(norm1 - _norm1) > fabs(_norm1)*eps ||
    835            fabs(norm2 - _norm2) > fabs(_norm2)*eps )
    836         {
    837             errcount++;
    838             ts->printf(cvtest::TS::LOG, "%d: The norms are different: %.20g/%.20g/%.20g vs %.20g/%.20g/%.20g\n",
    839                        si, norm0, norm1, norm2, _norm0, _norm1, _norm2 );
    840             break;
    841         }
    842 
    843         int n = (unsigned)rng % max(p/5,10);
    844         n = min(max(n, 1), p) + nz0;
    845 
    846         for( i = 0; i < n; i++ )
    847         {
    848             double val1, val2, val3, val0;
    849             if(i < nz0)
    850             {
    851                 sidx = all_idxs[i];
    852                 string2idx(sidx, idx, dims);
    853                 val0 = all_vals[i];
    854             }
    855             else
    856             {
    857                 for( k = 0; k < dims; k++ )
    858                     idx[k] = (unsigned)rng % size[k];
    859                 sidx = idx2string(idx, dims);
    860                 val0 = M0[sidx];
    861             }
    862             val1 = getValue(M, idx, rng);
    863             val2 = getValue(M2, idx);
    864             val3 = getValue(M3, idx, rng);
    865 
    866             if( val1 != val0 || val2 != val0 || fabs(val3 - val0*2) > fabs(val0*2)*FLT_EPSILON )
    867             {
    868                 errcount++;
    869                 ts->printf(cvtest::TS::LOG, "SparseMat M[%s] = %g/%g/%g (while it should be %g)\n", sidx.c_str(), val1, val2, val3, val0 );
    870                 break;
    871             }
    872         }
    873 
    874         for( i = 0; i < n; i++ )
    875         {
    876             double val1, val2;
    877             if(i < nz0)
    878             {
    879                 sidx = all_idxs[i];
    880                 string2idx(sidx, idx, dims);
    881             }
    882             else
    883             {
    884                 for( k = 0; k < dims; k++ )
    885                     idx[k] = (unsigned)rng % size[k];
    886                 sidx = idx2string(idx, dims);
    887             }
    888             eraseValue(M, idx, rng);
    889             eraseValue(M2, idx);
    890             val1 = getValue(M, idx, rng);
    891             val2 = getValue(M2, idx);
    892             if( val1 != 0 || val2 != 0 )
    893             {
    894                 errcount++;
    895                 ts->printf(cvtest::TS::LOG, "SparseMat: after deleting M[%s], it is =%g/%g (while it should be 0)\n", sidx.c_str(), val1, val2 );
    896                 break;
    897             }
    898         }
    899 
    900         int nz = (int)M.nzcount();
    901         if( nz != 0 )
    902         {
    903             errcount++;
    904             ts->printf(cvtest::TS::LOG, "The number of non-zero elements after removing all the elements = %d (while it should be 0)\n", nz );
    905             break;
    906         }
    907 
    908         int idx1[MAX_DIM], idx2[MAX_DIM];
    909         double val1 = 0, val2 = 0;
    910         M3 = SparseMat(Md);
    911         minMaxLoc(M3, &val1, &val2, idx1, idx2);
    912         string s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
    913         if( val1 != min_val || val2 != max_val || s1 != min_sidx || s2 != max_sidx )
    914         {
    915             errcount++;
    916             ts->printf(cvtest::TS::LOG, "%d. Sparse: The value and positions of minimum/maximum elements are different from the reference values and positions:\n\t"
    917                        "(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
    918                        min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
    919             break;
    920         }
    921 
    922         minMaxIdx(Md, &val1, &val2, idx1, idx2);
    923         s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
    924         if( (min_val < 0 && (val1 != min_val || s1 != min_sidx)) ||
    925            (max_val > 0 && (val2 != max_val || s2 != max_sidx)) )
    926         {
    927             errcount++;
    928             ts->printf(cvtest::TS::LOG, "%d. Dense: The value and positions of minimum/maximum elements are different from the reference values and positions:\n\t"
    929                        "(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
    930                        min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
    931             break;
    932         }
    933     }
    934 
    935     ts->set_failed_test_info(errcount == 0 ? cvtest::TS::OK : cvtest::TS::FAIL_INVALID_OUTPUT);
    936 }
    937 
    938 
    939 template <class ElemType>
    940 int calcDiffElemCountImpl(const vector<Mat>& mv, const Mat& m)
    941 {
    942     int diffElemCount = 0;
    943     const int mChannels = m.channels();
    944     for(int y = 0; y < m.rows; y++)
    945     {
    946         for(int x = 0; x < m.cols; x++)
    947         {
    948             const ElemType* mElem = &m.at<ElemType>(y,x*mChannels);
    949             size_t loc = 0;
    950             for(size_t i = 0; i < mv.size(); i++)
    951             {
    952                 const size_t mvChannel = mv[i].channels();
    953                 const ElemType* mvElem = &mv[i].at<ElemType>(y,x*(int)mvChannel);
    954                 for(size_t li = 0; li < mvChannel; li++)
    955                     if(mElem[loc + li] != mvElem[li])
    956                         diffElemCount++;
    957                 loc += mvChannel;
    958             }
    959             CV_Assert(loc == (size_t)mChannels);
    960         }
    961     }
    962     return diffElemCount;
    963 }
    964 
    965 static
    966 int calcDiffElemCount(const vector<Mat>& mv, const Mat& m)
    967 {
    968     int depth = m.depth();
    969     switch (depth)
    970     {
    971     case CV_8U:
    972         return calcDiffElemCountImpl<uchar>(mv, m);
    973     case CV_8S:
    974         return calcDiffElemCountImpl<char>(mv, m);
    975     case CV_16U:
    976         return calcDiffElemCountImpl<unsigned short>(mv, m);
    977     case CV_16S:
    978         return calcDiffElemCountImpl<short int>(mv, m);
    979     case CV_32S:
    980         return calcDiffElemCountImpl<int>(mv, m);
    981     case CV_32F:
    982         return calcDiffElemCountImpl<float>(mv, m);
    983     case CV_64F:
    984         return calcDiffElemCountImpl<double>(mv, m);
    985     }
    986 
    987     return INT_MAX;
    988 }
    989 
    990 class Core_MergeSplitBaseTest : public cvtest::BaseTest
    991 {
    992 protected:
    993     virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng) = 0;
    994 
    995     virtual void run(int)
    996     {
    997         // m is Mat
    998         // mv is vector<Mat>
    999         const int minMSize = 1;
   1000         const int maxMSize = 100;
   1001         const size_t maxMvSize = 10;
   1002 
   1003         RNG& rng = theRNG();
   1004         Size mSize(rng.uniform(minMSize, maxMSize), rng.uniform(minMSize, maxMSize));
   1005         size_t mvSize = rng.uniform(1, maxMvSize);
   1006 
   1007         int res = cvtest::TS::OK, curRes = res;
   1008         curRes = run_case(CV_8U, mvSize, mSize, rng);
   1009         res = curRes != cvtest::TS::OK ? curRes : res;
   1010 
   1011         curRes = run_case(CV_8S, mvSize, mSize, rng);
   1012         res = curRes != cvtest::TS::OK ? curRes : res;
   1013 
   1014         curRes = run_case(CV_16U, mvSize, mSize, rng);
   1015         res = curRes != cvtest::TS::OK ? curRes : res;
   1016 
   1017         curRes = run_case(CV_16S, mvSize, mSize, rng);
   1018         res = curRes != cvtest::TS::OK ? curRes : res;
   1019 
   1020         curRes = run_case(CV_32S, mvSize, mSize, rng);
   1021         res = curRes != cvtest::TS::OK ? curRes : res;
   1022 
   1023         curRes = run_case(CV_32F, mvSize, mSize, rng);
   1024         res = curRes != cvtest::TS::OK ? curRes : res;
   1025 
   1026         curRes = run_case(CV_64F, mvSize, mSize, rng);
   1027         res = curRes != cvtest::TS::OK ? curRes : res;
   1028 
   1029         ts->set_failed_test_info(res);
   1030     }
   1031 };
   1032 
   1033 class Core_MergeTest : public Core_MergeSplitBaseTest
   1034 {
   1035 public:
   1036     Core_MergeTest() {}
   1037     ~Core_MergeTest() {}
   1038 
   1039 protected:
   1040     virtual int run_case(int depth, size_t matCount, const Size& size, RNG& rng)
   1041     {
   1042         const int maxMatChannels = 10;
   1043 
   1044         vector<Mat> src(matCount);
   1045         int channels = 0;
   1046         for(size_t i = 0; i < src.size(); i++)
   1047         {
   1048             Mat m(size, CV_MAKETYPE(depth, rng.uniform(1,maxMatChannels)));
   1049             rng.fill(m, RNG::UNIFORM, 0, 100, true);
   1050             channels += m.channels();
   1051             src[i] = m;
   1052         }
   1053 
   1054         Mat dst;
   1055         merge(src, dst);
   1056 
   1057         // check result
   1058         stringstream commonLog;
   1059         commonLog << "Depth " << depth << " :";
   1060         if(dst.depth() != depth)
   1061         {
   1062             ts->printf(cvtest::TS::LOG, "%s incorrect depth of dst (%d instead of %d)\n",
   1063                        commonLog.str().c_str(), dst.depth(), depth);
   1064             return cvtest::TS::FAIL_INVALID_OUTPUT;
   1065         }
   1066         if(dst.size() != size)
   1067         {
   1068             ts->printf(cvtest::TS::LOG, "%s incorrect size of dst (%d x %d instead of %d x %d)\n",
   1069                        commonLog.str().c_str(), dst.rows, dst.cols, size.height, size.width);
   1070             return cvtest::TS::FAIL_INVALID_OUTPUT;
   1071         }
   1072         if(dst.channels() != channels)
   1073         {
   1074             ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst (%d instead of %d)\n",
   1075                        commonLog.str().c_str(), dst.channels(), channels);
   1076             return cvtest::TS::FAIL_INVALID_OUTPUT;
   1077         }
   1078 
   1079         int diffElemCount = calcDiffElemCount(src, dst);
   1080         if(diffElemCount > 0)
   1081         {
   1082             ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n",
   1083                        commonLog.str().c_str(), static_cast<float>(diffElemCount)/(channels*size.area()));
   1084             return cvtest::TS::FAIL_INVALID_OUTPUT;
   1085         }
   1086 
   1087         return cvtest::TS::OK;
   1088     }
   1089 };
   1090 
   1091 class Core_SplitTest : public Core_MergeSplitBaseTest
   1092 {
   1093 public:
   1094     Core_SplitTest() {}
   1095     ~Core_SplitTest() {}
   1096 
   1097 protected:
   1098     virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng)
   1099     {
   1100         Mat src(size, CV_MAKETYPE(depth, (int)channels));
   1101         rng.fill(src, RNG::UNIFORM, 0, 100, true);
   1102 
   1103         vector<Mat> dst;
   1104         split(src, dst);
   1105 
   1106         // check result
   1107         stringstream commonLog;
   1108         commonLog << "Depth " << depth << " :";
   1109         if(dst.size() != channels)
   1110         {
   1111             ts->printf(cvtest::TS::LOG, "%s incorrect count of matrices in dst (%d instead of %d)\n",
   1112                        commonLog.str().c_str(), dst.size(), channels);
   1113             return cvtest::TS::FAIL_INVALID_OUTPUT;
   1114         }
   1115         for(size_t i = 0; i < dst.size(); i++)
   1116         {
   1117             if(dst[i].size() != size)
   1118             {
   1119                 ts->printf(cvtest::TS::LOG, "%s incorrect size of dst[%d] (%d x %d instead of %d x %d)\n",
   1120                            commonLog.str().c_str(), i, dst[i].rows, dst[i].cols, size.height, size.width);
   1121                 return cvtest::TS::FAIL_INVALID_OUTPUT;
   1122             }
   1123             if(dst[i].depth() != depth)
   1124             {
   1125                 ts->printf(cvtest::TS::LOG, "%s: incorrect depth of dst[%d] (%d instead of %d)\n",
   1126                            commonLog.str().c_str(), i, dst[i].depth(), depth);
   1127                 return cvtest::TS::FAIL_INVALID_OUTPUT;
   1128             }
   1129             if(dst[i].channels() != 1)
   1130             {
   1131                 ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst[%d] (%d instead of %d)\n",
   1132                            commonLog.str().c_str(), i, dst[i].channels(), 1);
   1133                 return cvtest::TS::FAIL_INVALID_OUTPUT;
   1134             }
   1135         }
   1136 
   1137         int diffElemCount = calcDiffElemCount(dst, src);
   1138         if(diffElemCount > 0)
   1139         {
   1140             ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n",
   1141                        commonLog.str().c_str(), static_cast<float>(diffElemCount)/(channels*size.area()));
   1142             return cvtest::TS::FAIL_INVALID_OUTPUT;
   1143         }
   1144 
   1145         return cvtest::TS::OK;
   1146     }
   1147 };
   1148 
   1149 TEST(Core_PCA, accuracy) { Core_PCATest test; test.safe_run(); }
   1150 TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); }
   1151 TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); }
   1152 
   1153 TEST(Core_Merge, shape_operations) { Core_MergeTest test; test.safe_run(); }
   1154 TEST(Core_Split, shape_operations) { Core_SplitTest test; test.safe_run(); }
   1155 
   1156 
   1157 TEST(Core_IOArray, submat_assignment)
   1158 {
   1159     Mat1f A = Mat1f::zeros(2,2);
   1160     Mat1f B = Mat1f::ones(1,3);
   1161 
   1162     EXPECT_THROW( B.colRange(0,3).copyTo(A.row(0)), cv::Exception );
   1163 
   1164     EXPECT_NO_THROW( B.colRange(0,2).copyTo(A.row(0)) );
   1165 
   1166     EXPECT_EQ( 1.0f, A(0,0) );
   1167     EXPECT_EQ( 1.0f, A(0,1) );
   1168 }
   1169 
   1170 void OutputArray_create1(OutputArray m) { m.create(1, 2, CV_32S); }
   1171 void OutputArray_create2(OutputArray m) { m.create(1, 3, CV_32F); }
   1172 
   1173 TEST(Core_IOArray, submat_create)
   1174 {
   1175     Mat1f A = Mat1f::zeros(2,2);
   1176 
   1177     EXPECT_THROW( OutputArray_create1(A.row(0)), cv::Exception );
   1178     EXPECT_THROW( OutputArray_create2(A.row(0)), cv::Exception );
   1179 }
   1180 
   1181 TEST(Core_Mat, reshape_1942)
   1182 {
   1183     cv::Mat A = (cv::Mat_<float>(2,3) << 3.4884074, 1.4159607, 0.78737736,  2.3456569, -0.88010466, 0.3009364);
   1184     int cn = 0;
   1185     ASSERT_NO_THROW(
   1186         cv::Mat_<float> M = A.reshape(3);
   1187         cn = M.channels();
   1188     );
   1189     ASSERT_EQ(1, cn);
   1190 }
   1191 
   1192 TEST(Core_Mat, copyNx1ToVector)
   1193 {
   1194     cv::Mat_<uchar> src(5, 1);
   1195     cv::Mat_<uchar> ref_dst8;
   1196     cv::Mat_<ushort> ref_dst16;
   1197     std::vector<uchar> dst8;
   1198     std::vector<ushort> dst16;
   1199 
   1200     src << 1, 2, 3, 4, 5;
   1201 
   1202     src.copyTo(ref_dst8);
   1203     src.copyTo(dst8);
   1204 
   1205     ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst8, cv::Mat_<uchar>(dst8));
   1206 
   1207     src.convertTo(ref_dst16, CV_16U);
   1208     src.convertTo(dst16, CV_16U);
   1209 
   1210     ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst16, cv::Mat_<ushort>(dst16));
   1211 }
   1212 
   1213 TEST(Core_Matx, fromMat_)
   1214 {
   1215     Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
   1216     Matx22d b(a);
   1217     ASSERT_EQ( norm(a, b, NORM_INF), 0.);
   1218 }
   1219 
   1220 TEST(Core_InputArray, empty)
   1221 {
   1222     vector<vector<Point> > data;
   1223     ASSERT_TRUE( _InputArray(data).empty() );
   1224 }
   1225 
   1226 TEST(Core_CopyMask, bug1918)
   1227 {
   1228     Mat_<unsigned char> tmpSrc(100,100);
   1229     tmpSrc = 124;
   1230     Mat_<unsigned char> tmpMask(100,100);
   1231     tmpMask = 255;
   1232     Mat_<unsigned char> tmpDst(100,100);
   1233     tmpDst = 2;
   1234     tmpSrc.copyTo(tmpDst,tmpMask);
   1235     ASSERT_EQ(sum(tmpDst)[0], 124*100*100);
   1236 }
   1237 
   1238 TEST(Core_SVD, orthogonality)
   1239 {
   1240     for( int i = 0; i < 2; i++ )
   1241     {
   1242         int type = i == 0 ? CV_32F : CV_64F;
   1243         Mat mat_D(2, 2, type);
   1244         mat_D.setTo(88.);
   1245         Mat mat_U, mat_W;
   1246         SVD::compute(mat_D, mat_W, mat_U, noArray(), SVD::FULL_UV);
   1247         mat_U *= mat_U.t();
   1248         ASSERT_LT(norm(mat_U, Mat::eye(2, 2, type), NORM_INF), 1e-5);
   1249     }
   1250 }
   1251 
   1252 
   1253 TEST(Core_SparseMat, footprint)
   1254 {
   1255     int n = 1000000;
   1256     int sz[] = { n, n };
   1257     SparseMat m(2, sz, CV_64F);
   1258 
   1259     int nodeSize0 = (int)m.hdr->nodeSize;
   1260     double dataSize0 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6;
   1261     printf("before: node size=%d bytes, data size=%.0f Mbytes\n", nodeSize0, dataSize0);
   1262 
   1263     for (int i = 0; i < n; i++)
   1264     {
   1265         m.ref<double>(i, i) = 1;
   1266     }
   1267 
   1268     double dataSize1 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6;
   1269     double threshold = (n*nodeSize0*1.6 + n*2.*sizeof(size_t))*1e-6;
   1270     printf("after: data size=%.0f Mbytes, threshold=%.0f MBytes\n", dataSize1, threshold);
   1271 
   1272     ASSERT_LE((int)m.hdr->nodeSize, 32);
   1273     ASSERT_LE(dataSize1, threshold);
   1274 }
   1275