1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 #include "test_precomp.hpp"
5 
6 #ifdef HAVE_EIGEN
7 #include <Eigen/Core>
8 #include <Eigen/Dense>
9 #include "opencv2/core/eigen.hpp"
10 #endif
11 
12 #include "opencv2/core/cuda.hpp"
13 
14 namespace opencv_test { namespace {
15 
16 class Core_ReduceTest : public cvtest::BaseTest
17 {
18 public:
Core_ReduceTest()19     Core_ReduceTest() {}
20 protected:
21     void run( int);
22     int checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim );
23     int checkCase( int srcType, int dstType, int dim, Size sz );
24     int checkDim( int dim, Size sz );
25     int checkSize( Size sz );
26 };
27 
28 template<class Type>
testReduce(const Mat & src,Mat & sum,Mat & avg,Mat & max,Mat & min,int dim)29 void testReduce( const Mat& src, Mat& sum, Mat& avg, Mat& max, Mat& min, int dim )
30 {
31     assert( src.channels() == 1 );
32     if( dim == 0 ) // row
33     {
34         sum.create( 1, src.cols, CV_64FC1 );
35         max.create( 1, src.cols, CV_64FC1 );
36         min.create( 1, src.cols, CV_64FC1 );
37     }
38     else
39     {
40         sum.create( src.rows, 1, CV_64FC1 );
41         max.create( src.rows, 1, CV_64FC1 );
42         min.create( src.rows, 1, CV_64FC1 );
43     }
44     sum.setTo(Scalar(0));
45     max.setTo(Scalar(-DBL_MAX));
46     min.setTo(Scalar(DBL_MAX));
47 
48     const Mat_<Type>& src_ = src;
49     Mat_<double>& sum_ = (Mat_<double>&)sum;
50     Mat_<double>& min_ = (Mat_<double>&)min;
51     Mat_<double>& max_ = (Mat_<double>&)max;
52 
53     if( dim == 0 )
54     {
55         for( int ri = 0; ri < src.rows; ri++ )
56         {
57             for( int ci = 0; ci < src.cols; ci++ )
58             {
59                 sum_(0, ci) += src_(ri, ci);
60                 max_(0, ci) = std::max( max_(0, ci), (double)src_(ri, ci) );
61                 min_(0, ci) = std::min( min_(0, ci), (double)src_(ri, ci) );
62             }
63         }
64     }
65     else
66     {
67         for( int ci = 0; ci < src.cols; ci++ )
68         {
69             for( int ri = 0; ri < src.rows; ri++ )
70             {
71                 sum_(ri, 0) += src_(ri, ci);
72                 max_(ri, 0) = std::max( max_(ri, 0), (double)src_(ri, ci) );
73                 min_(ri, 0) = std::min( min_(ri, 0), (double)src_(ri, ci) );
74             }
75         }
76     }
77     sum.convertTo( avg, CV_64FC1 );
78     avg = avg * (1.0 / (dim==0 ? (double)src.rows : (double)src.cols));
79 }
80 
getMatTypeStr(int type,string & str)81 void getMatTypeStr( int type, string& str)
82 {
83     str = type == CV_8UC1 ? "CV_8UC1" :
84     type == CV_8SC1 ? "CV_8SC1" :
85     type == CV_16UC1 ? "CV_16UC1" :
86     type == CV_16SC1 ? "CV_16SC1" :
87     type == CV_32SC1 ? "CV_32SC1" :
88     type == CV_32FC1 ? "CV_32FC1" :
89     type == CV_64FC1 ? "CV_64FC1" : "unsupported matrix type";
90 }
91 
checkOp(const Mat & src,int dstType,int opType,const Mat & opRes,int dim)92 int Core_ReduceTest::checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim )
93 {
94     int srcType = src.type();
95     bool support = false;
96     if( opType == CV_REDUCE_SUM || opType == CV_REDUCE_AVG )
97     {
98         if( srcType == CV_8U && (dstType == CV_32S || dstType == CV_32F || dstType == CV_64F) )
99             support = true;
100         if( srcType == CV_16U && (dstType == CV_32F || dstType == CV_64F) )
101             support = true;
102         if( srcType == CV_16S && (dstType == CV_32F || dstType == CV_64F) )
103             support = true;
104         if( srcType == CV_32F && (dstType == CV_32F || dstType == CV_64F) )
105             support = true;
106         if( srcType == CV_64F && dstType == CV_64F)
107             support = true;
108     }
109     else if( opType == CV_REDUCE_MAX )
110     {
111         if( srcType == CV_8U && dstType == CV_8U )
112             support = true;
113         if( srcType == CV_32F && dstType == CV_32F )
114             support = true;
115         if( srcType == CV_64F && dstType == CV_64F )
116             support = true;
117     }
118     else if( opType == CV_REDUCE_MIN )
119     {
120         if( srcType == CV_8U && dstType == CV_8U)
121             support = true;
122         if( srcType == CV_32F && dstType == CV_32F)
123             support = true;
124         if( srcType == CV_64F && dstType == CV_64F)
125             support = true;
126     }
127     if( !support )
128         return cvtest::TS::OK;
129 
130     double eps = 0.0;
131     if ( opType == CV_REDUCE_SUM || opType == CV_REDUCE_AVG )
132     {
133         if ( dstType == CV_32F )
134             eps = 1.e-5;
135         else if( dstType == CV_64F )
136             eps = 1.e-8;
137         else if ( dstType == CV_32S )
138             eps = 0.6;
139     }
140 
141     assert( opRes.type() == CV_64FC1 );
142     Mat _dst, dst, diff;
143     cv::reduce( src, _dst, dim, opType, dstType );
144     _dst.convertTo( dst, CV_64FC1 );
145 
146     absdiff( opRes,dst,diff );
147     bool check = false;
148     if (dstType == CV_32F || dstType == CV_64F)
149         check = countNonZero(diff>eps*dst) > 0;
150     else
151         check = countNonZero(diff>eps) > 0;
152     if( check )
153     {
154         char msg[100];
155         const char* opTypeStr = opType == CV_REDUCE_SUM ? "CV_REDUCE_SUM" :
156         opType == CV_REDUCE_AVG ? "CV_REDUCE_AVG" :
157         opType == CV_REDUCE_MAX ? "CV_REDUCE_MAX" :
158         opType == CV_REDUCE_MIN ? "CV_REDUCE_MIN" : "unknown operation type";
159         string srcTypeStr, dstTypeStr;
160         getMatTypeStr( src.type(), srcTypeStr );
161         getMatTypeStr( dstType, dstTypeStr );
162         const char* dimStr = dim == 0 ? "ROWS" : "COLS";
163 
164         sprintf( msg, "bad accuracy with srcType = %s, dstType = %s, opType = %s, dim = %s",
165                 srcTypeStr.c_str(), dstTypeStr.c_str(), opTypeStr, dimStr );
166         ts->printf( cvtest::TS::LOG, msg );
167         return cvtest::TS::FAIL_BAD_ACCURACY;
168     }
169     return cvtest::TS::OK;
170 }
171 
checkCase(int srcType,int dstType,int dim,Size sz)172 int Core_ReduceTest::checkCase( int srcType, int dstType, int dim, Size sz )
173 {
174     int code = cvtest::TS::OK, tempCode;
175     Mat src, sum, avg, max, min;
176 
177     src.create( sz, srcType );
178     randu( src, Scalar(0), Scalar(100) );
179 
180     if( srcType == CV_8UC1 )
181         testReduce<uchar>( src, sum, avg, max, min, dim );
182     else if( srcType == CV_8SC1 )
183         testReduce<char>( src, sum, avg, max, min, dim );
184     else if( srcType == CV_16UC1 )
185         testReduce<unsigned short int>( src, sum, avg, max, min, dim );
186     else if( srcType == CV_16SC1 )
187         testReduce<short int>( src, sum, avg, max, min, dim );
188     else if( srcType == CV_32SC1 )
189         testReduce<int>( src, sum, avg, max, min, dim );
190     else if( srcType == CV_32FC1 )
191         testReduce<float>( src, sum, avg, max, min, dim );
192     else if( srcType == CV_64FC1 )
193         testReduce<double>( src, sum, avg, max, min, dim );
194     else
195         assert( 0 );
196 
197     // 1. sum
198     tempCode = checkOp( src, dstType, CV_REDUCE_SUM, sum, dim );
199     code = tempCode != cvtest::TS::OK ? tempCode : code;
200 
201     // 2. avg
202     tempCode = checkOp( src, dstType, CV_REDUCE_AVG, avg, dim );
203     code = tempCode != cvtest::TS::OK ? tempCode : code;
204 
205     // 3. max
206     tempCode = checkOp( src, dstType, CV_REDUCE_MAX, max, dim );
207     code = tempCode != cvtest::TS::OK ? tempCode : code;
208 
209     // 4. min
210     tempCode = checkOp( src, dstType, CV_REDUCE_MIN, min, dim );
211     code = tempCode != cvtest::TS::OK ? tempCode : code;
212 
213     return code;
214 }
215 
checkDim(int dim,Size sz)216 int Core_ReduceTest::checkDim( int dim, Size sz )
217 {
218     int code = cvtest::TS::OK, tempCode;
219 
220     // CV_8UC1
221     tempCode = checkCase( CV_8UC1, CV_8UC1, dim, sz );
222     code = tempCode != cvtest::TS::OK ? tempCode : code;
223 
224     tempCode = checkCase( CV_8UC1, CV_32SC1, dim, sz );
225     code = tempCode != cvtest::TS::OK ? tempCode : code;
226 
227     tempCode = checkCase( CV_8UC1, CV_32FC1, dim, sz );
228     code = tempCode != cvtest::TS::OK ? tempCode : code;
229 
230     tempCode = checkCase( CV_8UC1, CV_64FC1, dim, sz );
231     code = tempCode != cvtest::TS::OK ? tempCode : code;
232 
233     // CV_16UC1
234     tempCode = checkCase( CV_16UC1, CV_32FC1, dim, sz );
235     code = tempCode != cvtest::TS::OK ? tempCode : code;
236 
237     tempCode = checkCase( CV_16UC1, CV_64FC1, dim, sz );
238     code = tempCode != cvtest::TS::OK ? tempCode : code;
239 
240     // CV_16SC1
241     tempCode = checkCase( CV_16SC1, CV_32FC1, dim, sz );
242     code = tempCode != cvtest::TS::OK ? tempCode : code;
243 
244     tempCode = checkCase( CV_16SC1, CV_64FC1, dim, sz );
245     code = tempCode != cvtest::TS::OK ? tempCode : code;
246 
247     // CV_32FC1
248     tempCode = checkCase( CV_32FC1, CV_32FC1, dim, sz );
249     code = tempCode != cvtest::TS::OK ? tempCode : code;
250 
251     tempCode = checkCase( CV_32FC1, CV_64FC1, dim, sz );
252     code = tempCode != cvtest::TS::OK ? tempCode : code;
253 
254     // CV_64FC1
255     tempCode = checkCase( CV_64FC1, CV_64FC1, dim, sz );
256     code = tempCode != cvtest::TS::OK ? tempCode : code;
257 
258     return code;
259 }
260 
checkSize(Size sz)261 int Core_ReduceTest::checkSize( Size sz )
262 {
263     int code = cvtest::TS::OK, tempCode;
264 
265     tempCode = checkDim( 0, sz ); // rows
266     code = tempCode != cvtest::TS::OK ? tempCode : code;
267 
268     tempCode = checkDim( 1, sz ); // cols
269     code = tempCode != cvtest::TS::OK ? tempCode : code;
270 
271     return code;
272 }
273 
run(int)274 void Core_ReduceTest::run( int )
275 {
276     int code = cvtest::TS::OK, tempCode;
277 
278     tempCode = checkSize( Size(1,1) );
279     code = tempCode != cvtest::TS::OK ? tempCode : code;
280 
281     tempCode = checkSize( Size(1,100) );
282     code = tempCode != cvtest::TS::OK ? tempCode : code;
283 
284     tempCode = checkSize( Size(100,1) );
285     code = tempCode != cvtest::TS::OK ? tempCode : code;
286 
287     tempCode = checkSize( Size(1000,500) );
288     code = tempCode != cvtest::TS::OK ? tempCode : code;
289 
290     ts->set_failed_test_info( code );
291 }
292 
293 
294 #define CHECK_C
295 
TEST(Core_PCA,accuracy)296 TEST(Core_PCA, accuracy)
297 {
298     const Size sz(200, 500);
299 
300     double diffPrjEps, diffBackPrjEps,
301     prjEps, backPrjEps,
302     evalEps, evecEps;
303     int maxComponents = 100;
304     double retainedVariance = 0.95;
305     Mat rPoints(sz, CV_32FC1), rTestPoints(sz, CV_32FC1);
306     RNG rng(12345);
307 
308     rng.fill( rPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) );
309     rng.fill( rTestPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) );
310 
311     PCA rPCA( rPoints, Mat(), CV_PCA_DATA_AS_ROW, maxComponents ), cPCA;
312 
313     // 1. check C++ PCA & ROW
314     Mat rPrjTestPoints = rPCA.project( rTestPoints );
315     Mat rBackPrjTestPoints = rPCA.backProject( rPrjTestPoints );
316 
317     Mat avg(1, sz.width, CV_32FC1 );
318     cv::reduce( rPoints, avg, 0, CV_REDUCE_AVG );
319     Mat Q = rPoints - repeat( avg, rPoints.rows, 1 ), Qt = Q.t(), eval, evec;
320     Q = Qt * Q;
321     Q = Q /(float)rPoints.rows;
322 
323     eigen( Q, eval, evec );
324     /*SVD svd(Q);
325      evec = svd.vt;
326      eval = svd.w;*/
327 
328     Mat subEval( maxComponents, 1, eval.type(), eval.ptr() ),
329     subEvec( maxComponents, evec.cols, evec.type(), evec.ptr() );
330 
331 #ifdef CHECK_C
332     Mat prjTestPoints, backPrjTestPoints, cPoints = rPoints.t(), cTestPoints = rTestPoints.t();
333     CvMat _points, _testPoints, _avg, _eval, _evec, _prjTestPoints, _backPrjTestPoints;
334 #endif
335 
336     // check eigen()
337     double eigenEps = 1e-4;
338     double err;
339     for(int i = 0; i < Q.rows; i++ )
340     {
341         Mat v = evec.row(i).t();
342         Mat Qv = Q * v;
343 
344         Mat lv = eval.at<float>(i,0) * v;
345         err = cvtest::norm(Qv, lv, NORM_L2 | NORM_RELATIVE);
346         EXPECT_LE(err, eigenEps) << "bad accuracy of eigen(); i = " << i;
347     }
348     // check pca eigenvalues
349     evalEps = 1e-5, evecEps = 5e-3;
350     err = cvtest::norm(rPCA.eigenvalues, subEval, NORM_L2 | NORM_RELATIVE);
351     EXPECT_LE(err , evalEps) << "pca.eigenvalues is incorrect (CV_PCA_DATA_AS_ROW)";
352     // check pca eigenvectors
353     for(int i = 0; i < subEvec.rows; i++)
354     {
355         Mat r0 = rPCA.eigenvectors.row(i);
356         Mat r1 = subEvec.row(i);
357         // eigenvectors have normalized length, but both directions v and -v are valid
358         double err1 = cvtest::norm(r0, r1, NORM_L2 | NORM_RELATIVE);
359         double err2 = cvtest::norm(r0, -r1, NORM_L2 | NORM_RELATIVE);
360         err = std::min(err1, err2);
361         if (err > evecEps)
362         {
363             Mat tmp;
364             absdiff(rPCA.eigenvectors, subEvec, tmp);
365             double mval = 0; Point mloc;
366             minMaxLoc(tmp, 0, &mval, 0, &mloc);
367 
368             EXPECT_LE(err, evecEps) << "pca.eigenvectors is incorrect (CV_PCA_DATA_AS_ROW) at " << i << " "
369                 << cv::format("max diff is %g at (i=%d, j=%d) (%g vs %g)\n",
370                         mval, mloc.y, mloc.x, rPCA.eigenvectors.at<float>(mloc.y, mloc.x),
371                         subEvec.at<float>(mloc.y, mloc.x))
372                 << "r0=" << r0 << std::endl
373                 << "r1=" << r1 << std::endl
374                 << "err1=" << err1 << " err2=" << err2
375             ;
376         }
377     }
378 
379     prjEps = 1.265, backPrjEps = 1.265;
380     for( int i = 0; i < rTestPoints.rows; i++ )
381     {
382         // check pca project
383         Mat subEvec_t = subEvec.t();
384         Mat prj = rTestPoints.row(i) - avg; prj *= subEvec_t;
385         err = cvtest::norm(rPrjTestPoints.row(i), prj, NORM_L2 | NORM_RELATIVE);
386         if (err < prjEps)
387         {
388             EXPECT_LE(err, prjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_ROW)";
389             continue;
390         }
391         // check pca backProject
392         Mat backPrj = rPrjTestPoints.row(i) * subEvec + avg;
393         err = cvtest::norm(rBackPrjTestPoints.row(i), backPrj, NORM_L2 | NORM_RELATIVE);
394         if (err > backPrjEps)
395         {
396             EXPECT_LE(err, backPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_ROW)";
397             continue;
398         }
399     }
400 
401     // 2. check C++ PCA & COL
402     cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, maxComponents );
403     diffPrjEps = 1, diffBackPrjEps = 1;
404     Mat ocvPrjTestPoints = cPCA.project(rTestPoints.t());
405     err = cvtest::norm(cv::abs(ocvPrjTestPoints), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE);
406     ASSERT_LE(err, diffPrjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_COL)";
407     err = cvtest::norm(cPCA.backProject(ocvPrjTestPoints), rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE);
408     ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_COL)";
409 
410     // 3. check C++ PCA w/retainedVariance
411     cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, retainedVariance );
412     diffPrjEps = 1, diffBackPrjEps = 1;
413     Mat rvPrjTestPoints = cPCA.project(rTestPoints.t());
414 
415     if( cPCA.eigenvectors.rows > maxComponents)
416         err = cvtest::norm(cv::abs(rvPrjTestPoints.rowRange(0,maxComponents)), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE);
417     else
418         err = cvtest::norm(cv::abs(rvPrjTestPoints), cv::abs(rPrjTestPoints.colRange(0,cPCA.eigenvectors.rows).t()), NORM_L2 | NORM_RELATIVE);
419 
420     ASSERT_LE(err, diffPrjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_COL); retainedVariance=" << retainedVariance;
421     err = cvtest::norm(cPCA.backProject(rvPrjTestPoints), rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE);
422     ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); retainedVariance=" << retainedVariance;
423 
424 #ifdef CHECK_C
425     // 4. check C PCA & ROW
426     _points = cvMat(rPoints);
427     _testPoints = cvMat(rTestPoints);
428     _avg = cvMat(avg);
429     _eval = cvMat(eval);
430     _evec = cvMat(evec);
431     prjTestPoints.create(rTestPoints.rows, maxComponents, rTestPoints.type() );
432     backPrjTestPoints.create(rPoints.size(), rPoints.type() );
433     _prjTestPoints = cvMat(prjTestPoints);
434     _backPrjTestPoints = cvMat(backPrjTestPoints);
435 
436     cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_ROW );
437     cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
438     cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
439 
440     err = cvtest::norm(prjTestPoints, rPrjTestPoints, NORM_L2 | NORM_RELATIVE);
441     ASSERT_LE(err, diffPrjEps) << "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_ROW)";
442     err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints, NORM_L2 | NORM_RELATIVE);
443     ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_ROW)";
444 
445     // 5. check C PCA & COL
446     _points = cvMat(cPoints);
447     _testPoints = cvMat(cTestPoints);
448     avg = avg.t(); _avg = cvMat(avg);
449     eval = eval.t(); _eval = cvMat(eval);
450     evec = evec.t(); _evec = cvMat(evec);
451     prjTestPoints = prjTestPoints.t(); _prjTestPoints = cvMat(prjTestPoints);
452     backPrjTestPoints = backPrjTestPoints.t(); _backPrjTestPoints = cvMat(backPrjTestPoints);
453 
454     cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_COL );
455     cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
456     cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
457 
458     err = cvtest::norm(cv::abs(prjTestPoints), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE);
459     ASSERT_LE(err, diffPrjEps) << "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_COL)";
460     err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE);
461     ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_COL)";
462 #endif
463     // Test read and write
464     FileStorage fs( "PCA_store.yml", FileStorage::WRITE );
465     rPCA.write( fs );
466     fs.release();
467 
468     PCA lPCA;
469     fs.open( "PCA_store.yml", FileStorage::READ );
470     lPCA.read( fs.root() );
471     err = cvtest::norm(rPCA.eigenvectors, lPCA.eigenvectors, NORM_L2 | NORM_RELATIVE);
472     EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)";
473     err = cvtest::norm(rPCA.eigenvalues, lPCA.eigenvalues, NORM_L2 | NORM_RELATIVE);
474     EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)";
475     err = cvtest::norm(rPCA.mean, lPCA.mean, NORM_L2 | NORM_RELATIVE);
476     EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)";
477 }
478 
479 class Core_ArrayOpTest : public cvtest::BaseTest
480 {
481 public:
482     Core_ArrayOpTest();
483     ~Core_ArrayOpTest();
484 protected:
485     void run(int);
486 };
487 
488 
Core_ArrayOpTest()489 Core_ArrayOpTest::Core_ArrayOpTest()
490 {
491 }
~Core_ArrayOpTest()492 Core_ArrayOpTest::~Core_ArrayOpTest() {}
493 
idx2string(const int * idx,int dims)494 static string idx2string(const int* idx, int dims)
495 {
496     char buf[256];
497     char* ptr = buf;
498     for( int k = 0; k < dims; k++ )
499     {
500         sprintf(ptr, "%4d ", idx[k]);
501         ptr += strlen(ptr);
502     }
503     ptr[-1] = '\0';
504     return string(buf);
505 }
506 
string2idx(const string & s,int * idx,int dims)507 static const int* string2idx(const string& s, int* idx, int dims)
508 {
509     const char* ptr = s.c_str();
510     for( int k = 0; k < dims; k++ )
511     {
512         int n = 0;
513         sscanf(ptr, "%d%n", idx + k, &n);
514         ptr += n;
515     }
516     return idx;
517 }
518 
getValue(SparseMat & M,const int * idx,RNG & rng)519 static double getValue(SparseMat& M, const int* idx, RNG& rng)
520 {
521     int d = M.dims();
522     size_t hv = 0, *phv = 0;
523     if( (unsigned)rng % 2 )
524     {
525         hv = d == 2 ? M.hash(idx[0], idx[1]) :
526         d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
527         phv = &hv;
528     }
529 
530     const uchar* ptr = d == 2 ? M.ptr(idx[0], idx[1], false, phv) :
531     d == 3 ? M.ptr(idx[0], idx[1], idx[2], false, phv) :
532     M.ptr(idx, false, phv);
533     return !ptr ? 0 : M.type() == CV_32F ? *(float*)ptr : M.type() == CV_64F ? *(double*)ptr : 0;
534 }
535 
getValue(const CvSparseMat * M,const int * idx)536 static double getValue(const CvSparseMat* M, const int* idx)
537 {
538     int type = 0;
539     const uchar* ptr = cvPtrND(M, idx, &type, 0);
540     return !ptr ? 0 : type == CV_32F ? *(float*)ptr : type == CV_64F ? *(double*)ptr : 0;
541 }
542 
eraseValue(SparseMat & M,const int * idx,RNG & rng)543 static void eraseValue(SparseMat& M, const int* idx, RNG& rng)
544 {
545     int d = M.dims();
546     size_t hv = 0, *phv = 0;
547     if( (unsigned)rng % 2 )
548     {
549         hv = d == 2 ? M.hash(idx[0], idx[1]) :
550         d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
551         phv = &hv;
552     }
553 
554     if( d == 2 )
555         M.erase(idx[0], idx[1], phv);
556     else if( d == 3 )
557         M.erase(idx[0], idx[1], idx[2], phv);
558     else
559         M.erase(idx, phv);
560 }
561 
eraseValue(CvSparseMat * M,const int * idx)562 static void eraseValue(CvSparseMat* M, const int* idx)
563 {
564     cvClearND(M, idx);
565 }
566 
setValue(SparseMat & M,const int * idx,double value,RNG & rng)567 static void setValue(SparseMat& M, const int* idx, double value, RNG& rng)
568 {
569     int d = M.dims();
570     size_t hv = 0, *phv = 0;
571     if( (unsigned)rng % 2 )
572     {
573         hv = d == 2 ? M.hash(idx[0], idx[1]) :
574         d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
575         phv = &hv;
576     }
577 
578     uchar* ptr = d == 2 ? M.ptr(idx[0], idx[1], true, phv) :
579     d == 3 ? M.ptr(idx[0], idx[1], idx[2], true, phv) :
580     M.ptr(idx, true, phv);
581     if( M.type() == CV_32F )
582         *(float*)ptr = (float)value;
583     else if( M.type() == CV_64F )
584         *(double*)ptr = value;
585     else
586         CV_Error(CV_StsUnsupportedFormat, "");
587 }
588 
589 template<typename Pixel>
590 struct InitializerFunctor{
591     /// Initializer for cv::Mat::forEach test
operator ()opencv_test::__anondf631fe40111::InitializerFunctor592     void operator()(Pixel & pixel, const int * idx) const {
593         pixel.x = idx[0];
594         pixel.y = idx[1];
595         pixel.z = idx[2];
596     }
597 };
598 
599 template<typename Pixel>
600 struct InitializerFunctor5D{
601     /// Initializer for cv::Mat::forEach test (5 dimensional case)
operator ()opencv_test::__anondf631fe40111::InitializerFunctor5D602     void operator()(Pixel & pixel, const int * idx) const {
603         pixel[0] = idx[0];
604         pixel[1] = idx[1];
605         pixel[2] = idx[2];
606         pixel[3] = idx[3];
607         pixel[4] = idx[4];
608     }
609 };
610 
611 template<typename Pixel>
612 struct EmptyFunctor
613 {
operator ()opencv_test::__anondf631fe40111::EmptyFunctor614     void operator()(const Pixel &, const int *) const {}
615 };
616 
617 
run(int)618 void Core_ArrayOpTest::run( int /* start_from */)
619 {
620     int errcount = 0;
621 
622     // dense matrix operations
623     {
624         int sz3[] = {5, 10, 15};
625         MatND A(3, sz3, CV_32F), B(3, sz3, CV_16SC4);
626         CvMatND matA = cvMatND(A), matB = cvMatND(B);
627         RNG rng;
628         rng.fill(A, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
629         rng.fill(B, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
630 
631         int idx0[] = {3,4,5}, idx1[] = {0, 9, 7};
632         float val0 = 130;
633         Scalar val1(-1000, 30, 3, 8);
634         cvSetRealND(&matA, idx0, val0);
635         cvSetReal3D(&matA, idx1[0], idx1[1], idx1[2], -val0);
636         cvSetND(&matB, idx0, cvScalar(val1));
637         cvSet3D(&matB, idx1[0], idx1[1], idx1[2], cvScalar(-val1));
638         Ptr<CvMatND> matC(cvCloneMatND(&matB));
639 
640         if( A.at<float>(idx0[0], idx0[1], idx0[2]) != val0 ||
641            A.at<float>(idx1[0], idx1[1], idx1[2]) != -val0 ||
642            cvGetReal3D(&matA, idx0[0], idx0[1], idx0[2]) != val0 ||
643            cvGetRealND(&matA, idx1) != -val0 ||
644 
645            Scalar(B.at<Vec4s>(idx0[0], idx0[1], idx0[2])) != val1 ||
646            Scalar(B.at<Vec4s>(idx1[0], idx1[1], idx1[2])) != -val1 ||
647            Scalar(cvGet3D(matC, idx0[0], idx0[1], idx0[2])) != val1 ||
648            Scalar(cvGetND(matC, idx1)) != -val1 )
649         {
650             ts->printf(cvtest::TS::LOG, "one of cvSetReal3D, cvSetRealND, cvSet3D, cvSetND "
651                        "or the corresponding *Get* functions is not correct\n");
652             errcount++;
653         }
654     }
655     // test cv::Mat::forEach
656     {
657         const int dims[3] = { 101, 107, 7 };
658         typedef cv::Point3i Pixel;
659 
660         cv::Mat a = cv::Mat::zeros(3, dims, CV_32SC3);
661         InitializerFunctor<Pixel> initializer;
662 
663         a.forEach<Pixel>(initializer);
664 
665         uint64 total = 0;
666         bool error_reported = false;
667         for (int i0 = 0; i0 < dims[0]; ++i0) {
668             for (int i1 = 0; i1 < dims[1]; ++i1) {
669                 for (int i2 = 0; i2 < dims[2]; ++i2) {
670                     Pixel& pixel = a.at<Pixel>(i0, i1, i2);
671                     if (pixel.x != i0 || pixel.y != i1 || pixel.z != i2) {
672                         if (!error_reported) {
673                             ts->printf(cvtest::TS::LOG, "forEach is not correct.\n"
674                                 "First error detected at (%d, %d, %d).\n", pixel.x, pixel.y, pixel.z);
675                             error_reported = true;
676                         }
677                         errcount++;
678                     }
679                     total += pixel.x;
680                     total += pixel.y;
681                     total += pixel.z;
682                 }
683             }
684         }
685         uint64 total2 = 0;
686         for (size_t i = 0; i < sizeof(dims) / sizeof(dims[0]); ++i) {
687             total2 += ((dims[i] - 1) * dims[i] / 2) * dims[0] * dims[1] * dims[2] / dims[i];
688         }
689         if (total != total2) {
690             ts->printf(cvtest::TS::LOG, "forEach is not correct because total is invalid.\n");
691             errcount++;
692         }
693     }
694 
695     // test cv::Mat::forEach
696     // with a matrix that has more dimensions than columns
697     // See https://github.com/opencv/opencv/issues/8447
698     {
699         const int dims[5] = { 2, 2, 2, 2, 2 };
700         typedef cv::Vec<int, 5> Pixel;
701 
702         cv::Mat a = cv::Mat::zeros(5, dims, CV_32SC(5));
703         InitializerFunctor5D<Pixel> initializer;
704 
705         a.forEach<Pixel>(initializer);
706 
707         uint64 total = 0;
708         bool error_reported = false;
709         for (int i0 = 0; i0 < dims[0]; ++i0) {
710             for (int i1 = 0; i1 < dims[1]; ++i1) {
711                 for (int i2 = 0; i2 < dims[2]; ++i2) {
712                     for (int i3 = 0; i3 < dims[3]; ++i3) {
713                         for (int i4 = 0; i4 < dims[4]; ++i4) {
714                             const int i[5] = { i0, i1, i2, i3, i4 };
715                             Pixel& pixel = a.at<Pixel>(i);
716                             if (pixel[0] != i0 || pixel[1] != i1 || pixel[2] != i2 || pixel[3] != i3 || pixel[4] != i4) {
717                                 if (!error_reported) {
718                                     ts->printf(cvtest::TS::LOG, "forEach is not correct.\n"
719                                         "First error detected at position (%d, %d, %d, %d, %d), got value (%d, %d, %d, %d, %d).\n",
720                                         i0, i1, i2, i3, i4,
721                                         pixel[0], pixel[1], pixel[2], pixel[3], pixel[4]);
722                                     error_reported = true;
723                                 }
724                                 errcount++;
725                             }
726                             total += pixel[0];
727                             total += pixel[1];
728                             total += pixel[2];
729                             total += pixel[3];
730                             total += pixel[4];
731                         }
732                     }
733                 }
734             }
735         }
736         uint64 total2 = 0;
737         for (size_t i = 0; i < sizeof(dims) / sizeof(dims[0]); ++i) {
738             total2 += ((dims[i] - 1) * dims[i] / 2) * dims[0] * dims[1] * dims[2] * dims[3] * dims[4] / dims[i];
739         }
740         if (total != total2) {
741             ts->printf(cvtest::TS::LOG, "forEach is not correct because total is invalid.\n");
742             errcount++;
743         }
744     }
745 
746     // test const cv::Mat::forEach
747     {
748         const Mat a(10, 10, CV_32SC3);
749         Mat b(10, 10, CV_32SC3);
750         const Mat & c = b;
751         a.forEach<Point3i>(EmptyFunctor<Point3i>());
752         b.forEach<Point3i>(EmptyFunctor<const Point3i>());
753         c.forEach<Point3i>(EmptyFunctor<Point3i>());
754         // tests compilation, no runtime check is needed
755     }
756 
757     RNG rng;
758     const int MAX_DIM = 5, MAX_DIM_SZ = 10;
759     // sparse matrix operations
760     for( int si = 0; si < 10; si++ )
761     {
762         int depth = (unsigned)rng % 2 == 0 ? CV_32F : CV_64F;
763         int dims = ((unsigned)rng % MAX_DIM) + 1;
764         int i, k, size[MAX_DIM]={0}, idx[MAX_DIM]={0};
765         vector<string> all_idxs;
766         vector<double> all_vals;
767         vector<double> all_vals2;
768         string sidx, min_sidx, max_sidx;
769         double min_val=0, max_val=0;
770 
771         int p = 1;
772         for( k = 0; k < dims; k++ )
773         {
774             size[k] = ((unsigned)rng % MAX_DIM_SZ) + 1;
775             p *= size[k];
776         }
777         SparseMat M( dims, size, depth );
778         map<string, double> M0;
779 
780         int nz0 = (unsigned)rng % std::max(p/5,10);
781         nz0 = std::min(std::max(nz0, 1), p);
782         all_vals.resize(nz0);
783         all_vals2.resize(nz0);
784         Mat_<double> _all_vals(all_vals), _all_vals2(all_vals2);
785         rng.fill(_all_vals, CV_RAND_UNI, Scalar(-1000), Scalar(1000));
786         if( depth == CV_32F )
787         {
788             Mat _all_vals_f;
789             _all_vals.convertTo(_all_vals_f, CV_32F);
790             _all_vals_f.convertTo(_all_vals, CV_64F);
791         }
792         _all_vals.convertTo(_all_vals2, _all_vals2.type(), 2);
793         if( depth == CV_32F )
794         {
795             Mat _all_vals2_f;
796             _all_vals2.convertTo(_all_vals2_f, CV_32F);
797             _all_vals2_f.convertTo(_all_vals2, CV_64F);
798         }
799 
800         minMaxLoc(_all_vals, &min_val, &max_val);
801         double _norm0 = cv/*test*/::norm(_all_vals, CV_C);
802         double _norm1 = cv/*test*/::norm(_all_vals, CV_L1);
803         double _norm2 = cv/*test*/::norm(_all_vals, CV_L2);
804 
805         for( i = 0; i < nz0; i++ )
806         {
807             for(;;)
808             {
809                 for( k = 0; k < dims; k++ )
810                     idx[k] = (unsigned)rng % size[k];
811                 sidx = idx2string(idx, dims);
812                 if( M0.count(sidx) == 0 )
813                     break;
814             }
815             all_idxs.push_back(sidx);
816             M0[sidx] = all_vals[i];
817             if( all_vals[i] == min_val )
818                 min_sidx = sidx;
819             if( all_vals[i] == max_val )
820                 max_sidx = sidx;
821             setValue(M, idx, all_vals[i], rng);
822             double v = getValue(M, idx, rng);
823             if( v != all_vals[i] )
824             {
825                 ts->printf(cvtest::TS::LOG, "%d. immediately after SparseMat[%s]=%.20g the current value is %.20g\n",
826                            i, sidx.c_str(), all_vals[i], v);
827                 errcount++;
828                 break;
829             }
830         }
831 
832         Ptr<CvSparseMat> M2(cvCreateSparseMat(M));
833         MatND Md;
834         M.copyTo(Md);
835         SparseMat M3; SparseMat(Md).convertTo(M3, Md.type(), 2);
836 
837         int nz1 = (int)M.nzcount(), nz2 = (int)M3.nzcount();
838         double norm0 = cv/*test*/::norm(M, CV_C);
839         double norm1 = cv/*test*/::norm(M, CV_L1);
840         double norm2 = cv/*test*/::norm(M, CV_L2);
841         double eps = depth == CV_32F ? FLT_EPSILON*100 : DBL_EPSILON*1000;
842 
843         if( nz1 != nz0 || nz2 != nz0)
844         {
845             errcount++;
846             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",
847                        si, nz1, nz2, nz0 );
848             break;
849         }
850 
851         if( fabs(norm0 - _norm0) > fabs(_norm0)*eps ||
852            fabs(norm1 - _norm1) > fabs(_norm1)*eps ||
853            fabs(norm2 - _norm2) > fabs(_norm2)*eps )
854         {
855             errcount++;
856             ts->printf(cvtest::TS::LOG, "%d: The norms are different: %.20g/%.20g/%.20g vs %.20g/%.20g/%.20g\n",
857                        si, norm0, norm1, norm2, _norm0, _norm1, _norm2 );
858             break;
859         }
860 
861         int n = (unsigned)rng % std::max(p/5,10);
862         n = std::min(std::max(n, 1), p) + nz0;
863 
864         for( i = 0; i < n; i++ )
865         {
866             double val1, val2, val3, val0;
867             if(i < nz0)
868             {
869                 sidx = all_idxs[i];
870                 string2idx(sidx, idx, dims);
871                 val0 = all_vals[i];
872             }
873             else
874             {
875                 for( k = 0; k < dims; k++ )
876                     idx[k] = (unsigned)rng % size[k];
877                 sidx = idx2string(idx, dims);
878                 val0 = M0[sidx];
879             }
880             val1 = getValue(M, idx, rng);
881             val2 = getValue(M2, idx);
882             val3 = getValue(M3, idx, rng);
883 
884             if( val1 != val0 || val2 != val0 || fabs(val3 - val0*2) > fabs(val0*2)*FLT_EPSILON )
885             {
886                 errcount++;
887                 ts->printf(cvtest::TS::LOG, "SparseMat M[%s] = %g/%g/%g (while it should be %g)\n", sidx.c_str(), val1, val2, val3, val0 );
888                 break;
889             }
890         }
891 
892         for( i = 0; i < n; i++ )
893         {
894             double val1, val2;
895             if(i < nz0)
896             {
897                 sidx = all_idxs[i];
898                 string2idx(sidx, idx, dims);
899             }
900             else
901             {
902                 for( k = 0; k < dims; k++ )
903                     idx[k] = (unsigned)rng % size[k];
904                 sidx = idx2string(idx, dims);
905             }
906             eraseValue(M, idx, rng);
907             eraseValue(M2, idx);
908             val1 = getValue(M, idx, rng);
909             val2 = getValue(M2, idx);
910             if( val1 != 0 || val2 != 0 )
911             {
912                 errcount++;
913                 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 );
914                 break;
915             }
916         }
917 
918         int nz = (int)M.nzcount();
919         if( nz != 0 )
920         {
921             errcount++;
922             ts->printf(cvtest::TS::LOG, "The number of non-zero elements after removing all the elements = %d (while it should be 0)\n", nz );
923             break;
924         }
925 
926         int idx1[MAX_DIM], idx2[MAX_DIM];
927         double val1 = 0, val2 = 0;
928         M3 = SparseMat(Md);
929         cv::minMaxLoc(M3, &val1, &val2, idx1, idx2);
930         string s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
931         if( val1 != min_val || val2 != max_val || s1 != min_sidx || s2 != max_sidx )
932         {
933             errcount++;
934             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"
935                        "(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
936                        min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
937             break;
938         }
939 
940         cv::minMaxIdx(Md, &val1, &val2, idx1, idx2);
941         s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
942         if( (min_val < 0 && (val1 != min_val || s1 != min_sidx)) ||
943            (max_val > 0 && (val2 != max_val || s2 != max_sidx)) )
944         {
945             errcount++;
946             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"
947                        "(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
948                        min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
949             break;
950         }
951     }
952 
953     ts->set_failed_test_info(errcount == 0 ? cvtest::TS::OK : cvtest::TS::FAIL_INVALID_OUTPUT);
954 }
955 
956 
957 template <class T>
calcDiffElemCountImpl(const vector<Mat> & mv,const Mat & m)958 int calcDiffElemCountImpl(const vector<Mat>& mv, const Mat& m)
959 {
960     int diffElemCount = 0;
961     const int mChannels = m.channels();
962     for(int y = 0; y < m.rows; y++)
963     {
964         for(int x = 0; x < m.cols; x++)
965         {
966             const T* mElem = &m.at<T>(y, x*mChannels);
967             size_t loc = 0;
968             for(size_t i = 0; i < mv.size(); i++)
969             {
970                 const size_t mvChannel = mv[i].channels();
971                 const T* mvElem = &mv[i].at<T>(y, x*(int)mvChannel);
972                 for(size_t li = 0; li < mvChannel; li++)
973                     if(mElem[loc + li] != mvElem[li])
974                         diffElemCount++;
975                 loc += mvChannel;
976             }
977             CV_Assert(loc == (size_t)mChannels);
978         }
979     }
980     return diffElemCount;
981 }
982 
983 static
calcDiffElemCount(const vector<Mat> & mv,const Mat & m)984 int calcDiffElemCount(const vector<Mat>& mv, const Mat& m)
985 {
986     int depth = m.depth();
987     switch (depth)
988     {
989     case CV_8U:
990         return calcDiffElemCountImpl<uchar>(mv, m);
991     case CV_8S:
992         return calcDiffElemCountImpl<char>(mv, m);
993     case CV_16U:
994         return calcDiffElemCountImpl<unsigned short>(mv, m);
995     case CV_16S:
996         return calcDiffElemCountImpl<short int>(mv, m);
997     case CV_32S:
998         return calcDiffElemCountImpl<int>(mv, m);
999     case CV_32F:
1000         return calcDiffElemCountImpl<float>(mv, m);
1001     case CV_64F:
1002         return calcDiffElemCountImpl<double>(mv, m);
1003     }
1004 
1005     return INT_MAX;
1006 }
1007 
1008 class Core_MergeSplitBaseTest : public cvtest::BaseTest
1009 {
1010 protected:
1011     virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng) = 0;
1012 
run(int)1013     virtual void run(int)
1014     {
1015         // m is Mat
1016         // mv is vector<Mat>
1017         const int minMSize = 1;
1018         const int maxMSize = 100;
1019         const size_t maxMvSize = 10;
1020 
1021         RNG& rng = theRNG();
1022         Size mSize(rng.uniform(minMSize, maxMSize), rng.uniform(minMSize, maxMSize));
1023         size_t mvSize = rng.uniform(1, maxMvSize);
1024 
1025         int res = cvtest::TS::OK;
1026         int curRes = run_case(CV_8U, mvSize, mSize, rng);
1027         res = curRes != cvtest::TS::OK ? curRes : res;
1028 
1029         curRes = run_case(CV_8S, mvSize, mSize, rng);
1030         res = curRes != cvtest::TS::OK ? curRes : res;
1031 
1032         curRes = run_case(CV_16U, mvSize, mSize, rng);
1033         res = curRes != cvtest::TS::OK ? curRes : res;
1034 
1035         curRes = run_case(CV_16S, mvSize, mSize, rng);
1036         res = curRes != cvtest::TS::OK ? curRes : res;
1037 
1038         curRes = run_case(CV_32S, mvSize, mSize, rng);
1039         res = curRes != cvtest::TS::OK ? curRes : res;
1040 
1041         curRes = run_case(CV_32F, mvSize, mSize, rng);
1042         res = curRes != cvtest::TS::OK ? curRes : res;
1043 
1044         curRes = run_case(CV_64F, mvSize, mSize, rng);
1045         res = curRes != cvtest::TS::OK ? curRes : res;
1046 
1047         ts->set_failed_test_info(res);
1048     }
1049 };
1050 
1051 class Core_MergeTest : public Core_MergeSplitBaseTest
1052 {
1053 public:
Core_MergeTest()1054     Core_MergeTest() {}
~Core_MergeTest()1055     ~Core_MergeTest() {}
1056 
1057 protected:
run_case(int depth,size_t matCount,const Size & size,RNG & rng)1058     virtual int run_case(int depth, size_t matCount, const Size& size, RNG& rng)
1059     {
1060         const int maxMatChannels = 10;
1061 
1062         vector<Mat> src(matCount);
1063         int channels = 0;
1064         for(size_t i = 0; i < src.size(); i++)
1065         {
1066             Mat m(size, CV_MAKETYPE(depth, rng.uniform(1,maxMatChannels)));
1067             rng.fill(m, RNG::UNIFORM, 0, 100, true);
1068             channels += m.channels();
1069             src[i] = m;
1070         }
1071 
1072         Mat dst;
1073         merge(src, dst);
1074 
1075         // check result
1076         std::stringstream commonLog;
1077         commonLog << "Depth " << depth << " :";
1078         if(dst.depth() != depth)
1079         {
1080             ts->printf(cvtest::TS::LOG, "%s incorrect depth of dst (%d instead of %d)\n",
1081                        commonLog.str().c_str(), dst.depth(), depth);
1082             return cvtest::TS::FAIL_INVALID_OUTPUT;
1083         }
1084         if(dst.size() != size)
1085         {
1086             ts->printf(cvtest::TS::LOG, "%s incorrect size of dst (%d x %d instead of %d x %d)\n",
1087                        commonLog.str().c_str(), dst.rows, dst.cols, size.height, size.width);
1088             return cvtest::TS::FAIL_INVALID_OUTPUT;
1089         }
1090         if(dst.channels() != channels)
1091         {
1092             ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst (%d instead of %d)\n",
1093                        commonLog.str().c_str(), dst.channels(), channels);
1094             return cvtest::TS::FAIL_INVALID_OUTPUT;
1095         }
1096 
1097         int diffElemCount = calcDiffElemCount(src, dst);
1098         if(diffElemCount > 0)
1099         {
1100             ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n",
1101                        commonLog.str().c_str(), static_cast<float>(diffElemCount)/(channels*size.area()));
1102             return cvtest::TS::FAIL_INVALID_OUTPUT;
1103         }
1104 
1105         return cvtest::TS::OK;
1106     }
1107 };
1108 
1109 class Core_SplitTest : public Core_MergeSplitBaseTest
1110 {
1111 public:
Core_SplitTest()1112     Core_SplitTest() {}
~Core_SplitTest()1113     ~Core_SplitTest() {}
1114 
1115 protected:
run_case(int depth,size_t channels,const Size & size,RNG & rng)1116     virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng)
1117     {
1118         Mat src(size, CV_MAKETYPE(depth, (int)channels));
1119         rng.fill(src, RNG::UNIFORM, 0, 100, true);
1120 
1121         vector<Mat> dst;
1122         split(src, dst);
1123 
1124         // check result
1125         std::stringstream commonLog;
1126         commonLog << "Depth " << depth << " :";
1127         if(dst.size() != channels)
1128         {
1129             ts->printf(cvtest::TS::LOG, "%s incorrect count of matrices in dst (%d instead of %d)\n",
1130                        commonLog.str().c_str(), dst.size(), channels);
1131             return cvtest::TS::FAIL_INVALID_OUTPUT;
1132         }
1133         for(size_t i = 0; i < dst.size(); i++)
1134         {
1135             if(dst[i].size() != size)
1136             {
1137                 ts->printf(cvtest::TS::LOG, "%s incorrect size of dst[%d] (%d x %d instead of %d x %d)\n",
1138                            commonLog.str().c_str(), i, dst[i].rows, dst[i].cols, size.height, size.width);
1139                 return cvtest::TS::FAIL_INVALID_OUTPUT;
1140             }
1141             if(dst[i].depth() != depth)
1142             {
1143                 ts->printf(cvtest::TS::LOG, "%s: incorrect depth of dst[%d] (%d instead of %d)\n",
1144                            commonLog.str().c_str(), i, dst[i].depth(), depth);
1145                 return cvtest::TS::FAIL_INVALID_OUTPUT;
1146             }
1147             if(dst[i].channels() != 1)
1148             {
1149                 ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst[%d] (%d instead of %d)\n",
1150                            commonLog.str().c_str(), i, dst[i].channels(), 1);
1151                 return cvtest::TS::FAIL_INVALID_OUTPUT;
1152             }
1153         }
1154 
1155         int diffElemCount = calcDiffElemCount(dst, src);
1156         if(diffElemCount > 0)
1157         {
1158             ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n",
1159                        commonLog.str().c_str(), static_cast<float>(diffElemCount)/(channels*size.area()));
1160             return cvtest::TS::FAIL_INVALID_OUTPUT;
1161         }
1162 
1163         return cvtest::TS::OK;
1164     }
1165 };
1166 
TEST(Core_Reduce,accuracy)1167 TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); }
TEST(Core_Array,basic_operations)1168 TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); }
1169 
TEST(Core_Merge,shape_operations)1170 TEST(Core_Merge, shape_operations) { Core_MergeTest test; test.safe_run(); }
TEST(Core_Split,shape_operations)1171 TEST(Core_Split, shape_operations) { Core_SplitTest test; test.safe_run(); }
1172 
1173 
TEST(Core_IOArray,submat_assignment)1174 TEST(Core_IOArray, submat_assignment)
1175 {
1176     Mat1f A = Mat1f::zeros(2,2);
1177     Mat1f B = Mat1f::ones(1,3);
1178 
1179     EXPECT_THROW( B.colRange(0,3).copyTo(A.row(0)), cv::Exception );
1180 
1181     EXPECT_NO_THROW( B.colRange(0,2).copyTo(A.row(0)) );
1182 
1183     EXPECT_EQ( 1.0f, A(0,0) );
1184     EXPECT_EQ( 1.0f, A(0,1) );
1185 }
1186 
OutputArray_create1(OutputArray m)1187 void OutputArray_create1(OutputArray m) { m.create(1, 2, CV_32S); }
OutputArray_create2(OutputArray m)1188 void OutputArray_create2(OutputArray m) { m.create(1, 3, CV_32F); }
1189 
TEST(Core_IOArray,submat_create)1190 TEST(Core_IOArray, submat_create)
1191 {
1192     Mat1f A = Mat1f::zeros(2,2);
1193 
1194     EXPECT_THROW( OutputArray_create1(A.row(0)), cv::Exception );
1195     EXPECT_THROW( OutputArray_create2(A.row(0)), cv::Exception );
1196 }
1197 
TEST(Core_Mat,issue4457_pass_null_ptr)1198 TEST(Core_Mat, issue4457_pass_null_ptr)
1199 {
1200     ASSERT_ANY_THROW(cv::Mat mask(45, 45, CV_32F, 0));
1201 }
1202 
TEST(Core_Mat,reshape_1942)1203 TEST(Core_Mat, reshape_1942)
1204 {
1205     cv::Mat A = (cv::Mat_<float>(2,3) << 3.4884074, 1.4159607, 0.78737736,  2.3456569, -0.88010466, 0.3009364);
1206     int cn = 0;
1207     ASSERT_NO_THROW(
1208         cv::Mat_<float> M = A.reshape(3);
1209         cn = M.channels();
1210     );
1211     ASSERT_EQ(1, cn);
1212 }
1213 
check_ndim_shape(const cv::Mat & mat,int cn,int ndims,const int * sizes)1214 static void check_ndim_shape(const cv::Mat &mat, int cn, int ndims, const int *sizes)
1215 {
1216     EXPECT_EQ(mat.channels(), cn);
1217     EXPECT_EQ(mat.dims, ndims);
1218 
1219     if (mat.dims != ndims)
1220         return;
1221 
1222     for (int i = 0; i < ndims; i++)
1223         EXPECT_EQ(mat.size[i], sizes[i]);
1224 }
1225 
TEST(Core_Mat,reshape_ndims_2)1226 TEST(Core_Mat, reshape_ndims_2)
1227 {
1228     const cv::Mat A(8, 16, CV_8UC3);
1229     cv::Mat B;
1230 
1231     {
1232         int new_sizes_mask[] = { 0, 3, 4, 4 };
1233         int new_sizes_real[] = { 8, 3, 4, 4 };
1234         ASSERT_NO_THROW(B = A.reshape(1, 4, new_sizes_mask));
1235         check_ndim_shape(B, 1, 4, new_sizes_real);
1236     }
1237     {
1238         int new_sizes[] = { 16, 8 };
1239         ASSERT_NO_THROW(B = A.reshape(0, 2, new_sizes));
1240         check_ndim_shape(B, 3, 2, new_sizes);
1241         EXPECT_EQ(B.rows, new_sizes[0]);
1242         EXPECT_EQ(B.cols, new_sizes[1]);
1243     }
1244     {
1245         int new_sizes[] = { 2, 5, 1, 3 };
1246         cv::Mat A_sliced = A(cv::Range::all(), cv::Range(0, 15));
1247         ASSERT_ANY_THROW(A_sliced.reshape(4, 4, new_sizes));
1248     }
1249 }
1250 
TEST(Core_Mat,reshape_ndims_4)1251 TEST(Core_Mat, reshape_ndims_4)
1252 {
1253     const int sizes[] = { 2, 6, 4, 12 };
1254     const cv::Mat A(4, sizes, CV_8UC3);
1255     cv::Mat B;
1256 
1257     {
1258         int new_sizes_mask[] = { 0, 864 };
1259         int new_sizes_real[] = { 2, 864 };
1260         ASSERT_NO_THROW(B = A.reshape(1, 2, new_sizes_mask));
1261         check_ndim_shape(B, 1, 2, new_sizes_real);
1262         EXPECT_EQ(B.rows, new_sizes_real[0]);
1263         EXPECT_EQ(B.cols, new_sizes_real[1]);
1264     }
1265     {
1266         int new_sizes_mask[] = { 4, 0, 0, 2, 3 };
1267         int new_sizes_real[] = { 4, 6, 4, 2, 3 };
1268         ASSERT_NO_THROW(B = A.reshape(0, 5, new_sizes_mask));
1269         check_ndim_shape(B, 3, 5, new_sizes_real);
1270     }
1271     {
1272         int new_sizes_mask[] = { 1, 1 };
1273         ASSERT_ANY_THROW(A.reshape(0, 2, new_sizes_mask));
1274     }
1275     {
1276         int new_sizes_mask[] = { 4, 6, 3, 3, 0 };
1277         ASSERT_ANY_THROW(A.reshape(0, 5, new_sizes_mask));
1278     }
1279 }
1280 
TEST(Core_Mat,push_back)1281 TEST(Core_Mat, push_back)
1282 {
1283     Mat a = (Mat_<float>(1,2) << 3.4884074f, 1.4159607f);
1284     Mat b = (Mat_<float>(1,2) << 0.78737736f, 2.3456569f);
1285 
1286     a.push_back(b);
1287 
1288     ASSERT_EQ(2, a.cols);
1289     ASSERT_EQ(2, a.rows);
1290 
1291     ASSERT_FLOAT_EQ(3.4884074f, a.at<float>(0, 0));
1292     ASSERT_FLOAT_EQ(1.4159607f, a.at<float>(0, 1));
1293     ASSERT_FLOAT_EQ(0.78737736f, a.at<float>(1, 0));
1294     ASSERT_FLOAT_EQ(2.3456569f, a.at<float>(1, 1));
1295 
1296     Mat c = (Mat_<float>(2,2) << -0.88010466f, 0.3009364f, 2.22399974f, -5.45933905f);
1297 
1298     ASSERT_EQ(c.rows, a.cols);
1299 
1300     a.push_back(c.t());
1301 
1302     ASSERT_EQ(2, a.cols);
1303     ASSERT_EQ(4, a.rows);
1304 
1305     ASSERT_FLOAT_EQ(3.4884074f, a.at<float>(0, 0));
1306     ASSERT_FLOAT_EQ(1.4159607f, a.at<float>(0, 1));
1307     ASSERT_FLOAT_EQ(0.78737736f, a.at<float>(1, 0));
1308     ASSERT_FLOAT_EQ(2.3456569f, a.at<float>(1, 1));
1309     ASSERT_FLOAT_EQ(-0.88010466f, a.at<float>(2, 0));
1310     ASSERT_FLOAT_EQ(2.22399974f, a.at<float>(2, 1));
1311     ASSERT_FLOAT_EQ(0.3009364f, a.at<float>(3, 0));
1312     ASSERT_FLOAT_EQ(-5.45933905f, a.at<float>(3, 1));
1313 
1314     a.push_back(Mat::ones(2, 2, CV_32FC1));
1315 
1316     ASSERT_EQ(6, a.rows);
1317 
1318     for(int row=4; row<a.rows; row++) {
1319 
1320         for(int col=0; col<a.cols; col++) {
1321 
1322             ASSERT_FLOAT_EQ(1.f, a.at<float>(row, col));
1323         }
1324     }
1325 }
1326 
TEST(Core_Mat,copyNx1ToVector)1327 TEST(Core_Mat, copyNx1ToVector)
1328 {
1329     cv::Mat_<uchar> src(5, 1);
1330     cv::Mat_<uchar> ref_dst8;
1331     cv::Mat_<ushort> ref_dst16;
1332     std::vector<uchar> dst8;
1333     std::vector<ushort> dst16;
1334 
1335     src << 1, 2, 3, 4, 5;
1336 
1337     src.copyTo(ref_dst8);
1338     src.copyTo(dst8);
1339 
1340     ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst8, cv::Mat_<uchar>(dst8));
1341 
1342     src.convertTo(ref_dst16, CV_16U);
1343     src.convertTo(dst16, CV_16U);
1344 
1345     ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst16, cv::Mat_<ushort>(dst16));
1346 }
1347 
TEST(Core_Matx,fromMat_)1348 TEST(Core_Matx, fromMat_)
1349 {
1350     Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
1351     Matx22d b(a);
1352     ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.);
1353 }
1354 
TEST(Core_Matx,from_initializer_list)1355 TEST(Core_Matx, from_initializer_list)
1356 {
1357     Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
1358     Matx22d b = {10, 11, 12, 13};
1359     ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.);
1360 }
1361 
TEST(Core_Mat,regression_9507)1362 TEST(Core_Mat, regression_9507)
1363 {
1364     cv::Mat m = Mat::zeros(5, 5, CV_8UC3);
1365     cv::Mat m2{m};
1366     EXPECT_EQ(25u, m2.total());
1367 }
1368 
TEST(Core_InputArray,empty)1369 TEST(Core_InputArray, empty)
1370 {
1371     vector<vector<Point> > data;
1372     ASSERT_TRUE( _InputArray(data).empty() );
1373 }
1374 
TEST(Core_CopyMask,bug1918)1375 TEST(Core_CopyMask, bug1918)
1376 {
1377     Mat_<unsigned char> tmpSrc(100,100);
1378     tmpSrc = 124;
1379     Mat_<unsigned char> tmpMask(100,100);
1380     tmpMask = 255;
1381     Mat_<unsigned char> tmpDst(100,100);
1382     tmpDst = 2;
1383     tmpSrc.copyTo(tmpDst,tmpMask);
1384     ASSERT_EQ(sum(tmpDst)[0], 124*100*100);
1385 }
1386 
TEST(Core_SVD,orthogonality)1387 TEST(Core_SVD, orthogonality)
1388 {
1389     for( int i = 0; i < 2; i++ )
1390     {
1391         int type = i == 0 ? CV_32F : CV_64F;
1392         Mat mat_D(2, 2, type);
1393         mat_D.setTo(88.);
1394         Mat mat_U, mat_W;
1395         SVD::compute(mat_D, mat_W, mat_U, noArray(), SVD::FULL_UV);
1396         mat_U *= mat_U.t();
1397         ASSERT_LT(cvtest::norm(mat_U, Mat::eye(2, 2, type), NORM_INF), 1e-5);
1398     }
1399 }
1400 
1401 
TEST(Core_SparseMat,footprint)1402 TEST(Core_SparseMat, footprint)
1403 {
1404     int n = 1000000;
1405     int sz[] = { n, n };
1406     SparseMat m(2, sz, CV_64F);
1407 
1408     int nodeSize0 = (int)m.hdr->nodeSize;
1409     double dataSize0 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6;
1410     printf("before: node size=%d bytes, data size=%.0f Mbytes\n", nodeSize0, dataSize0);
1411 
1412     for (int i = 0; i < n; i++)
1413     {
1414         m.ref<double>(i, i) = 1;
1415     }
1416 
1417     double dataSize1 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6;
1418     double threshold = (n*nodeSize0*1.6 + n*2.*sizeof(size_t))*1e-6;
1419     printf("after: data size=%.0f Mbytes, threshold=%.0f MBytes\n", dataSize1, threshold);
1420 
1421     ASSERT_LE((int)m.hdr->nodeSize, 32);
1422     ASSERT_LE(dataSize1, threshold);
1423 }
1424 
1425 
1426 // Can't fix without dirty hacks or broken user code (PR #4159)
TEST(Core_Mat_vector,DISABLED_OutputArray_create_getMat)1427 TEST(Core_Mat_vector, DISABLED_OutputArray_create_getMat)
1428 {
1429     cv::Mat_<uchar> src_base(5, 1);
1430     std::vector<uchar> dst8;
1431 
1432     src_base << 1, 2, 3, 4, 5;
1433 
1434     Mat src(src_base);
1435     OutputArray _dst(dst8);
1436     {
1437         _dst.create(src.rows, src.cols, src.type());
1438         Mat dst = _dst.getMat();
1439         EXPECT_EQ(src.dims, dst.dims);
1440         EXPECT_EQ(src.cols, dst.cols);
1441         EXPECT_EQ(src.rows, dst.rows);
1442     }
1443 }
1444 
TEST(Core_Mat_vector,copyTo_roi_column)1445 TEST(Core_Mat_vector, copyTo_roi_column)
1446 {
1447     cv::Mat_<uchar> src_base(5, 2);
1448     std::vector<uchar> dst1;
1449 
1450     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1451 
1452     Mat src_full(src_base);
1453     Mat src(src_full.col(0));
1454 #if 0 // Can't fix without dirty hacks or broken user code (PR #4159)
1455     OutputArray _dst(dst1);
1456     {
1457         _dst.create(src.rows, src.cols, src.type());
1458         Mat dst = _dst.getMat();
1459         EXPECT_EQ(src.dims, dst.dims);
1460         EXPECT_EQ(src.cols, dst.cols);
1461         EXPECT_EQ(src.rows, dst.rows);
1462     }
1463 #endif
1464 
1465     std::vector<uchar> dst2;
1466     src.copyTo(dst2);
1467     std::cout << "src = " << src << std::endl;
1468     std::cout << "dst = " << Mat(dst2) << std::endl;
1469     EXPECT_EQ((size_t)5, dst2.size());
1470     EXPECT_EQ(1, (int)dst2[0]);
1471     EXPECT_EQ(3, (int)dst2[1]);
1472     EXPECT_EQ(5, (int)dst2[2]);
1473     EXPECT_EQ(7, (int)dst2[3]);
1474     EXPECT_EQ(9, (int)dst2[4]);
1475 }
1476 
TEST(Core_Mat_vector,copyTo_roi_row)1477 TEST(Core_Mat_vector, copyTo_roi_row)
1478 {
1479     cv::Mat_<uchar> src_base(2, 5);
1480     std::vector<uchar> dst1;
1481 
1482     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1483 
1484     Mat src_full(src_base);
1485     Mat src(src_full.row(0));
1486     OutputArray _dst(dst1);
1487     {
1488         _dst.create(src.rows, src.cols, src.type());
1489         Mat dst = _dst.getMat();
1490         EXPECT_EQ(src.dims, dst.dims);
1491         EXPECT_EQ(src.cols, dst.cols);
1492         EXPECT_EQ(src.rows, dst.rows);
1493     }
1494 
1495     std::vector<uchar> dst2;
1496     src.copyTo(dst2);
1497     std::cout << "src = " << src << std::endl;
1498     std::cout << "dst = " << Mat(dst2) << std::endl;
1499     EXPECT_EQ((size_t)5, dst2.size());
1500     EXPECT_EQ(1, (int)dst2[0]);
1501     EXPECT_EQ(2, (int)dst2[1]);
1502     EXPECT_EQ(3, (int)dst2[2]);
1503     EXPECT_EQ(4, (int)dst2[3]);
1504     EXPECT_EQ(5, (int)dst2[4]);
1505 }
1506 
TEST(Mat,regression_5991)1507 TEST(Mat, regression_5991)
1508 {
1509     int sz[] = {2,3,2};
1510     Mat mat(3, sz, CV_32F, Scalar(1));
1511     ASSERT_NO_THROW(mat.convertTo(mat, CV_8U));
1512     EXPECT_EQ(sz[0], mat.size[0]);
1513     EXPECT_EQ(sz[1], mat.size[1]);
1514     EXPECT_EQ(sz[2], mat.size[2]);
1515     EXPECT_EQ(0, cvtest::norm(mat, Mat(3, sz, CV_8U, Scalar(1)), NORM_INF));
1516 }
1517 
TEST(Mat,regression_9720)1518 TEST(Mat, regression_9720)
1519 {
1520     Mat mat(1, 1, CV_32FC1);
1521     mat.at<float>(0) = 1.f;
1522     const float a = 0.1f;
1523     Mat me1 = (Mat)(mat.mul((a / mat)));
1524     Mat me2 = (Mat)(mat.mul((Mat)(a / mat)));
1525     Mat me3 = (Mat)(mat.mul((a * mat)));
1526     Mat me4 = (Mat)(mat.mul((Mat)(a * mat)));
1527     EXPECT_EQ(me1.at<float>(0), me2.at<float>(0));
1528     EXPECT_EQ(me3.at<float>(0), me4.at<float>(0));
1529 }
1530 
1531 #ifdef OPENCV_TEST_BIGDATA
TEST(Mat,regression_6696_BigData_8Gb)1532 TEST(Mat, regression_6696_BigData_8Gb)
1533 {
1534     int width = 60000;
1535     int height = 10000;
1536 
1537     Mat destImageBGR = Mat(height, width, CV_8UC3, Scalar(1, 2, 3, 0));
1538     Mat destImageA = Mat(height, width, CV_8UC1, Scalar::all(4));
1539 
1540     vector<Mat> planes;
1541     split(destImageBGR, planes);
1542     planes.push_back(destImageA);
1543     merge(planes, destImageBGR);
1544 
1545     EXPECT_EQ(1, destImageBGR.at<Vec4b>(0)[0]);
1546     EXPECT_EQ(2, destImageBGR.at<Vec4b>(0)[1]);
1547     EXPECT_EQ(3, destImageBGR.at<Vec4b>(0)[2]);
1548     EXPECT_EQ(4, destImageBGR.at<Vec4b>(0)[3]);
1549 
1550     EXPECT_EQ(1, destImageBGR.at<Vec4b>(height-1, width-1)[0]);
1551     EXPECT_EQ(2, destImageBGR.at<Vec4b>(height-1, width-1)[1]);
1552     EXPECT_EQ(3, destImageBGR.at<Vec4b>(height-1, width-1)[2]);
1553     EXPECT_EQ(4, destImageBGR.at<Vec4b>(height-1, width-1)[3]);
1554 }
1555 #endif
1556 
TEST(Reduce,regression_should_fail_bug_4594)1557 TEST(Reduce, regression_should_fail_bug_4594)
1558 {
1559     cv::Mat src = cv::Mat::eye(4, 4, CV_8U);
1560     std::vector<int> dst;
1561 
1562     EXPECT_THROW(cv::reduce(src, dst, 0, CV_REDUCE_MIN, CV_32S), cv::Exception);
1563     EXPECT_THROW(cv::reduce(src, dst, 0, CV_REDUCE_MAX, CV_32S), cv::Exception);
1564     EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_SUM, CV_32S));
1565     EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_AVG, CV_32S));
1566 }
1567 
TEST(Mat,push_back_vector)1568 TEST(Mat, push_back_vector)
1569 {
1570     cv::Mat result(1, 5, CV_32FC1);
1571 
1572     std::vector<float> vec1(result.cols + 1);
1573     std::vector<int> vec2(result.cols);
1574 
1575     EXPECT_THROW(result.push_back(vec1), cv::Exception);
1576     EXPECT_THROW(result.push_back(vec2), cv::Exception);
1577 
1578     vec1.resize(result.cols);
1579 
1580     for (int i = 0; i < 5; ++i)
1581         result.push_back(cv::Mat(vec1).reshape(1, 1));
1582 
1583     ASSERT_EQ(6, result.rows);
1584 }
1585 
TEST(Mat,regression_5917_clone_empty)1586 TEST(Mat, regression_5917_clone_empty)
1587 {
1588     Mat cloned;
1589     Mat_<Point2f> source(5, 0);
1590 
1591     ASSERT_NO_THROW(cloned = source.clone());
1592 }
1593 
TEST(Mat,regression_7873_mat_vector_initialize)1594 TEST(Mat, regression_7873_mat_vector_initialize)
1595 {
1596     std::vector<int> dims;
1597     dims.push_back(12);
1598     dims.push_back(3);
1599     dims.push_back(2);
1600     Mat multi_mat(dims, CV_32FC1, cv::Scalar(0));
1601 
1602     ASSERT_EQ(3, multi_mat.dims);
1603     ASSERT_EQ(12, multi_mat.size[0]);
1604     ASSERT_EQ(3, multi_mat.size[1]);
1605     ASSERT_EQ(2, multi_mat.size[2]);
1606 
1607     std::vector<Range> ranges;
1608     ranges.push_back(Range(1, 2));
1609     ranges.push_back(Range::all());
1610     ranges.push_back(Range::all());
1611     Mat sub_mat = multi_mat(ranges);
1612 
1613     ASSERT_EQ(3, sub_mat.dims);
1614     ASSERT_EQ(1, sub_mat.size[0]);
1615     ASSERT_EQ(3, sub_mat.size[1]);
1616     ASSERT_EQ(2, sub_mat.size[2]);
1617 }
1618 
TEST(Mat,regression_10507_mat_setTo)1619 TEST(Mat, regression_10507_mat_setTo)
1620 {
1621     Size sz(6, 4);
1622     Mat test_mask(sz, CV_8UC1, cv::Scalar::all(255));
1623     test_mask.at<uchar>(1,0) = 0;
1624     test_mask.at<uchar>(0,1) = 0;
1625     for (int cn = 1; cn <= 4; cn++)
1626     {
1627         cv::Mat A(sz, CV_MAKE_TYPE(CV_32F, cn), cv::Scalar::all(5));
1628         A.setTo(cv::Scalar::all(std::numeric_limits<float>::quiet_NaN()), test_mask);
1629         int nans = 0;
1630         for (int y = 0; y < A.rows; y++)
1631         {
1632             for (int x = 0; x < A.cols; x++)
1633             {
1634                 for (int c = 0; c < cn; c++)
1635                 {
1636                     float v = A.ptr<float>(y, x)[c];
1637                     nans += (v == v) ? 0 : 1;
1638                 }
1639             }
1640         }
1641         EXPECT_EQ(nans, cn * (sz.area() - 2)) << "A=" << A << std::endl << "mask=" << test_mask << std::endl;
1642     }
1643 }
1644 
TEST(Core_Mat_array,outputArray_create_getMat)1645 TEST(Core_Mat_array, outputArray_create_getMat)
1646 {
1647     cv::Mat_<uchar> src_base(5, 1);
1648     std::array<uchar, 5> dst8;
1649 
1650     src_base << 1, 2, 3, 4, 5;
1651 
1652     Mat src(src_base);
1653     OutputArray _dst(dst8);
1654 
1655     {
1656         _dst.create(src.rows, src.cols, src.type());
1657         Mat dst = _dst.getMat();
1658         EXPECT_EQ(src.dims, dst.dims);
1659         EXPECT_EQ(src.cols, dst.cols);
1660         EXPECT_EQ(src.rows, dst.rows);
1661     }
1662 }
1663 
TEST(Core_Mat_array,copyTo_roi_column)1664 TEST(Core_Mat_array, copyTo_roi_column)
1665 {
1666     cv::Mat_<uchar> src_base(5, 2);
1667 
1668     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1669 
1670     Mat src_full(src_base);
1671     Mat src(src_full.col(0));
1672 
1673     std::array<uchar, 5> dst1;
1674     src.copyTo(dst1);
1675     std::cout << "src = " << src << std::endl;
1676     std::cout << "dst = " << Mat(dst1) << std::endl;
1677     EXPECT_EQ((size_t)5, dst1.size());
1678     EXPECT_EQ(1, (int)dst1[0]);
1679     EXPECT_EQ(3, (int)dst1[1]);
1680     EXPECT_EQ(5, (int)dst1[2]);
1681     EXPECT_EQ(7, (int)dst1[3]);
1682     EXPECT_EQ(9, (int)dst1[4]);
1683 }
1684 
TEST(Core_Mat_array,copyTo_roi_row)1685 TEST(Core_Mat_array, copyTo_roi_row)
1686 {
1687     cv::Mat_<uchar> src_base(2, 5);
1688     std::array<uchar, 5> dst1;
1689 
1690     src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1691 
1692     Mat src_full(src_base);
1693     Mat src(src_full.row(0));
1694     OutputArray _dst(dst1);
1695     {
1696         _dst.create(5, 1, src.type());
1697         Mat dst = _dst.getMat();
1698         EXPECT_EQ(src.dims, dst.dims);
1699         EXPECT_EQ(1, dst.cols);
1700         EXPECT_EQ(5, dst.rows);
1701     }
1702 
1703     std::array<uchar, 5> dst2;
1704     src.copyTo(dst2);
1705     std::cout << "src = " << src << std::endl;
1706     std::cout << "dst = " << Mat(dst2) << std::endl;
1707     EXPECT_EQ(1, (int)dst2[0]);
1708     EXPECT_EQ(2, (int)dst2[1]);
1709     EXPECT_EQ(3, (int)dst2[2]);
1710     EXPECT_EQ(4, (int)dst2[3]);
1711     EXPECT_EQ(5, (int)dst2[4]);
1712 }
1713 
TEST(Core_Mat_array,SplitMerge)1714 TEST(Core_Mat_array, SplitMerge)
1715 {
1716     std::array<cv::Mat, 3> src;
1717     for (size_t i = 0; i < src.size(); ++i)
1718     {
1719         src[i] = Mat(10, 10, CV_8U, Scalar((double)(16 * (i + 1))));
1720     }
1721 
1722     Mat merged;
1723     merge(src, merged);
1724 
1725     std::array<cv::Mat, 3> dst;
1726     split(merged, dst);
1727 
1728     for (size_t i = 0; i < dst.size(); ++i)
1729     {
1730         EXPECT_EQ(0, cvtest::norm(src[i], dst[i], NORM_INF));
1731     }
1732 }
1733 
TEST(Mat,regression_8680)1734 TEST(Mat, regression_8680)
1735 {
1736    Mat_<Point2i> mat(3,1);
1737    ASSERT_EQ(mat.channels(), 2);
1738    mat.release();
1739    ASSERT_EQ(mat.channels(), 2);
1740 }
1741 
TEST(Mat_,range_based_for)1742 TEST(Mat_, range_based_for)
1743 {
1744     Mat_<uchar> img = Mat_<uchar>::zeros(3, 3);
1745 
1746     for(auto& pixel : img)
1747     {
1748         pixel = 1;
1749     }
1750 
1751     Mat_<uchar> ref(3, 3);
1752     ref.setTo(Scalar(1));
1753     ASSERT_DOUBLE_EQ(cvtest::norm(img, ref, NORM_INF), 0.);
1754 }
1755 
TEST(Mat,from_initializer_list)1756 TEST(Mat, from_initializer_list)
1757 {
1758     Mat A({1.f, 2.f, 3.f});
1759     Mat_<float> B(3, 1); B << 1, 2, 3;
1760     Mat_<float> C({3}, {1,2,3});
1761 
1762     ASSERT_EQ(A.type(), CV_32F);
1763     ASSERT_DOUBLE_EQ(cvtest::norm(A, B, NORM_INF), 0.);
1764     ASSERT_DOUBLE_EQ(cvtest::norm(A, C, NORM_INF), 0.);
1765     ASSERT_DOUBLE_EQ(cvtest::norm(B, C, NORM_INF), 0.);
1766 
1767     auto D = Mat_<double>({2, 3}, {1, 2, 3, 4, 5, 6});
1768     EXPECT_EQ(2, D.rows);
1769     EXPECT_EQ(3, D.cols);
1770 }
1771 
TEST(Mat_,from_initializer_list)1772 TEST(Mat_, from_initializer_list)
1773 {
1774     Mat_<float> A = {1, 2, 3};
1775     Mat_<float> B(3, 1); B << 1, 2, 3;
1776     Mat_<float> C({3}, {1,2,3});
1777 
1778     ASSERT_DOUBLE_EQ(cvtest::norm(A, B, NORM_INF), 0.);
1779     ASSERT_DOUBLE_EQ(cvtest::norm(A, C, NORM_INF), 0.);
1780     ASSERT_DOUBLE_EQ(cvtest::norm(B, C, NORM_INF), 0.);
1781 }
1782 
1783 
TEST(Mat,template_based_ptr)1784 TEST(Mat, template_based_ptr)
1785 {
1786     Mat mat = (Mat_<float>(2, 2) << 11.0f, 22.0f, 33.0f, 44.0f);
1787     int idx[2] = {1, 0};
1788     ASSERT_FLOAT_EQ(33.0f, *(mat.ptr<float>(idx)));
1789     idx[0] = 1;
1790     idx[1] = 1;
1791     ASSERT_FLOAT_EQ(44.0f, *(mat.ptr<float>(idx)));
1792 }
1793 
TEST(Mat_,template_based_ptr)1794 TEST(Mat_, template_based_ptr)
1795 {
1796     int dim[4] = {2, 2, 1, 2};
1797     Mat_<float> mat = (Mat_<float>(4, dim) << 11.0f, 22.0f, 33.0f, 44.0f,
1798                                               55.0f, 66.0f, 77.0f, 88.0f);
1799     int idx[4] = {1, 0, 0, 1};
1800     ASSERT_FLOAT_EQ(66.0f, *(mat.ptr<float>(idx)));
1801 }
1802 
1803 
BIGDATA_TEST(Mat,push_back_regression_4158)1804 BIGDATA_TEST(Mat, push_back_regression_4158)  // memory usage: ~10.6 Gb
1805 {
1806     Mat result;
1807 
1808     Mat tail(100, 500000, CV_32FC2, Scalar(1, 2));
1809 
1810     tail.copyTo(result);
1811     for (int i = 1; i < 15; i++)
1812     {
1813         result.push_back(tail);
1814         std::cout << "i = " << i << "  result = " << result.size() << "   used = " << (uint64)result.total()*result.elemSize()*(1.0 / (1 << 20)) << " Mb"
1815             << "   allocated=" << (uint64)(result.datalimit - result.datastart)*(1.0 / (1 << 20)) << " Mb" << std::endl;
1816     }
1817     for (int i = 0; i < 15; i++)
1818     {
1819         Rect roi(0, tail.rows * i, tail.cols, tail.rows);
1820         int nz = countNonZero(result(roi).reshape(1) == 2);
1821         EXPECT_EQ(tail.total(), (size_t)nz) << "i=" << i;
1822     }
1823 }
1824 
1825 
TEST(Core_Merge,hang_12171)1826 TEST(Core_Merge, hang_12171)
1827 {
1828     Mat src1(4, 24, CV_8UC1, Scalar::all(1));
1829     Mat src2(4, 24, CV_8UC1, Scalar::all(2));
1830     Rect src_roi(0, 0, 23, 4);
1831     Mat src_channels[2] = { src1(src_roi), src2(src_roi) };
1832     Mat dst(4, 24, CV_8UC2, Scalar::all(5));
1833     Rect dst_roi(1, 0, 23, 4);
1834     cv::merge(src_channels, 2, dst(dst_roi));
1835     EXPECT_EQ(5, dst.ptr<uchar>()[0]);
1836     EXPECT_EQ(5, dst.ptr<uchar>()[1]);
1837     EXPECT_EQ(1, dst.ptr<uchar>()[2]);
1838     EXPECT_EQ(2, dst.ptr<uchar>()[3]);
1839     EXPECT_EQ(5, dst.ptr<uchar>(1)[0]);
1840     EXPECT_EQ(5, dst.ptr<uchar>(1)[1]);
1841     EXPECT_EQ(1, dst.ptr<uchar>(1)[2]);
1842     EXPECT_EQ(2, dst.ptr<uchar>(1)[3]);
1843 }
1844 
TEST(Core_Split,hang_12171)1845 TEST(Core_Split, hang_12171)
1846 {
1847     Mat src(4, 24, CV_8UC2, Scalar(1,2,3,4));
1848     Rect src_roi(0, 0, 23, 4);
1849     Mat dst1(4, 24, CV_8UC1, Scalar::all(5));
1850     Mat dst2(4, 24, CV_8UC1, Scalar::all(10));
1851     Rect dst_roi(0, 0, 23, 4);
1852     Mat dst[2] = { dst1(dst_roi), dst2(dst_roi) };
1853     cv::split(src(src_roi), dst);
1854     EXPECT_EQ(1, dst1.ptr<uchar>()[0]);
1855     EXPECT_EQ(1, dst1.ptr<uchar>()[1]);
1856     EXPECT_EQ(2, dst2.ptr<uchar>()[0]);
1857     EXPECT_EQ(2, dst2.ptr<uchar>()[1]);
1858     EXPECT_EQ(1, dst1.ptr<uchar>(1)[0]);
1859     EXPECT_EQ(1, dst1.ptr<uchar>(1)[1]);
1860     EXPECT_EQ(2, dst2.ptr<uchar>(1)[0]);
1861     EXPECT_EQ(2, dst2.ptr<uchar>(1)[1]);
1862 }
1863 
TEST(Core_Split,crash_12171)1864 TEST(Core_Split, crash_12171)
1865 {
1866     Mat src(4, 40, CV_8UC2, Scalar(1,2,3,4));
1867     Rect src_roi(0, 0, 39, 4);
1868     Mat dst1(4, 40, CV_8UC1, Scalar::all(5));
1869     Mat dst2(4, 40, CV_8UC1, Scalar::all(10));
1870     Rect dst_roi(0, 0, 39, 4);
1871     Mat dst[2] = { dst1(dst_roi), dst2(dst_roi) };
1872     cv::split(src(src_roi), dst);
1873     EXPECT_EQ(1, dst1.ptr<uchar>()[0]);
1874     EXPECT_EQ(1, dst1.ptr<uchar>()[1]);
1875     EXPECT_EQ(2, dst2.ptr<uchar>()[0]);
1876     EXPECT_EQ(2, dst2.ptr<uchar>()[1]);
1877     EXPECT_EQ(1, dst1.ptr<uchar>(1)[0]);
1878     EXPECT_EQ(1, dst1.ptr<uchar>(1)[1]);
1879     EXPECT_EQ(2, dst2.ptr<uchar>(1)[0]);
1880     EXPECT_EQ(2, dst2.ptr<uchar>(1)[1]);
1881 }
1882 
TEST(Core_Merge,bug_13544)1883 TEST(Core_Merge, bug_13544)
1884 {
1885     Mat src1(2, 2, CV_8UC3, Scalar::all(1));
1886     Mat src2(2, 2, CV_8UC3, Scalar::all(2));
1887     Mat src3(2, 2, CV_8UC3, Scalar::all(3));
1888     Mat src_arr[] = { src1, src2, src3 };
1889     Mat dst;
1890     merge(src_arr, 3, dst);
1891     ASSERT_EQ(9, dst.channels());  // Avoid memory access out of buffer
1892     EXPECT_EQ(3, (int)dst.ptr<uchar>(0)[6]);
1893     EXPECT_EQ(3, (int)dst.ptr<uchar>(0)[7]);
1894     EXPECT_EQ(3, (int)dst.ptr<uchar>(0)[8]);
1895     EXPECT_EQ(1, (int)dst.ptr<uchar>(1)[0]);
1896     EXPECT_EQ(1, (int)dst.ptr<uchar>(1)[1]);
1897     EXPECT_EQ(1, (int)dst.ptr<uchar>(1)[2]);
1898     EXPECT_EQ(2, (int)dst.ptr<uchar>(1)[3]);
1899     EXPECT_EQ(2, (int)dst.ptr<uchar>(1)[4]);
1900     EXPECT_EQ(2, (int)dst.ptr<uchar>(1)[5]);
1901     EXPECT_EQ(3, (int)dst.ptr<uchar>(1)[6]);
1902     EXPECT_EQ(3, (int)dst.ptr<uchar>(1)[7]);
1903     EXPECT_EQ(3, (int)dst.ptr<uchar>(1)[8]);
1904 }
1905 
1906 struct CustomType  // like cv::Keypoint
1907 {
1908     Point2f pt;
1909     float size;
1910     float angle;
1911     float response;
1912     int octave;
1913     int class_id;
1914 };
1915 
test_CustomType(InputArray src_,OutputArray dst_)1916 static void test_CustomType(InputArray src_, OutputArray dst_)
1917 {
1918     Mat src = src_.getMat();
1919     ASSERT_EQ(sizeof(CustomType), src.elemSize());
1920     CV_CheckTypeEQ(src.type(), CV_MAKETYPE(CV_8U, sizeof(CustomType)), "");
1921 
1922     CustomType* kpt = NULL;
1923     {
1924         Mat dst = dst_.getMat();
1925         for (size_t i = 0; i < dst.total(); i++)
1926         {
1927             kpt = dst.ptr<CustomType>(0) + i;
1928             kpt->octave = (int)i;
1929         }
1930     }
1931     const int N = (int)src.total();
1932     dst_.create(1, N * 2, rawType<CustomType>());
1933     Mat dst = dst_.getMat();
1934     for (size_t i = N; i < dst.total(); i++)
1935     {
1936         kpt = dst.ptr<CustomType>(0) + i;
1937         kpt->octave = -(int)i;
1938     }
1939 #if 0 // Compilation error
1940     CustomType& kpt = dst.at<CustomType>(0, 5);
1941 #endif
1942 }
1943 
TEST(Core_InputArray,support_CustomType)1944 TEST(Core_InputArray, support_CustomType)
1945 {
1946     std::vector<CustomType> kp1(5);
1947     std::vector<CustomType> kp2(3);
1948     test_CustomType(rawIn(kp1), rawOut(kp2));
1949     ASSERT_EQ((size_t)10, kp2.size());
1950     for (int i = 0; i < 3; i++)
1951     {
1952         EXPECT_EQ(i, kp2[i].octave);
1953     }
1954     for (int i = 3; i < 5; i++)
1955     {
1956         EXPECT_EQ(0, kp2[i].octave);
1957     }
1958     for (int i = 5; i < 10; i++)
1959     {
1960         EXPECT_EQ(-i, kp2[i].octave);
1961     }
1962 }
1963 
1964 
TEST(Core_InputArray,fetch_MatExpr)1965 TEST(Core_InputArray, fetch_MatExpr)
1966 {
1967     Mat a(Size(10, 5), CV_32FC1, 5);
1968     Mat b(Size(10, 5), CV_32FC1, 2);
1969     MatExpr expr = a * b.t();                    // gemm expression
1970     Mat dst;
1971     cv::add(expr, Scalar(1), dst);               // invoke gemm() here
1972     void* expr_data = expr.a.data;
1973     Mat result = expr;                           // should not call gemm() here again
1974     EXPECT_EQ(expr_data, result.data);           // expr data is reused
1975     EXPECT_EQ(dst.size(), result.size());
1976 }
1977 
1978 
1979 #ifdef CV_CXX11
1980 class TestInputArrayRangeChecking {
kind2str(cv::_InputArray ia)1981     static const char *kind2str(cv::_InputArray ia)
1982     {
1983         switch (ia.kind())
1984         {
1985         #define C(x) case cv::_InputArray::x: return #x
1986         C(MAT);
1987         C(UMAT);
1988         C(EXPR);
1989         C(MATX);
1990         C(STD_VECTOR);
1991         C(NONE);
1992         C(STD_VECTOR_VECTOR);
1993         C(STD_BOOL_VECTOR);
1994         C(STD_VECTOR_MAT);
1995         C(STD_ARRAY_MAT);
1996         C(STD_VECTOR_UMAT);
1997         C(CUDA_GPU_MAT);
1998         C(STD_VECTOR_CUDA_GPU_MAT);
1999         #undef C
2000         default:
2001             return "<unsupported>";
2002         }
2003     }
2004 
banner(cv::_InputArray ia,const char * label,const char * name)2005     static void banner(cv::_InputArray ia, const char *label, const char *name)
2006     {
2007         std::cout << std::endl
2008                   << label << " = " << name << ", Kind: " << kind2str(ia)
2009                   << std::endl;
2010     }
2011 
2012     template<typename I, typename F>
testA(I ia,F f,const char * mfname)2013     static void testA(I ia, F f, const char *mfname)
2014     {
2015         banner(ia, "f", mfname);
2016         EXPECT_THROW(f(ia, -1), cv::Exception)
2017             << "f(ia, " << -1 << ") should throw cv::Exception";
2018         for (int i = 0; i < int(ia.size()); i++)
2019         {
2020             EXPECT_NO_THROW(f(ia, i))
2021                 << "f(ia, " << i << ") should not throw an exception";
2022         }
2023         EXPECT_THROW(f(ia, int(ia.size())), cv::Exception)
2024             << "f(ia, " << ia.size() << ") should throw cv::Exception";
2025     }
2026 
2027     template<typename I, typename F>
testB(I ia,F f,const char * mfname)2028     static void testB(I ia, F f, const char *mfname)
2029     {
2030         banner(ia, "f", mfname);
2031         EXPECT_THROW(f(ia, -1), cv::Exception)
2032             << "f(ia, " << -1 << ") should throw cv::Exception";
2033         for (int i = 0; i < int(ia.size()); i++)
2034         {
2035             EXPECT_NO_THROW(f(ia, i))
2036                 << "f(ia, " << i << ") should not throw an exception";
2037         }
2038         EXPECT_THROW(f(ia, int(ia.size())), cv::Exception)
2039             << "f(ia, " << ia.size() << ") should throw cv::Exception";
2040     }
2041 
test_isContinuous()2042     static void test_isContinuous()
2043     {
2044         auto f = [](cv::_InputArray ia, int i) { (void)ia.isContinuous(i); };
2045 
2046         cv::Mat M;
2047         cv::UMat uM;
2048 
2049         std::vector<cv::Mat> vec = {M, M};
2050         std::array<cv::Mat, 2> arr = {M, M};
2051         std::vector<cv::UMat> uvec = {uM, uM};
2052 
2053         testA(vec, f, "isContinuous");
2054         testA(arr, f, "isContinuous");
2055         testA(uvec, f, "isContinuous");
2056     }
2057 
test_isSubmatrix()2058     static void test_isSubmatrix()
2059     {
2060         auto f = [](cv::_InputArray ia, int i) { (void)ia.isSubmatrix(i); };
2061 
2062         cv::Mat M;
2063         cv::UMat uM;
2064 
2065         std::vector<cv::Mat> vec = {M, M};
2066         std::array<cv::Mat, 2> arr = {M, M};
2067         std::vector<cv::UMat> uvec = {uM, uM};
2068 
2069         testA(vec, f, "isSubmatrix");
2070         testA(arr, f, "isSubmatrix");
2071         testA(uvec, f, "isSubmatrix");
2072     }
2073 
test_offset()2074     static void test_offset()
2075     {
2076         auto f = [](cv::_InputArray ia, int i) { return ia.offset(i); };
2077 
2078         cv::Mat M;
2079         cv::UMat uM;
2080         cv::cuda::GpuMat gM;
2081 
2082         std::vector<cv::Mat> vec = {M, M};
2083         std::array<cv::Mat, 2> arr = {M, M};
2084         std::vector<cv::UMat> uvec = {uM, uM};
2085         std::vector<cv::cuda::GpuMat> gvec = {gM, gM};
2086 
2087         testB(vec, f, "offset");
2088         testB(arr, f, "offset");
2089         testB(uvec, f, "offset");
2090         testB(gvec, f, "offset");
2091     }
2092 
test_step()2093     static void test_step()
2094     {
2095         auto f = [](cv::_InputArray ia, int i) { return ia.step(i); };
2096 
2097         cv::Mat M;
2098         cv::UMat uM;
2099         cv::cuda::GpuMat gM;
2100 
2101         std::vector<cv::Mat> vec = {M, M};
2102         std::array<cv::Mat, 2> arr = {M, M};
2103         std::vector<cv::UMat> uvec = {uM, uM};
2104         std::vector<cv::cuda::GpuMat> gvec = {gM, gM};
2105 
2106         testB(vec, f, "step");
2107         testB(arr, f, "step");
2108         testB(uvec, f, "step");
2109         testB(gvec, f, "step");
2110     }
2111 
2112 public:
run()2113     static void run()
2114     {
2115         test_isContinuous();
2116         test_isSubmatrix();
2117         test_offset();
2118         test_step();
2119     }
2120 };
2121 
TEST(Core_InputArray,range_checking)2122 TEST(Core_InputArray, range_checking)
2123 {
2124     TestInputArrayRangeChecking::run();
2125 }
2126 #endif
2127 
2128 
TEST(Core_Vectors,issue_13078)2129 TEST(Core_Vectors, issue_13078)
2130 {
2131     float floats_[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2132     std::vector<float> floats(floats_, floats_ + 8);
2133     std::vector<int> ints(4);
2134 
2135     Mat m(4, 1, CV_32FC1, floats.data(), sizeof(floats[0]) * 2);
2136 
2137     m.convertTo(ints, CV_32S);
2138 
2139     ASSERT_EQ(1, ints[0]);
2140     ASSERT_EQ(3, ints[1]);
2141     ASSERT_EQ(5, ints[2]);
2142     ASSERT_EQ(7, ints[3]);
2143 }
2144 
TEST(Core_Vectors,issue_13078_workaround)2145 TEST(Core_Vectors, issue_13078_workaround)
2146 {
2147     float floats_[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2148     std::vector<float> floats(floats_, floats_ + 8);
2149     std::vector<int> ints(4);
2150 
2151     Mat m(4, 1, CV_32FC1, floats.data(), sizeof(floats[0]) * 2);
2152 
2153     m.convertTo(Mat(ints), CV_32S);
2154 
2155     ASSERT_EQ(1, ints[0]);
2156     ASSERT_EQ(3, ints[1]);
2157     ASSERT_EQ(5, ints[2]);
2158     ASSERT_EQ(7, ints[3]);
2159 }
2160 
TEST(Core_MatExpr,issue_13926)2161 TEST(Core_MatExpr, issue_13926)
2162 {
2163     Mat M1 = (Mat_<double>(4,4,CV_64FC1) << 1, 2, 3, 4,
2164                                            5, 6, 7, 8,
2165                                            9, 10, 11, 12,
2166                                            13, 14, 15, 16);
2167 
2168     Matx44d M2(1, 2, 3, 4,
2169                5, 6, 7, 8,
2170                9, 10, 11, 12,
2171                13, 14, 15, 16);
2172 
2173     EXPECT_GE(1e-6, cvtest::norm(M1*M2, M1*M1, NORM_INF)) << Mat(M1*M2) << std::endl << Mat(M1*M1);
2174     EXPECT_GE(1e-6, cvtest::norm(M2*M1, M2*M2, NORM_INF)) << Mat(M2*M1) << std::endl << Mat(M2*M2);
2175 }
2176 
TEST(Core_MatExpr,issue_16655)2177 TEST(Core_MatExpr, issue_16655)
2178 {
2179     Mat a(Size(5, 5), CV_32FC3, Scalar::all(1));
2180     Mat b(Size(5, 5), CV_32FC3, Scalar::all(2));
2181     MatExpr ab_expr = a != b;
2182     Mat ab_mat = ab_expr;
2183     EXPECT_EQ(CV_8UC3, ab_expr.type())
2184         << "MatExpr: CV_8UC3 != " << typeToString(ab_expr.type());
2185     EXPECT_EQ(CV_8UC3, ab_mat.type())
2186         << "Mat: CV_8UC3 != " << typeToString(ab_mat.type());
2187 }
2188 
TEST(Core_MatExpr,issue_16689)2189 TEST(Core_MatExpr, issue_16689)
2190 {
2191     Mat a(Size(10, 5), CV_32FC1, 5);
2192     Mat b(Size(10, 5), CV_32FC1, 2);
2193     Mat bt(Size(5, 10), CV_32FC1, 3);
2194     {
2195         MatExpr r = a * bt;  // gemm
2196         EXPECT_EQ(Mat(r).size(), r.size()) << "[10x5] x [5x10] => [5x5]";
2197     }
2198     {
2199         MatExpr r = a * b.t();  // gemm
2200         EXPECT_EQ(Mat(r).size(), r.size()) << "[10x5] x [10x5].t() => [5x5]";
2201     }
2202     {
2203         MatExpr r = a.t() * b;  // gemm
2204         EXPECT_EQ(Mat(r).size(), r.size()) << "[10x5].t() x [10x5] => [10x10]";
2205     }
2206     {
2207         MatExpr r = a.t() * bt.t();  // gemm
2208         EXPECT_EQ(Mat(r).size(), r.size()) << "[10x5].t() x [5x10].t() => [10x10]";
2209     }
2210 }
2211 
2212 #ifdef HAVE_EIGEN
TEST(Core_Eigen,eigen2cv_check_Mat_type)2213 TEST(Core_Eigen, eigen2cv_check_Mat_type)
2214 {
2215     Mat A(4, 4, CV_32FC1, Scalar::all(0));
2216     Eigen::MatrixXf eigen_A;
2217     cv2eigen(A, eigen_A);
2218 
2219     Mat_<float> f_mat;
2220     EXPECT_NO_THROW(eigen2cv(eigen_A, f_mat));
2221     EXPECT_EQ(CV_32FC1, f_mat.type());
2222 
2223     Mat_<double> d_mat;
2224     EXPECT_ANY_THROW(eigen2cv(eigen_A, d_mat));
2225     //EXPECT_EQ(CV_64FC1, d_mat.type());
2226 }
2227 #endif // HAVE_EIGEN
2228 
2229 #ifdef OPENCV_EIGEN_TENSOR_SUPPORT
TEST(Core_Eigen,cv2eigen_check_tensor_conversion)2230 TEST(Core_Eigen, cv2eigen_check_tensor_conversion)
2231 {
2232     Mat A(2, 3, CV_32FC3);
2233     float value = 0;
2234     for(int row=0; row<A.rows; row++)
2235         for(int col=0; col<A.cols; col++)
2236             for(int ch=0; ch<A.channels(); ch++)
2237                 A.at<Vec3f>(row,col)[ch] = value++;
2238 
2239     Eigen::Tensor<float, 3, Eigen::RowMajor> row_tensor;
2240     cv2eigen(A, row_tensor);
2241 
2242     float* mat_ptr = (float*)A.data;
2243     float* tensor_ptr = row_tensor.data();
2244     for (int i=0; i< row_tensor.size(); i++)
2245         ASSERT_FLOAT_EQ(mat_ptr[i], tensor_ptr[i]);
2246 
2247     Eigen::Tensor<float, 3, Eigen::ColMajor> col_tensor;
2248     cv2eigen(A, col_tensor);
2249     value = 0;
2250     for(int row=0; row<A.rows; row++)
2251         for(int col=0; col<A.cols; col++)
2252             for(int ch=0; ch<A.channels(); ch++)
2253                 ASSERT_FLOAT_EQ(value++, col_tensor(row,col,ch));
2254 }
2255 #endif // OPENCV_EIGEN_TENSOR_SUPPORT
2256 
2257 #ifdef OPENCV_EIGEN_TENSOR_SUPPORT
TEST(Core_Eigen,eigen2cv_check_tensor_conversion)2258 TEST(Core_Eigen, eigen2cv_check_tensor_conversion)
2259 {
2260     Eigen::Tensor<float, 3, Eigen::RowMajor> row_tensor(2,3,3);
2261     Eigen::Tensor<float, 3, Eigen::ColMajor> col_tensor(2,3,3);
2262     float value = 0;
2263     for(int row=0; row<row_tensor.dimension(0); row++)
2264         for(int col=0; col<row_tensor.dimension(1); col++)
2265             for(int ch=0; ch<row_tensor.dimension(2); ch++)
2266             {
2267                 row_tensor(row,col,ch) = value;
2268                 col_tensor(row,col,ch) = value;
2269                 value++;
2270             }
2271 
2272     Mat A;
2273     eigen2cv(row_tensor, A);
2274 
2275     float* tensor_ptr = row_tensor.data();
2276     float* mat_ptr = (float*)A.data;
2277     for (int i=0; i< row_tensor.size(); i++)
2278         ASSERT_FLOAT_EQ(tensor_ptr[i], mat_ptr[i]);
2279 
2280     Mat B;
2281     eigen2cv(col_tensor, B);
2282 
2283     value = 0;
2284     for(int row=0; row<B.rows; row++)
2285         for(int col=0; col<B.cols; col++)
2286             for(int ch=0; ch<B.channels(); ch++)
2287                 ASSERT_FLOAT_EQ(value++, B.at<Vec3f>(row,col)[ch]);
2288 }
2289 #endif // OPENCV_EIGEN_TENSOR_SUPPORT
2290 
2291 #ifdef OPENCV_EIGEN_TENSOR_SUPPORT
TEST(Core_Eigen,cv2eigen_tensormap_check_tensormap_access)2292 TEST(Core_Eigen, cv2eigen_tensormap_check_tensormap_access)
2293 {
2294     float arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
2295     Mat a_mat(2, 2, CV_32FC3, arr);
2296     Eigen::TensorMap<Eigen::Tensor<float, 3, Eigen::RowMajor>> a_tensor = cv2eigen_tensormap<float>(a_mat);
2297 
2298     for(int i=0; i<a_mat.rows; i++) {
2299         for (int j=0; j<a_mat.cols; j++) {
2300             for (int ch=0; ch<a_mat.channels(); ch++) {
2301                 ASSERT_FLOAT_EQ(a_mat.at<Vec3f>(i,j)[ch], a_tensor(i,j,ch));
2302                 ASSERT_EQ(&a_mat.at<Vec3f>(i,j)[ch], &a_tensor(i,j,ch));
2303             }
2304         }
2305     }
2306 }
2307 #endif // OPENCV_EIGEN_TENSOR_SUPPORT
2308 
TEST(Mat,regression_12943)2309 TEST(Mat, regression_12943)  // memory usage: ~4.5 Gb
2310 {
2311     applyTestTag(CV_TEST_TAG_MEMORY_6GB);
2312 
2313     const int width = 0x8000;
2314     const int height = 0x10001;
2315 
2316     cv::Mat src(height, width, CV_8UC1, Scalar::all(128));
2317 
2318     cv::Mat dst;
2319     cv::flip(src, dst, 0);
2320 }
2321 
TEST(Mat,empty_iterator_16855)2322 TEST(Mat, empty_iterator_16855)
2323 {
2324     cv::Mat m;
2325     EXPECT_NO_THROW(m.begin<uchar>());
2326     EXPECT_NO_THROW(m.end<uchar>());
2327     EXPECT_TRUE(m.begin<uchar>() == m.end<uchar>());
2328 }
2329 
2330 
TEST(Mat,regression_18473)2331 TEST(Mat, regression_18473)
2332 {
2333     std::vector<int> sizes(3);
2334     sizes[0] = 20;
2335     sizes[1] = 50;
2336     sizes[2] = 100;
2337 #if 1  // with the fix
2338     std::vector<size_t> steps(2);
2339     steps[0] = 50*100*2;
2340     steps[1] = 100*2;
2341 #else  // without the fix
2342     std::vector<size_t> steps(3);
2343     steps[0] = 50*100*2;
2344     steps[1] = 100*2;
2345     steps[2] = 2;
2346 #endif
2347     std::vector<short> data(20*50*100, 0);  // 1Mb
2348     data[data.size() - 1] = 5;
2349 
2350     // param steps Array of ndims-1 steps
2351     Mat m(sizes, CV_16SC1, (void*)data.data(), (const size_t*)steps.data());
2352 
2353     ASSERT_FALSE(m.empty());
2354     EXPECT_EQ((int)5, (int)m.at<short>(19, 49, 99));
2355 }
2356 
2357 
TEST(Mat,ptrVecni_20044)2358 TEST(Mat, ptrVecni_20044)
2359 {
2360     Mat_<int> m(3,4); m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12;
2361     Vec2i idx(1,1);
2362 
2363     uchar *u = m.ptr(idx);
2364     EXPECT_EQ(int(6), *(int*)(u));
2365     const uchar *cu = m.ptr(idx);
2366     EXPECT_EQ(int(6), *(int*)(cu));
2367 
2368     int *i = m.ptr<int>(idx);
2369     EXPECT_EQ(int(6), *(i));
2370     const int *ci = m.ptr<int>(idx);
2371     EXPECT_EQ(int(6), *(ci));
2372 }
2373 
TEST(Mat,reverse_iterator_19967)2374 TEST(Mat, reverse_iterator_19967)
2375 {
2376     // empty iterator (#16855)
2377     cv::Mat m_empty;
2378     EXPECT_NO_THROW(m_empty.rbegin<uchar>());
2379     EXPECT_NO_THROW(m_empty.rend<uchar>());
2380     EXPECT_TRUE(m_empty.rbegin<uchar>() == m_empty.rend<uchar>());
2381 
2382     // 1D test
2383     std::vector<uchar> data{0, 1, 2, 3};
2384     const std::vector<int> sizes_1d{4};
2385 
2386     //Base class
2387     cv::Mat m_1d(sizes_1d, CV_8U, data.data());
2388     auto mismatch_it_pair_1d = std::mismatch(data.rbegin(), data.rend(), m_1d.rbegin<uchar>());
2389     EXPECT_EQ(mismatch_it_pair_1d.first, data.rend());  // expect no mismatch
2390     EXPECT_EQ(mismatch_it_pair_1d.second, m_1d.rend<uchar>());
2391 
2392     //Templated derived class
2393     cv::Mat_<uchar> m_1d_t(static_cast<int>(sizes_1d.size()), sizes_1d.data(), data.data());
2394     auto mismatch_it_pair_1d_t = std::mismatch(data.rbegin(), data.rend(), m_1d_t.rbegin());
2395     EXPECT_EQ(mismatch_it_pair_1d_t.first, data.rend());  // expect no mismatch
2396     EXPECT_EQ(mismatch_it_pair_1d_t.second, m_1d_t.rend());
2397 
2398 
2399     // 2D test
2400     const std::vector<int> sizes_2d{2, 2};
2401 
2402     //Base class
2403     cv::Mat m_2d(sizes_2d, CV_8U, data.data());
2404     auto mismatch_it_pair_2d = std::mismatch(data.rbegin(), data.rend(), m_2d.rbegin<uchar>());
2405     EXPECT_EQ(mismatch_it_pair_2d.first, data.rend());
2406     EXPECT_EQ(mismatch_it_pair_2d.second, m_2d.rend<uchar>());
2407 
2408     //Templated derived class
2409     cv::Mat_<uchar> m_2d_t(static_cast<int>(sizes_2d.size()),sizes_2d.data(), data.data());
2410     auto mismatch_it_pair_2d_t = std::mismatch(data.rbegin(), data.rend(), m_2d_t.rbegin());
2411     EXPECT_EQ(mismatch_it_pair_2d_t.first, data.rend());
2412     EXPECT_EQ(mismatch_it_pair_2d_t.second, m_2d_t.rend());
2413 
2414     // 3D test
2415     std::vector<uchar> data_3d{0, 1, 2, 3, 4, 5, 6, 7};
2416     const std::vector<int> sizes_3d{2, 2, 2};
2417 
2418     //Base class
2419     cv::Mat m_3d(sizes_3d, CV_8U, data_3d.data());
2420     auto mismatch_it_pair_3d = std::mismatch(data_3d.rbegin(), data_3d.rend(), m_3d.rbegin<uchar>());
2421     EXPECT_EQ(mismatch_it_pair_3d.first, data_3d.rend());
2422     EXPECT_EQ(mismatch_it_pair_3d.second, m_3d.rend<uchar>());
2423 
2424     //Templated derived class
2425     cv::Mat_<uchar> m_3d_t(static_cast<int>(sizes_3d.size()),sizes_3d.data(), data_3d.data());
2426     auto mismatch_it_pair_3d_t = std::mismatch(data_3d.rbegin(), data_3d.rend(), m_3d_t.rbegin());
2427     EXPECT_EQ(mismatch_it_pair_3d_t.first, data_3d.rend());
2428     EXPECT_EQ(mismatch_it_pair_3d_t.second, m_3d_t.rend());
2429 
2430     // const test base class
2431     const cv::Mat m_1d_const(sizes_1d, CV_8U, data.data());
2432 
2433     auto mismatch_it_pair_1d_const = std::mismatch(data.rbegin(), data.rend(), m_1d_const.rbegin<uchar>());
2434     EXPECT_EQ(mismatch_it_pair_1d_const.first, data.rend());  // expect no mismatch
2435     EXPECT_EQ(mismatch_it_pair_1d_const.second, m_1d_const.rend<uchar>());
2436 
2437     EXPECT_FALSE((std::is_assignable<decltype(m_1d_const.rend<uchar>()), uchar>::value)) << "Constness of const iterator violated.";
2438     EXPECT_FALSE((std::is_assignable<decltype(m_1d_const.rbegin<uchar>()), uchar>::value)) << "Constness of const iterator violated.";
2439 
2440     // const test templated dervied class
2441     const cv::Mat_<uchar> m_1d_const_t(static_cast<int>(sizes_1d.size()), sizes_1d.data(), data.data());
2442 
2443     auto mismatch_it_pair_1d_const_t = std::mismatch(data.rbegin(), data.rend(), m_1d_const_t.rbegin());
2444     EXPECT_EQ(mismatch_it_pair_1d_const_t.first, data.rend());  // expect no mismatch
2445     EXPECT_EQ(mismatch_it_pair_1d_const_t.second, m_1d_const_t.rend());
2446 
2447     EXPECT_FALSE((std::is_assignable<decltype(m_1d_const_t.rend()), uchar>::value)) << "Constness of const iterator violated.";
2448     EXPECT_FALSE((std::is_assignable<decltype(m_1d_const_t.rbegin()), uchar>::value)) << "Constness of const iterator violated.";
2449 
2450 }
2451 
2452 }} // namespace
2453