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