6c2ab85c3c447a4a00b662b4db50a50f877519f7
[platform/upstream/opencv.git] / modules / core / test / test_mat.cpp
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 template<typename Pixel>
663 struct InitializerFunctor5D{
664     /// Initializer for cv::Mat::forEach test (5 dimensional case)
665     void operator()(Pixel & pixel, const int * idx) const {
666         pixel[0] = idx[0];
667         pixel[1] = idx[1];
668         pixel[2] = idx[2];
669         pixel[3] = idx[3];
670         pixel[4] = idx[4];
671     }
672 };
673
674 template<typename Pixel>
675 struct EmptyFunctor
676 {
677     void operator()(const Pixel &, const int *) const {}
678 };
679
680
681 void Core_ArrayOpTest::run( int /* start_from */)
682 {
683     int errcount = 0;
684
685     // dense matrix operations
686     {
687         int sz3[] = {5, 10, 15};
688         MatND A(3, sz3, CV_32F), B(3, sz3, CV_16SC4);
689         CvMatND matA = A, matB = B;
690         RNG rng;
691         rng.fill(A, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
692         rng.fill(B, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
693
694         int idx0[] = {3,4,5}, idx1[] = {0, 9, 7};
695         float val0 = 130;
696         Scalar val1(-1000, 30, 3, 8);
697         cvSetRealND(&matA, idx0, val0);
698         cvSetReal3D(&matA, idx1[0], idx1[1], idx1[2], -val0);
699         cvSetND(&matB, idx0, val1);
700         cvSet3D(&matB, idx1[0], idx1[1], idx1[2], -val1);
701         Ptr<CvMatND> matC(cvCloneMatND(&matB));
702
703         if( A.at<float>(idx0[0], idx0[1], idx0[2]) != val0 ||
704            A.at<float>(idx1[0], idx1[1], idx1[2]) != -val0 ||
705            cvGetReal3D(&matA, idx0[0], idx0[1], idx0[2]) != val0 ||
706            cvGetRealND(&matA, idx1) != -val0 ||
707
708            Scalar(B.at<Vec4s>(idx0[0], idx0[1], idx0[2])) != val1 ||
709            Scalar(B.at<Vec4s>(idx1[0], idx1[1], idx1[2])) != -val1 ||
710            Scalar(cvGet3D(matC, idx0[0], idx0[1], idx0[2])) != val1 ||
711            Scalar(cvGetND(matC, idx1)) != -val1 )
712         {
713             ts->printf(cvtest::TS::LOG, "one of cvSetReal3D, cvSetRealND, cvSet3D, cvSetND "
714                        "or the corresponding *Get* functions is not correct\n");
715             errcount++;
716         }
717     }
718     // test cv::Mat::forEach
719     {
720         const int dims[3] = { 101, 107, 7 };
721         typedef cv::Point3i Pixel;
722
723         cv::Mat a = cv::Mat::zeros(3, dims, CV_32SC3);
724         InitializerFunctor<Pixel> initializer;
725
726         a.forEach<Pixel>(initializer);
727
728         uint64 total = 0;
729         bool error_reported = false;
730         for (int i0 = 0; i0 < dims[0]; ++i0) {
731             for (int i1 = 0; i1 < dims[1]; ++i1) {
732                 for (int i2 = 0; i2 < dims[2]; ++i2) {
733                     Pixel& pixel = a.at<Pixel>(i0, i1, i2);
734                     if (pixel.x != i0 || pixel.y != i1 || pixel.z != i2) {
735                         if (!error_reported) {
736                             ts->printf(cvtest::TS::LOG, "forEach is not correct.\n"
737                                 "First error detected at (%d, %d, %d).\n", pixel.x, pixel.y, pixel.z);
738                             error_reported = true;
739                         }
740                         errcount++;
741                     }
742                     total += pixel.x;
743                     total += pixel.y;
744                     total += pixel.z;
745                 }
746             }
747         }
748         uint64 total2 = 0;
749         for (size_t i = 0; i < sizeof(dims) / sizeof(dims[0]); ++i) {
750             total2 += ((dims[i] - 1) * dims[i] / 2) * dims[0] * dims[1] * dims[2] / dims[i];
751         }
752         if (total != total2) {
753             ts->printf(cvtest::TS::LOG, "forEach is not correct because total is invalid.\n");
754             errcount++;
755         }
756     }
757
758     // test cv::Mat::forEach
759     // with a matrix that has more dimensions than columns
760     // See https://github.com/opencv/opencv/issues/8447
761     {
762         const int dims[5] = { 2, 2, 2, 2, 2 };
763         typedef cv::Vec<int, 5> Pixel;
764
765         cv::Mat a = cv::Mat::zeros(5, dims, CV_32SC(5));
766         InitializerFunctor5D<Pixel> initializer;
767
768         a.forEach<Pixel>(initializer);
769
770         uint64 total = 0;
771         bool error_reported = false;
772         for (int i0 = 0; i0 < dims[0]; ++i0) {
773             for (int i1 = 0; i1 < dims[1]; ++i1) {
774                 for (int i2 = 0; i2 < dims[2]; ++i2) {
775                     for (int i3 = 0; i3 < dims[3]; ++i3) {
776                         for (int i4 = 0; i4 < dims[4]; ++i4) {
777                             const int i[5] = { i0, i1, i2, i3, i4 };
778                             Pixel& pixel = a.at<Pixel>(i);
779                             if (pixel[0] != i0 || pixel[1] != i1 || pixel[2] != i2 || pixel[3] != i3 || pixel[4] != i4) {
780                                 if (!error_reported) {
781                                     ts->printf(cvtest::TS::LOG, "forEach is not correct.\n"
782                                         "First error detected at position (%d, %d, %d, %d, %d), got value (%d, %d, %d, %d, %d).\n",
783                                         i0, i1, i2, i3, i4,
784                                         pixel[0], pixel[1], pixel[2], pixel[3], pixel[4]);
785                                     error_reported = true;
786                                 }
787                                 errcount++;
788                             }
789                             total += pixel[0];
790                             total += pixel[1];
791                             total += pixel[2];
792                             total += pixel[3];
793                             total += pixel[4];
794                         }
795                     }
796                 }
797             }
798         }
799         uint64 total2 = 0;
800         for (size_t i = 0; i < sizeof(dims) / sizeof(dims[0]); ++i) {
801             total2 += ((dims[i] - 1) * dims[i] / 2) * dims[0] * dims[1] * dims[2] * dims[3] * dims[4] / dims[i];
802         }
803         if (total != total2) {
804             ts->printf(cvtest::TS::LOG, "forEach is not correct because total is invalid.\n");
805             errcount++;
806         }
807     }
808
809     // test const cv::Mat::forEach
810     {
811         const Mat a(10, 10, CV_32SC3);
812         Mat b(10, 10, CV_32SC3);
813         const Mat & c = b;
814         a.forEach<Point3i>(EmptyFunctor<Point3i>());
815         b.forEach<Point3i>(EmptyFunctor<const Point3i>());
816         c.forEach<Point3i>(EmptyFunctor<Point3i>());
817         // tests compilation, no runtime check is needed
818     }
819
820     RNG rng;
821     const int MAX_DIM = 5, MAX_DIM_SZ = 10;
822     // sparse matrix operations
823     for( int si = 0; si < 10; si++ )
824     {
825         int depth = (unsigned)rng % 2 == 0 ? CV_32F : CV_64F;
826         int dims = ((unsigned)rng % MAX_DIM) + 1;
827         int i, k, size[MAX_DIM]={0}, idx[MAX_DIM]={0};
828         vector<string> all_idxs;
829         vector<double> all_vals;
830         vector<double> all_vals2;
831         string sidx, min_sidx, max_sidx;
832         double min_val=0, max_val=0;
833
834         int p = 1;
835         for( k = 0; k < dims; k++ )
836         {
837             size[k] = ((unsigned)rng % MAX_DIM_SZ) + 1;
838             p *= size[k];
839         }
840         SparseMat M( dims, size, depth );
841         map<string, double> M0;
842
843         int nz0 = (unsigned)rng % max(p/5,10);
844         nz0 = min(max(nz0, 1), p);
845         all_vals.resize(nz0);
846         all_vals2.resize(nz0);
847         Mat_<double> _all_vals(all_vals), _all_vals2(all_vals2);
848         rng.fill(_all_vals, CV_RAND_UNI, Scalar(-1000), Scalar(1000));
849         if( depth == CV_32F )
850         {
851             Mat _all_vals_f;
852             _all_vals.convertTo(_all_vals_f, CV_32F);
853             _all_vals_f.convertTo(_all_vals, CV_64F);
854         }
855         _all_vals.convertTo(_all_vals2, _all_vals2.type(), 2);
856         if( depth == CV_32F )
857         {
858             Mat _all_vals2_f;
859             _all_vals2.convertTo(_all_vals2_f, CV_32F);
860             _all_vals2_f.convertTo(_all_vals2, CV_64F);
861         }
862
863         minMaxLoc(_all_vals, &min_val, &max_val);
864         double _norm0 = cvtest::norm(_all_vals, CV_C);
865         double _norm1 = cvtest::norm(_all_vals, CV_L1);
866         double _norm2 = cvtest::norm(_all_vals, CV_L2);
867
868         for( i = 0; i < nz0; i++ )
869         {
870             for(;;)
871             {
872                 for( k = 0; k < dims; k++ )
873                     idx[k] = (unsigned)rng % size[k];
874                 sidx = idx2string(idx, dims);
875                 if( M0.count(sidx) == 0 )
876                     break;
877             }
878             all_idxs.push_back(sidx);
879             M0[sidx] = all_vals[i];
880             if( all_vals[i] == min_val )
881                 min_sidx = sidx;
882             if( all_vals[i] == max_val )
883                 max_sidx = sidx;
884             setValue(M, idx, all_vals[i], rng);
885             double v = getValue(M, idx, rng);
886             if( v != all_vals[i] )
887             {
888                 ts->printf(cvtest::TS::LOG, "%d. immediately after SparseMat[%s]=%.20g the current value is %.20g\n",
889                            i, sidx.c_str(), all_vals[i], v);
890                 errcount++;
891                 break;
892             }
893         }
894
895         Ptr<CvSparseMat> M2(cvCreateSparseMat(M));
896         MatND Md;
897         M.copyTo(Md);
898         SparseMat M3; SparseMat(Md).convertTo(M3, Md.type(), 2);
899
900         int nz1 = (int)M.nzcount(), nz2 = (int)M3.nzcount();
901         double norm0 = norm(M, CV_C);
902         double norm1 = norm(M, CV_L1);
903         double norm2 = norm(M, CV_L2);
904         double eps = depth == CV_32F ? FLT_EPSILON*100 : DBL_EPSILON*1000;
905
906         if( nz1 != nz0 || nz2 != nz0)
907         {
908             errcount++;
909             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",
910                        si, nz1, nz2, nz0 );
911             break;
912         }
913
914         if( fabs(norm0 - _norm0) > fabs(_norm0)*eps ||
915            fabs(norm1 - _norm1) > fabs(_norm1)*eps ||
916            fabs(norm2 - _norm2) > fabs(_norm2)*eps )
917         {
918             errcount++;
919             ts->printf(cvtest::TS::LOG, "%d: The norms are different: %.20g/%.20g/%.20g vs %.20g/%.20g/%.20g\n",
920                        si, norm0, norm1, norm2, _norm0, _norm1, _norm2 );
921             break;
922         }
923
924         int n = (unsigned)rng % max(p/5,10);
925         n = min(max(n, 1), p) + nz0;
926
927         for( i = 0; i < n; i++ )
928         {
929             double val1, val2, val3, val0;
930             if(i < nz0)
931             {
932                 sidx = all_idxs[i];
933                 string2idx(sidx, idx, dims);
934                 val0 = all_vals[i];
935             }
936             else
937             {
938                 for( k = 0; k < dims; k++ )
939                     idx[k] = (unsigned)rng % size[k];
940                 sidx = idx2string(idx, dims);
941                 val0 = M0[sidx];
942             }
943             val1 = getValue(M, idx, rng);
944             val2 = getValue(M2, idx);
945             val3 = getValue(M3, idx, rng);
946
947             if( val1 != val0 || val2 != val0 || fabs(val3 - val0*2) > fabs(val0*2)*FLT_EPSILON )
948             {
949                 errcount++;
950                 ts->printf(cvtest::TS::LOG, "SparseMat M[%s] = %g/%g/%g (while it should be %g)\n", sidx.c_str(), val1, val2, val3, val0 );
951                 break;
952             }
953         }
954
955         for( i = 0; i < n; i++ )
956         {
957             double val1, val2;
958             if(i < nz0)
959             {
960                 sidx = all_idxs[i];
961                 string2idx(sidx, idx, dims);
962             }
963             else
964             {
965                 for( k = 0; k < dims; k++ )
966                     idx[k] = (unsigned)rng % size[k];
967                 sidx = idx2string(idx, dims);
968             }
969             eraseValue(M, idx, rng);
970             eraseValue(M2, idx);
971             val1 = getValue(M, idx, rng);
972             val2 = getValue(M2, idx);
973             if( val1 != 0 || val2 != 0 )
974             {
975                 errcount++;
976                 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 );
977                 break;
978             }
979         }
980
981         int nz = (int)M.nzcount();
982         if( nz != 0 )
983         {
984             errcount++;
985             ts->printf(cvtest::TS::LOG, "The number of non-zero elements after removing all the elements = %d (while it should be 0)\n", nz );
986             break;
987         }
988
989         int idx1[MAX_DIM], idx2[MAX_DIM];
990         double val1 = 0, val2 = 0;
991         M3 = SparseMat(Md);
992         minMaxLoc(M3, &val1, &val2, idx1, idx2);
993         string s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
994         if( val1 != min_val || val2 != max_val || s1 != min_sidx || s2 != max_sidx )
995         {
996             errcount++;
997             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"
998                        "(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
999                        min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
1000             break;
1001         }
1002
1003         minMaxIdx(Md, &val1, &val2, idx1, idx2);
1004         s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
1005         if( (min_val < 0 && (val1 != min_val || s1 != min_sidx)) ||
1006            (max_val > 0 && (val2 != max_val || s2 != max_sidx)) )
1007         {
1008             errcount++;
1009             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"
1010                        "(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
1011                        min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
1012             break;
1013         }
1014     }
1015
1016     ts->set_failed_test_info(errcount == 0 ? cvtest::TS::OK : cvtest::TS::FAIL_INVALID_OUTPUT);
1017 }
1018
1019
1020 template <class ElemType>
1021 int calcDiffElemCountImpl(const vector<Mat>& mv, const Mat& m)
1022 {
1023     int diffElemCount = 0;
1024     const int mChannels = m.channels();
1025     for(int y = 0; y < m.rows; y++)
1026     {
1027         for(int x = 0; x < m.cols; x++)
1028         {
1029             const ElemType* mElem = &m.at<ElemType>(y,x*mChannels);
1030             size_t loc = 0;
1031             for(size_t i = 0; i < mv.size(); i++)
1032             {
1033                 const size_t mvChannel = mv[i].channels();
1034                 const ElemType* mvElem = &mv[i].at<ElemType>(y,x*(int)mvChannel);
1035                 for(size_t li = 0; li < mvChannel; li++)
1036                     if(mElem[loc + li] != mvElem[li])
1037                         diffElemCount++;
1038                 loc += mvChannel;
1039             }
1040             CV_Assert(loc == (size_t)mChannels);
1041         }
1042     }
1043     return diffElemCount;
1044 }
1045
1046 static
1047 int calcDiffElemCount(const vector<Mat>& mv, const Mat& m)
1048 {
1049     int depth = m.depth();
1050     switch (depth)
1051     {
1052     case CV_8U:
1053         return calcDiffElemCountImpl<uchar>(mv, m);
1054     case CV_8S:
1055         return calcDiffElemCountImpl<char>(mv, m);
1056     case CV_16U:
1057         return calcDiffElemCountImpl<unsigned short>(mv, m);
1058     case CV_16S:
1059         return calcDiffElemCountImpl<short int>(mv, m);
1060     case CV_32S:
1061         return calcDiffElemCountImpl<int>(mv, m);
1062     case CV_32F:
1063         return calcDiffElemCountImpl<float>(mv, m);
1064     case CV_64F:
1065         return calcDiffElemCountImpl<double>(mv, m);
1066     }
1067
1068     return INT_MAX;
1069 }
1070
1071 class Core_MergeSplitBaseTest : public cvtest::BaseTest
1072 {
1073 protected:
1074     virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng) = 0;
1075
1076     virtual void run(int)
1077     {
1078         // m is Mat
1079         // mv is vector<Mat>
1080         const int minMSize = 1;
1081         const int maxMSize = 100;
1082         const size_t maxMvSize = 10;
1083
1084         RNG& rng = theRNG();
1085         Size mSize(rng.uniform(minMSize, maxMSize), rng.uniform(minMSize, maxMSize));
1086         size_t mvSize = rng.uniform(1, maxMvSize);
1087
1088         int res = cvtest::TS::OK, curRes = res;
1089         curRes = run_case(CV_8U, mvSize, mSize, rng);
1090         res = curRes != cvtest::TS::OK ? curRes : res;
1091
1092         curRes = run_case(CV_8S, mvSize, mSize, rng);
1093         res = curRes != cvtest::TS::OK ? curRes : res;
1094
1095         curRes = run_case(CV_16U, mvSize, mSize, rng);
1096         res = curRes != cvtest::TS::OK ? curRes : res;
1097
1098         curRes = run_case(CV_16S, mvSize, mSize, rng);
1099         res = curRes != cvtest::TS::OK ? curRes : res;
1100
1101         curRes = run_case(CV_32S, mvSize, mSize, rng);
1102         res = curRes != cvtest::TS::OK ? curRes : res;
1103
1104         curRes = run_case(CV_32F, mvSize, mSize, rng);
1105         res = curRes != cvtest::TS::OK ? curRes : res;
1106
1107         curRes = run_case(CV_64F, mvSize, mSize, rng);
1108         res = curRes != cvtest::TS::OK ? curRes : res;
1109
1110         ts->set_failed_test_info(res);
1111     }
1112 };
1113
1114 class Core_MergeTest : public Core_MergeSplitBaseTest
1115 {
1116 public:
1117     Core_MergeTest() {}
1118     ~Core_MergeTest() {}
1119
1120 protected:
1121     virtual int run_case(int depth, size_t matCount, const Size& size, RNG& rng)
1122     {
1123         const int maxMatChannels = 10;
1124
1125         vector<Mat> src(matCount);
1126         int channels = 0;
1127         for(size_t i = 0; i < src.size(); i++)
1128         {
1129             Mat m(size, CV_MAKETYPE(depth, rng.uniform(1,maxMatChannels)));
1130             rng.fill(m, RNG::UNIFORM, 0, 100, true);
1131             channels += m.channels();
1132             src[i] = m;
1133         }
1134
1135         Mat dst;
1136         merge(src, dst);
1137
1138         // check result
1139         stringstream commonLog;
1140         commonLog << "Depth " << depth << " :";
1141         if(dst.depth() != depth)
1142         {
1143             ts->printf(cvtest::TS::LOG, "%s incorrect depth of dst (%d instead of %d)\n",
1144                        commonLog.str().c_str(), dst.depth(), depth);
1145             return cvtest::TS::FAIL_INVALID_OUTPUT;
1146         }
1147         if(dst.size() != size)
1148         {
1149             ts->printf(cvtest::TS::LOG, "%s incorrect size of dst (%d x %d instead of %d x %d)\n",
1150                        commonLog.str().c_str(), dst.rows, dst.cols, size.height, size.width);
1151             return cvtest::TS::FAIL_INVALID_OUTPUT;
1152         }
1153         if(dst.channels() != channels)
1154         {
1155             ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst (%d instead of %d)\n",
1156                        commonLog.str().c_str(), dst.channels(), channels);
1157             return cvtest::TS::FAIL_INVALID_OUTPUT;
1158         }
1159
1160         int diffElemCount = calcDiffElemCount(src, dst);
1161         if(diffElemCount > 0)
1162         {
1163             ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n",
1164                        commonLog.str().c_str(), static_cast<float>(diffElemCount)/(channels*size.area()));
1165             return cvtest::TS::FAIL_INVALID_OUTPUT;
1166         }
1167
1168         return cvtest::TS::OK;
1169     }
1170 };
1171
1172 class Core_SplitTest : public Core_MergeSplitBaseTest
1173 {
1174 public:
1175     Core_SplitTest() {}
1176     ~Core_SplitTest() {}
1177
1178 protected:
1179     virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng)
1180     {
1181         Mat src(size, CV_MAKETYPE(depth, (int)channels));
1182         rng.fill(src, RNG::UNIFORM, 0, 100, true);
1183
1184         vector<Mat> dst;
1185         split(src, dst);
1186
1187         // check result
1188         stringstream commonLog;
1189         commonLog << "Depth " << depth << " :";
1190         if(dst.size() != channels)
1191         {
1192             ts->printf(cvtest::TS::LOG, "%s incorrect count of matrices in dst (%d instead of %d)\n",
1193                        commonLog.str().c_str(), dst.size(), channels);
1194             return cvtest::TS::FAIL_INVALID_OUTPUT;
1195         }
1196         for(size_t i = 0; i < dst.size(); i++)
1197         {
1198             if(dst[i].size() != size)
1199             {
1200                 ts->printf(cvtest::TS::LOG, "%s incorrect size of dst[%d] (%d x %d instead of %d x %d)\n",
1201                            commonLog.str().c_str(), i, dst[i].rows, dst[i].cols, size.height, size.width);
1202                 return cvtest::TS::FAIL_INVALID_OUTPUT;
1203             }
1204             if(dst[i].depth() != depth)
1205             {
1206                 ts->printf(cvtest::TS::LOG, "%s: incorrect depth of dst[%d] (%d instead of %d)\n",
1207                            commonLog.str().c_str(), i, dst[i].depth(), depth);
1208                 return cvtest::TS::FAIL_INVALID_OUTPUT;
1209             }
1210             if(dst[i].channels() != 1)
1211             {
1212                 ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst[%d] (%d instead of %d)\n",
1213                            commonLog.str().c_str(), i, dst[i].channels(), 1);
1214                 return cvtest::TS::FAIL_INVALID_OUTPUT;
1215             }
1216         }
1217
1218         int diffElemCount = calcDiffElemCount(dst, src);
1219         if(diffElemCount > 0)
1220         {
1221             ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n",
1222                        commonLog.str().c_str(), static_cast<float>(diffElemCount)/(channels*size.area()));
1223             return cvtest::TS::FAIL_INVALID_OUTPUT;
1224         }
1225
1226         return cvtest::TS::OK;
1227     }
1228 };
1229
1230 TEST(Core_PCA, accuracy) { Core_PCATest test; test.safe_run(); }
1231 TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); }
1232 TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); }
1233
1234 TEST(Core_Merge, shape_operations) { Core_MergeTest test; test.safe_run(); }
1235 TEST(Core_Split, shape_operations) { Core_SplitTest test; test.safe_run(); }
1236
1237
1238 TEST(Core_IOArray, submat_assignment)
1239 {
1240     Mat1f A = Mat1f::zeros(2,2);
1241     Mat1f B = Mat1f::ones(1,3);
1242
1243     EXPECT_THROW( B.colRange(0,3).copyTo(A.row(0)), cv::Exception );
1244
1245     EXPECT_NO_THROW( B.colRange(0,2).copyTo(A.row(0)) );
1246
1247     EXPECT_EQ( 1.0f, A(0,0) );
1248     EXPECT_EQ( 1.0f, A(0,1) );
1249 }
1250
1251 void OutputArray_create1(OutputArray m) { m.create(1, 2, CV_32S); }
1252 void OutputArray_create2(OutputArray m) { m.create(1, 3, CV_32F); }
1253
1254 TEST(Core_IOArray, submat_create)
1255 {
1256     Mat1f A = Mat1f::zeros(2,2);
1257
1258     EXPECT_THROW( OutputArray_create1(A.row(0)), cv::Exception );
1259     EXPECT_THROW( OutputArray_create2(A.row(0)), cv::Exception );
1260 }
1261
1262 TEST(Core_Mat, issue4457_pass_null_ptr)
1263 {
1264     ASSERT_ANY_THROW(cv::Mat mask(45, 45, CV_32F, 0));
1265 }
1266
1267 TEST(Core_Mat, reshape_1942)
1268 {
1269     cv::Mat A = (cv::Mat_<float>(2,3) << 3.4884074, 1.4159607, 0.78737736,  2.3456569, -0.88010466, 0.3009364);
1270     int cn = 0;
1271     ASSERT_NO_THROW(
1272         cv::Mat_<float> M = A.reshape(3);
1273         cn = M.channels();
1274     );
1275     ASSERT_EQ(1, cn);
1276 }
1277
1278 static void check_ndim_shape(const cv::Mat &mat, int cn, int ndims, const int *sizes)
1279 {
1280     EXPECT_EQ(mat.channels(), cn);
1281     EXPECT_EQ(mat.dims, ndims);
1282
1283     if (mat.dims != ndims)
1284         return;
1285
1286     for (int i = 0; i < ndims; i++)
1287         EXPECT_EQ(mat.size[i], sizes[i]);
1288 }
1289
1290 TEST(Core_Mat, reshape_ndims_2)
1291 {
1292     const cv::Mat A(8, 16, CV_8UC3);
1293     cv::Mat B;
1294
1295     {
1296         int new_sizes_mask[] = { 0, 3, 4, 4 };
1297         int new_sizes_real[] = { 8, 3, 4, 4 };
1298         ASSERT_NO_THROW(B = A.reshape(1, 4, new_sizes_mask));
1299         check_ndim_shape(B, 1, 4, new_sizes_real);
1300     }
1301     {
1302         int new_sizes[] = { 16, 8 };
1303         ASSERT_NO_THROW(B = A.reshape(0, 2, new_sizes));
1304         check_ndim_shape(B, 3, 2, new_sizes);
1305         EXPECT_EQ(B.rows, new_sizes[0]);
1306         EXPECT_EQ(B.cols, new_sizes[1]);
1307     }
1308     {
1309         int new_sizes[] = { 2, 5, 1, 3 };
1310         cv::Mat A_sliced = A(cv::Range::all(), cv::Range(0, 15));
1311         ASSERT_ANY_THROW(A_sliced.reshape(4, 4, new_sizes));
1312     }
1313 }
1314
1315 TEST(Core_Mat, reshape_ndims_4)
1316 {
1317     const int sizes[] = { 2, 6, 4, 12 };
1318     const cv::Mat A(4, sizes, CV_8UC3);
1319     cv::Mat B;
1320
1321     {
1322         int new_sizes_mask[] = { 0, 864 };
1323         int new_sizes_real[] = { 2, 864 };
1324         ASSERT_NO_THROW(B = A.reshape(1, 2, new_sizes_mask));
1325         check_ndim_shape(B, 1, 2, new_sizes_real);
1326         EXPECT_EQ(B.rows, new_sizes_real[0]);
1327         EXPECT_EQ(B.cols, new_sizes_real[1]);
1328     }
1329     {
1330         int new_sizes_mask[] = { 4, 0, 0, 2, 3 };
1331         int new_sizes_real[] = { 4, 6, 4, 2, 3 };
1332         ASSERT_NO_THROW(B = A.reshape(0, 5, new_sizes_mask));
1333         check_ndim_shape(B, 3, 5, new_sizes_real);
1334     }
1335     {
1336         int new_sizes_mask[] = { 1, 1 };
1337         ASSERT_ANY_THROW(A.reshape(0, 2, new_sizes_mask));
1338     }
1339     {
1340         int new_sizes_mask[] = { 4, 6, 3, 3, 0 };
1341         ASSERT_ANY_THROW(A.reshape(0, 5, new_sizes_mask));
1342     }
1343 }
1344
1345 TEST(Core_Mat, push_back)
1346 {
1347     Mat a = (Mat_<float>(1,2) << 3.4884074f, 1.4159607f);
1348     Mat b = (Mat_<float>(1,2) << 0.78737736f, 2.3456569f);
1349
1350     a.push_back(b);
1351
1352     ASSERT_EQ(2, a.cols);
1353     ASSERT_EQ(2, a.rows);
1354
1355     ASSERT_FLOAT_EQ(3.4884074f, a.at<float>(0, 0));
1356     ASSERT_FLOAT_EQ(1.4159607f, a.at<float>(0, 1));
1357     ASSERT_FLOAT_EQ(0.78737736f, a.at<float>(1, 0));
1358     ASSERT_FLOAT_EQ(2.3456569f, a.at<float>(1, 1));
1359
1360     Mat c = (Mat_<float>(2,2) << -0.88010466f, 0.3009364f, 2.22399974f, -5.45933905f);
1361
1362     ASSERT_EQ(c.rows, a.cols);
1363
1364     a.push_back(c.t());
1365
1366     ASSERT_EQ(2, a.cols);
1367     ASSERT_EQ(4, a.rows);
1368
1369     ASSERT_FLOAT_EQ(3.4884074f, a.at<float>(0, 0));
1370     ASSERT_FLOAT_EQ(1.4159607f, a.at<float>(0, 1));
1371     ASSERT_FLOAT_EQ(0.78737736f, a.at<float>(1, 0));
1372     ASSERT_FLOAT_EQ(2.3456569f, a.at<float>(1, 1));
1373     ASSERT_FLOAT_EQ(-0.88010466f, a.at<float>(2, 0));
1374     ASSERT_FLOAT_EQ(2.22399974f, a.at<float>(2, 1));
1375     ASSERT_FLOAT_EQ(0.3009364f, a.at<float>(3, 0));
1376     ASSERT_FLOAT_EQ(-5.45933905f, a.at<float>(3, 1));
1377
1378     a.push_back(Mat::ones(2, 2, CV_32FC1));
1379
1380     ASSERT_EQ(6, a.rows);
1381
1382     for(int row=4; row<a.rows; row++) {
1383
1384         for(int col=0; col<a.cols; col++) {
1385
1386             ASSERT_FLOAT_EQ(1.f, a.at<float>(row, col));
1387         }
1388     }
1389 }
1390
1391 TEST(Core_Mat, copyNx1ToVector)
1392 {
1393     cv::Mat_<uchar> src(5, 1);
1394     cv::Mat_<uchar> ref_dst8;
1395     cv::Mat_<ushort> ref_dst16;
1396     std::vector<uchar> dst8;
1397     std::vector<ushort> dst16;
1398
1399     src << 1, 2, 3, 4, 5;
1400
1401     src.copyTo(ref_dst8);
1402     src.copyTo(dst8);
1403
1404     ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst8, cv::Mat_<uchar>(dst8));
1405
1406     src.convertTo(ref_dst16, CV_16U);
1407     src.convertTo(dst16, CV_16U);
1408
1409     ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst16, cv::Mat_<ushort>(dst16));
1410 }
1411
1412 TEST(Core_Matx, fromMat_)
1413 {
1414     Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
1415     Matx22d b(a);
1416     ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.);
1417 }
1418
1419 #ifdef CV_CXX11
1420
1421 TEST(Core_Matx, from_initializer_list)
1422 {
1423     Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
1424     Matx22d b = {10, 11, 12, 13};
1425     ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.);
1426 }
1427
1428 TEST(Core_Mat, regression_9507)
1429 {
1430     cv::Mat m = Mat::zeros(5, 5, CV_8UC3);
1431     cv::Mat m2{m};
1432     EXPECT_EQ(25u, m2.total());
1433 }
1434
1435 #endif // CXX11
1436
1437 TEST(Core_InputArray, empty)
1438 {
1439     vector<vector<Point> > data;
1440     ASSERT_TRUE( _InputArray(data).empty() );
1441 }
1442
1443 TEST(Core_CopyMask, bug1918)
1444 {
1445     Mat_<unsigned char> tmpSrc(100,100);
1446     tmpSrc = 124;
1447     Mat_<unsigned char> tmpMask(100,100);
1448     tmpMask = 255;
1449     Mat_<unsigned char> tmpDst(100,100);
1450     tmpDst = 2;
1451     tmpSrc.copyTo(tmpDst,tmpMask);
1452     ASSERT_EQ(sum(tmpDst)[0], 124*100*100);
1453 }
1454
1455 TEST(Core_SVD, orthogonality)
1456 {
1457     for( int i = 0; i < 2; i++ )
1458     {
1459         int type = i == 0 ? CV_32F : CV_64F;
1460         Mat mat_D(2, 2, type);
1461         mat_D.setTo(88.);
1462         Mat mat_U, mat_W;
1463         SVD::compute(mat_D, mat_W, mat_U, noArray(), SVD::FULL_UV);
1464         mat_U *= mat_U.t();
1465         ASSERT_LT(norm(mat_U, Mat::eye(2, 2, type), NORM_INF), 1e-5);
1466     }
1467 }
1468
1469
1470 TEST(Core_SparseMat, footprint)
1471 {
1472     int n = 1000000;
1473     int sz[] = { n, n };
1474     SparseMat m(2, sz, CV_64F);
1475
1476     int nodeSize0 = (int)m.hdr->nodeSize;
1477     double dataSize0 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6;
1478     printf("before: node size=%d bytes, data size=%.0f Mbytes\n", nodeSize0, dataSize0);
1479
1480     for (int i = 0; i < n; i++)
1481     {
1482         m.ref<double>(i, i) = 1;
1483     }
1484
1485     double dataSize1 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6;
1486     double threshold = (n*nodeSize0*1.6 + n*2.*sizeof(size_t))*1e-6;
1487     printf("after: data size=%.0f Mbytes, threshold=%.0f MBytes\n", dataSize1, threshold);
1488
1489     ASSERT_LE((int)m.hdr->nodeSize, 32);
1490     ASSERT_LE(dataSize1, threshold);
1491 }
1492
1493
1494 // Can't fix without dirty hacks or broken user code (PR #4159)
1495 TEST(Core_Mat_vector, DISABLED_OutputArray_create_getMat)
1496 {
1497     cv::Mat_<uchar> src_base(5, 1);
1498     std::vector<uchar> dst8;
1499
1500     src_base << 1, 2, 3, 4, 5;
1501
1502     Mat src(src_base);
1503     OutputArray _dst(dst8);
1504     {
1505         _dst.create(src.rows, src.cols, src.type());
1506         Mat dst = _dst.getMat();
1507         EXPECT_EQ(src.dims, dst.dims);
1508         EXPECT_EQ(src.cols, dst.cols);
1509         EXPECT_EQ(src.rows, dst.rows);
1510     }
1511 }
1512
1513 TEST(Core_Mat_vector, copyTo_roi_column)
1514 {
1515     cv::Mat_<uchar> src_base(5, 2);
1516     std::vector<uchar> dst1;
1517
1518     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1519
1520     Mat src_full(src_base);
1521     Mat src(src_full.col(0));
1522 #if 0 // Can't fix without dirty hacks or broken user code (PR #4159)
1523     OutputArray _dst(dst1);
1524     {
1525         _dst.create(src.rows, src.cols, src.type());
1526         Mat dst = _dst.getMat();
1527         EXPECT_EQ(src.dims, dst.dims);
1528         EXPECT_EQ(src.cols, dst.cols);
1529         EXPECT_EQ(src.rows, dst.rows);
1530     }
1531 #endif
1532
1533     std::vector<uchar> dst2;
1534     src.copyTo(dst2);
1535     std::cout << "src = " << src << std::endl;
1536     std::cout << "dst = " << Mat(dst2) << std::endl;
1537     EXPECT_EQ((size_t)5, dst2.size());
1538     EXPECT_EQ(1, (int)dst2[0]);
1539     EXPECT_EQ(3, (int)dst2[1]);
1540     EXPECT_EQ(5, (int)dst2[2]);
1541     EXPECT_EQ(7, (int)dst2[3]);
1542     EXPECT_EQ(9, (int)dst2[4]);
1543 }
1544
1545 TEST(Core_Mat_vector, copyTo_roi_row)
1546 {
1547     cv::Mat_<uchar> src_base(2, 5);
1548     std::vector<uchar> dst1;
1549
1550     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1551
1552     Mat src_full(src_base);
1553     Mat src(src_full.row(0));
1554     OutputArray _dst(dst1);
1555     {
1556         _dst.create(src.rows, src.cols, src.type());
1557         Mat dst = _dst.getMat();
1558         EXPECT_EQ(src.dims, dst.dims);
1559         EXPECT_EQ(src.cols, dst.cols);
1560         EXPECT_EQ(src.rows, dst.rows);
1561     }
1562
1563     std::vector<uchar> dst2;
1564     src.copyTo(dst2);
1565     std::cout << "src = " << src << std::endl;
1566     std::cout << "dst = " << Mat(dst2) << std::endl;
1567     EXPECT_EQ((size_t)5, dst2.size());
1568     EXPECT_EQ(1, (int)dst2[0]);
1569     EXPECT_EQ(2, (int)dst2[1]);
1570     EXPECT_EQ(3, (int)dst2[2]);
1571     EXPECT_EQ(4, (int)dst2[3]);
1572     EXPECT_EQ(5, (int)dst2[4]);
1573 }
1574
1575 TEST(Mat, regression_5991)
1576 {
1577     int sz[] = {2,3,2};
1578     Mat mat(3, sz, CV_32F, Scalar(1));
1579     ASSERT_NO_THROW(mat.convertTo(mat, CV_8U));
1580     EXPECT_EQ(sz[0], mat.size[0]);
1581     EXPECT_EQ(sz[1], mat.size[1]);
1582     EXPECT_EQ(sz[2], mat.size[2]);
1583     EXPECT_EQ(0, cvtest::norm(mat, Mat(3, sz, CV_8U, Scalar(1)), NORM_INF));
1584 }
1585
1586 #ifdef OPENCV_TEST_BIGDATA
1587 TEST(Mat, regression_6696_BigData_8Gb)
1588 {
1589     int width = 60000;
1590     int height = 10000;
1591
1592     Mat destImageBGR = Mat(height, width, CV_8UC3, Scalar(1, 2, 3, 0));
1593     Mat destImageA = Mat(height, width, CV_8UC1, Scalar::all(4));
1594
1595     vector<Mat> planes;
1596     split(destImageBGR, planes);
1597     planes.push_back(destImageA);
1598     merge(planes, destImageBGR);
1599
1600     EXPECT_EQ(1, destImageBGR.at<Vec4b>(0)[0]);
1601     EXPECT_EQ(2, destImageBGR.at<Vec4b>(0)[1]);
1602     EXPECT_EQ(3, destImageBGR.at<Vec4b>(0)[2]);
1603     EXPECT_EQ(4, destImageBGR.at<Vec4b>(0)[3]);
1604
1605     EXPECT_EQ(1, destImageBGR.at<Vec4b>(height-1, width-1)[0]);
1606     EXPECT_EQ(2, destImageBGR.at<Vec4b>(height-1, width-1)[1]);
1607     EXPECT_EQ(3, destImageBGR.at<Vec4b>(height-1, width-1)[2]);
1608     EXPECT_EQ(4, destImageBGR.at<Vec4b>(height-1, width-1)[3]);
1609 }
1610 #endif
1611
1612 TEST(Reduce, regression_should_fail_bug_4594)
1613 {
1614     cv::Mat src = cv::Mat::eye(4, 4, CV_8U);
1615     std::vector<int> dst;
1616
1617     EXPECT_THROW(cv::reduce(src, dst, 0, CV_REDUCE_MIN, CV_32S), cv::Exception);
1618     EXPECT_THROW(cv::reduce(src, dst, 0, CV_REDUCE_MAX, CV_32S), cv::Exception);
1619     EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_SUM, CV_32S));
1620     EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_AVG, CV_32S));
1621 }
1622
1623 TEST(Mat, push_back_vector)
1624 {
1625     cv::Mat result(1, 5, CV_32FC1);
1626
1627     std::vector<float> vec1(result.cols + 1);
1628     std::vector<int> vec2(result.cols);
1629
1630     EXPECT_THROW(result.push_back(vec1), cv::Exception);
1631     EXPECT_THROW(result.push_back(vec2), cv::Exception);
1632
1633     vec1.resize(result.cols);
1634
1635     for (int i = 0; i < 5; ++i)
1636         result.push_back(cv::Mat(vec1).reshape(1, 1));
1637
1638     ASSERT_EQ(6, result.rows);
1639 }
1640
1641 TEST(Mat, regression_5917_clone_empty)
1642 {
1643     Mat cloned;
1644     Mat_<Point2f> source(5, 0);
1645
1646     ASSERT_NO_THROW(cloned = source.clone());
1647 }
1648
1649 TEST(Mat, regression_7873_mat_vector_initialize)
1650 {
1651     std::vector<int> dims;
1652     dims.push_back(12);
1653     dims.push_back(3);
1654     dims.push_back(2);
1655     Mat multi_mat(dims, CV_32FC1, cv::Scalar(0));
1656
1657     ASSERT_EQ(3, multi_mat.dims);
1658     ASSERT_EQ(12, multi_mat.size[0]);
1659     ASSERT_EQ(3, multi_mat.size[1]);
1660     ASSERT_EQ(2, multi_mat.size[2]);
1661
1662     std::vector<Range> ranges;
1663     ranges.push_back(Range(1, 2));
1664     ranges.push_back(Range::all());
1665     ranges.push_back(Range::all());
1666     Mat sub_mat = multi_mat(ranges);
1667
1668     ASSERT_EQ(3, sub_mat.dims);
1669     ASSERT_EQ(1, sub_mat.size[0]);
1670     ASSERT_EQ(3, sub_mat.size[1]);
1671     ASSERT_EQ(2, sub_mat.size[2]);
1672 }
1673
1674 #ifdef CV_CXX_STD_ARRAY
1675 TEST(Core_Mat_array, outputArray_create_getMat)
1676 {
1677     cv::Mat_<uchar> src_base(5, 1);
1678     std::array<uchar, 5> dst8;
1679
1680     src_base << 1, 2, 3, 4, 5;
1681
1682     Mat src(src_base);
1683     OutputArray _dst(dst8);
1684
1685     {
1686         _dst.create(src.rows, src.cols, src.type());
1687         Mat dst = _dst.getMat();
1688         EXPECT_EQ(src.dims, dst.dims);
1689         EXPECT_EQ(src.cols, dst.cols);
1690         EXPECT_EQ(src.rows, dst.rows);
1691     }
1692 }
1693
1694 TEST(Core_Mat_array, copyTo_roi_column)
1695 {
1696     cv::Mat_<uchar> src_base(5, 2);
1697
1698     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1699
1700     Mat src_full(src_base);
1701     Mat src(src_full.col(0));
1702
1703     std::array<uchar, 5> dst1;
1704     src.copyTo(dst1);
1705     std::cout << "src = " << src << std::endl;
1706     std::cout << "dst = " << Mat(dst1) << std::endl;
1707     EXPECT_EQ((size_t)5, dst1.size());
1708     EXPECT_EQ(1, (int)dst1[0]);
1709     EXPECT_EQ(3, (int)dst1[1]);
1710     EXPECT_EQ(5, (int)dst1[2]);
1711     EXPECT_EQ(7, (int)dst1[3]);
1712     EXPECT_EQ(9, (int)dst1[4]);
1713 }
1714
1715 TEST(Core_Mat_array, copyTo_roi_row)
1716 {
1717     cv::Mat_<uchar> src_base(2, 5);
1718     std::array<uchar, 5> dst1;
1719
1720     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1721
1722     Mat src_full(src_base);
1723     Mat src(src_full.row(0));
1724     OutputArray _dst(dst1);
1725     {
1726         _dst.create(5, 1, src.type());
1727         Mat dst = _dst.getMat();
1728         EXPECT_EQ(src.dims, dst.dims);
1729         EXPECT_EQ(1, dst.cols);
1730         EXPECT_EQ(5, dst.rows);
1731     }
1732
1733     std::array<uchar, 5> dst2;
1734     src.copyTo(dst2);
1735     std::cout << "src = " << src << std::endl;
1736     std::cout << "dst = " << Mat(dst2) << std::endl;
1737     EXPECT_EQ(1, (int)dst2[0]);
1738     EXPECT_EQ(2, (int)dst2[1]);
1739     EXPECT_EQ(3, (int)dst2[2]);
1740     EXPECT_EQ(4, (int)dst2[3]);
1741     EXPECT_EQ(5, (int)dst2[4]);
1742 }
1743
1744 TEST(Core_Mat_array, SplitMerge)
1745 {
1746     std::array<cv::Mat, 3> src;
1747     for(size_t i=0; i<src.size(); ++i) {
1748         src[i].create(10, 10, CV_8U);
1749         src[i] = 127 * i;
1750     }
1751
1752     Mat merged;
1753     merge(src, merged);
1754
1755     std::array<cv::Mat, 3> dst;
1756     split(merged, dst);
1757
1758     Mat diff;
1759     for(size_t i=0; i<dst.size(); ++i) {
1760         absdiff(src[i], dst[i], diff);
1761         EXPECT_EQ(0, countNonZero(diff));
1762     }
1763 }
1764 #endif
1765
1766 TEST(Mat, regression_8680)
1767 {
1768    Mat_<Point2i> mat(3,1);
1769    ASSERT_EQ(mat.channels(), 2);
1770    mat.release();
1771    ASSERT_EQ(mat.channels(), 2);
1772 }
1773
1774 #ifdef CV_CXX11
1775
1776 TEST(Mat_, range_based_for)
1777 {
1778     Mat_<uchar> img = Mat_<uchar>::zeros(3, 3);
1779
1780     for(auto& pixel : img)
1781     {
1782         pixel = 1;
1783     }
1784
1785     Mat_<uchar> ref(3, 3);
1786     ref.setTo(Scalar(1));
1787     ASSERT_DOUBLE_EQ(norm(img, ref), 0.);
1788 }
1789
1790 TEST(Mat, from_initializer_list)
1791 {
1792     Mat A({1.f, 2.f, 3.f});
1793     Mat_<float> B(3, 1); B << 1, 2, 3;
1794
1795     ASSERT_EQ(A.type(), CV_32F);
1796     ASSERT_DOUBLE_EQ(norm(A, B, NORM_INF), 0.);
1797 }
1798
1799 TEST(Mat_, from_initializer_list)
1800 {
1801     Mat_<float> A = {1, 2, 3};
1802     Mat_<float> B(3, 1); B << 1, 2, 3;
1803
1804     ASSERT_DOUBLE_EQ(norm(A, B, NORM_INF), 0.);
1805 }
1806
1807 #endif