Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/core/test/test_mat.cpp
16337 views
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
namespace opencv_test { namespace {
7
8
class Core_ReduceTest : public cvtest::BaseTest
9
{
10
public:
11
Core_ReduceTest() {}
12
protected:
13
void run( int);
14
int checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim );
15
int checkCase( int srcType, int dstType, int dim, Size sz );
16
int checkDim( int dim, Size sz );
17
int checkSize( Size sz );
18
};
19
20
template<class Type>
21
void testReduce( const Mat& src, Mat& sum, Mat& avg, Mat& max, Mat& min, int dim )
22
{
23
assert( src.channels() == 1 );
24
if( dim == 0 ) // row
25
{
26
sum.create( 1, src.cols, CV_64FC1 );
27
max.create( 1, src.cols, CV_64FC1 );
28
min.create( 1, src.cols, CV_64FC1 );
29
}
30
else
31
{
32
sum.create( src.rows, 1, CV_64FC1 );
33
max.create( src.rows, 1, CV_64FC1 );
34
min.create( src.rows, 1, CV_64FC1 );
35
}
36
sum.setTo(Scalar(0));
37
max.setTo(Scalar(-DBL_MAX));
38
min.setTo(Scalar(DBL_MAX));
39
40
const Mat_<Type>& src_ = src;
41
Mat_<double>& sum_ = (Mat_<double>&)sum;
42
Mat_<double>& min_ = (Mat_<double>&)min;
43
Mat_<double>& max_ = (Mat_<double>&)max;
44
45
if( dim == 0 )
46
{
47
for( int ri = 0; ri < src.rows; ri++ )
48
{
49
for( int ci = 0; ci < src.cols; ci++ )
50
{
51
sum_(0, ci) += src_(ri, ci);
52
max_(0, ci) = std::max( max_(0, ci), (double)src_(ri, ci) );
53
min_(0, ci) = std::min( min_(0, ci), (double)src_(ri, ci) );
54
}
55
}
56
}
57
else
58
{
59
for( int ci = 0; ci < src.cols; ci++ )
60
{
61
for( int ri = 0; ri < src.rows; ri++ )
62
{
63
sum_(ri, 0) += src_(ri, ci);
64
max_(ri, 0) = std::max( max_(ri, 0), (double)src_(ri, ci) );
65
min_(ri, 0) = std::min( min_(ri, 0), (double)src_(ri, ci) );
66
}
67
}
68
}
69
sum.convertTo( avg, CV_64FC1 );
70
avg = avg * (1.0 / (dim==0 ? (double)src.rows : (double)src.cols));
71
}
72
73
void getMatTypeStr( int type, string& str)
74
{
75
str = type == CV_8UC1 ? "CV_8UC1" :
76
type == CV_8SC1 ? "CV_8SC1" :
77
type == CV_16UC1 ? "CV_16UC1" :
78
type == CV_16SC1 ? "CV_16SC1" :
79
type == CV_32SC1 ? "CV_32SC1" :
80
type == CV_32FC1 ? "CV_32FC1" :
81
type == CV_64FC1 ? "CV_64FC1" : "unsupported matrix type";
82
}
83
84
int Core_ReduceTest::checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim )
85
{
86
int srcType = src.type();
87
bool support = false;
88
if( opType == CV_REDUCE_SUM || opType == CV_REDUCE_AVG )
89
{
90
if( srcType == CV_8U && (dstType == CV_32S || dstType == CV_32F || dstType == CV_64F) )
91
support = true;
92
if( srcType == CV_16U && (dstType == CV_32F || dstType == CV_64F) )
93
support = true;
94
if( srcType == CV_16S && (dstType == CV_32F || dstType == CV_64F) )
95
support = true;
96
if( srcType == CV_32F && (dstType == CV_32F || dstType == CV_64F) )
97
support = true;
98
if( srcType == CV_64F && dstType == CV_64F)
99
support = true;
100
}
101
else if( opType == CV_REDUCE_MAX )
102
{
103
if( srcType == CV_8U && dstType == CV_8U )
104
support = true;
105
if( srcType == CV_32F && dstType == CV_32F )
106
support = true;
107
if( srcType == CV_64F && dstType == CV_64F )
108
support = true;
109
}
110
else if( opType == CV_REDUCE_MIN )
111
{
112
if( srcType == CV_8U && dstType == CV_8U)
113
support = true;
114
if( srcType == CV_32F && dstType == CV_32F)
115
support = true;
116
if( srcType == CV_64F && dstType == CV_64F)
117
support = true;
118
}
119
if( !support )
120
return cvtest::TS::OK;
121
122
double eps = 0.0;
123
if ( opType == CV_REDUCE_SUM || opType == CV_REDUCE_AVG )
124
{
125
if ( dstType == CV_32F )
126
eps = 1.e-5;
127
else if( dstType == CV_64F )
128
eps = 1.e-8;
129
else if ( dstType == CV_32S )
130
eps = 0.6;
131
}
132
133
assert( opRes.type() == CV_64FC1 );
134
Mat _dst, dst, diff;
135
cv::reduce( src, _dst, dim, opType, dstType );
136
_dst.convertTo( dst, CV_64FC1 );
137
138
absdiff( opRes,dst,diff );
139
bool check = false;
140
if (dstType == CV_32F || dstType == CV_64F)
141
check = countNonZero(diff>eps*dst) > 0;
142
else
143
check = countNonZero(diff>eps) > 0;
144
if( check )
145
{
146
char msg[100];
147
const char* opTypeStr = opType == CV_REDUCE_SUM ? "CV_REDUCE_SUM" :
148
opType == CV_REDUCE_AVG ? "CV_REDUCE_AVG" :
149
opType == CV_REDUCE_MAX ? "CV_REDUCE_MAX" :
150
opType == CV_REDUCE_MIN ? "CV_REDUCE_MIN" : "unknown operation type";
151
string srcTypeStr, dstTypeStr;
152
getMatTypeStr( src.type(), srcTypeStr );
153
getMatTypeStr( dstType, dstTypeStr );
154
const char* dimStr = dim == 0 ? "ROWS" : "COLS";
155
156
sprintf( msg, "bad accuracy with srcType = %s, dstType = %s, opType = %s, dim = %s",
157
srcTypeStr.c_str(), dstTypeStr.c_str(), opTypeStr, dimStr );
158
ts->printf( cvtest::TS::LOG, msg );
159
return cvtest::TS::FAIL_BAD_ACCURACY;
160
}
161
return cvtest::TS::OK;
162
}
163
164
int Core_ReduceTest::checkCase( int srcType, int dstType, int dim, Size sz )
165
{
166
int code = cvtest::TS::OK, tempCode;
167
Mat src, sum, avg, max, min;
168
169
src.create( sz, srcType );
170
randu( src, Scalar(0), Scalar(100) );
171
172
if( srcType == CV_8UC1 )
173
testReduce<uchar>( src, sum, avg, max, min, dim );
174
else if( srcType == CV_8SC1 )
175
testReduce<char>( src, sum, avg, max, min, dim );
176
else if( srcType == CV_16UC1 )
177
testReduce<unsigned short int>( src, sum, avg, max, min, dim );
178
else if( srcType == CV_16SC1 )
179
testReduce<short int>( src, sum, avg, max, min, dim );
180
else if( srcType == CV_32SC1 )
181
testReduce<int>( src, sum, avg, max, min, dim );
182
else if( srcType == CV_32FC1 )
183
testReduce<float>( src, sum, avg, max, min, dim );
184
else if( srcType == CV_64FC1 )
185
testReduce<double>( src, sum, avg, max, min, dim );
186
else
187
assert( 0 );
188
189
// 1. sum
190
tempCode = checkOp( src, dstType, CV_REDUCE_SUM, sum, dim );
191
code = tempCode != cvtest::TS::OK ? tempCode : code;
192
193
// 2. avg
194
tempCode = checkOp( src, dstType, CV_REDUCE_AVG, avg, dim );
195
code = tempCode != cvtest::TS::OK ? tempCode : code;
196
197
// 3. max
198
tempCode = checkOp( src, dstType, CV_REDUCE_MAX, max, dim );
199
code = tempCode != cvtest::TS::OK ? tempCode : code;
200
201
// 4. min
202
tempCode = checkOp( src, dstType, CV_REDUCE_MIN, min, dim );
203
code = tempCode != cvtest::TS::OK ? tempCode : code;
204
205
return code;
206
}
207
208
int Core_ReduceTest::checkDim( int dim, Size sz )
209
{
210
int code = cvtest::TS::OK, tempCode;
211
212
// CV_8UC1
213
tempCode = checkCase( CV_8UC1, CV_8UC1, dim, sz );
214
code = tempCode != cvtest::TS::OK ? tempCode : code;
215
216
tempCode = checkCase( CV_8UC1, CV_32SC1, dim, sz );
217
code = tempCode != cvtest::TS::OK ? tempCode : code;
218
219
tempCode = checkCase( CV_8UC1, CV_32FC1, dim, sz );
220
code = tempCode != cvtest::TS::OK ? tempCode : code;
221
222
tempCode = checkCase( CV_8UC1, CV_64FC1, dim, sz );
223
code = tempCode != cvtest::TS::OK ? tempCode : code;
224
225
// CV_16UC1
226
tempCode = checkCase( CV_16UC1, CV_32FC1, dim, sz );
227
code = tempCode != cvtest::TS::OK ? tempCode : code;
228
229
tempCode = checkCase( CV_16UC1, CV_64FC1, dim, sz );
230
code = tempCode != cvtest::TS::OK ? tempCode : code;
231
232
// CV_16SC1
233
tempCode = checkCase( CV_16SC1, CV_32FC1, dim, sz );
234
code = tempCode != cvtest::TS::OK ? tempCode : code;
235
236
tempCode = checkCase( CV_16SC1, CV_64FC1, dim, sz );
237
code = tempCode != cvtest::TS::OK ? tempCode : code;
238
239
// CV_32FC1
240
tempCode = checkCase( CV_32FC1, CV_32FC1, dim, sz );
241
code = tempCode != cvtest::TS::OK ? tempCode : code;
242
243
tempCode = checkCase( CV_32FC1, CV_64FC1, dim, sz );
244
code = tempCode != cvtest::TS::OK ? tempCode : code;
245
246
// CV_64FC1
247
tempCode = checkCase( CV_64FC1, CV_64FC1, dim, sz );
248
code = tempCode != cvtest::TS::OK ? tempCode : code;
249
250
return code;
251
}
252
253
int Core_ReduceTest::checkSize( Size sz )
254
{
255
int code = cvtest::TS::OK, tempCode;
256
257
tempCode = checkDim( 0, sz ); // rows
258
code = tempCode != cvtest::TS::OK ? tempCode : code;
259
260
tempCode = checkDim( 1, sz ); // cols
261
code = tempCode != cvtest::TS::OK ? tempCode : code;
262
263
return code;
264
}
265
266
void Core_ReduceTest::run( int )
267
{
268
int code = cvtest::TS::OK, tempCode;
269
270
tempCode = checkSize( Size(1,1) );
271
code = tempCode != cvtest::TS::OK ? tempCode : code;
272
273
tempCode = checkSize( Size(1,100) );
274
code = tempCode != cvtest::TS::OK ? tempCode : code;
275
276
tempCode = checkSize( Size(100,1) );
277
code = tempCode != cvtest::TS::OK ? tempCode : code;
278
279
tempCode = checkSize( Size(1000,500) );
280
code = tempCode != cvtest::TS::OK ? tempCode : code;
281
282
ts->set_failed_test_info( code );
283
}
284
285
286
#define CHECK_C
287
288
TEST(Core_PCA, accuracy)
289
{
290
const Size sz(200, 500);
291
292
double diffPrjEps, diffBackPrjEps,
293
prjEps, backPrjEps,
294
evalEps, evecEps;
295
int maxComponents = 100;
296
double retainedVariance = 0.95;
297
Mat rPoints(sz, CV_32FC1), rTestPoints(sz, CV_32FC1);
298
RNG rng(12345);
299
300
rng.fill( rPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) );
301
rng.fill( rTestPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) );
302
303
PCA rPCA( rPoints, Mat(), CV_PCA_DATA_AS_ROW, maxComponents ), cPCA;
304
305
// 1. check C++ PCA & ROW
306
Mat rPrjTestPoints = rPCA.project( rTestPoints );
307
Mat rBackPrjTestPoints = rPCA.backProject( rPrjTestPoints );
308
309
Mat avg(1, sz.width, CV_32FC1 );
310
cv::reduce( rPoints, avg, 0, CV_REDUCE_AVG );
311
Mat Q = rPoints - repeat( avg, rPoints.rows, 1 ), Qt = Q.t(), eval, evec;
312
Q = Qt * Q;
313
Q = Q /(float)rPoints.rows;
314
315
eigen( Q, eval, evec );
316
/*SVD svd(Q);
317
evec = svd.vt;
318
eval = svd.w;*/
319
320
Mat subEval( maxComponents, 1, eval.type(), eval.ptr() ),
321
subEvec( maxComponents, evec.cols, evec.type(), evec.ptr() );
322
323
#ifdef CHECK_C
324
Mat prjTestPoints, backPrjTestPoints, cPoints = rPoints.t(), cTestPoints = rTestPoints.t();
325
CvMat _points, _testPoints, _avg, _eval, _evec, _prjTestPoints, _backPrjTestPoints;
326
#endif
327
328
// check eigen()
329
double eigenEps = 1e-4;
330
double err;
331
for(int i = 0; i < Q.rows; i++ )
332
{
333
Mat v = evec.row(i).t();
334
Mat Qv = Q * v;
335
336
Mat lv = eval.at<float>(i,0) * v;
337
err = cvtest::norm(Qv, lv, NORM_L2 | NORM_RELATIVE);
338
EXPECT_LE(err, eigenEps) << "bad accuracy of eigen(); i = " << i;
339
}
340
// check pca eigenvalues
341
evalEps = 1e-5, evecEps = 5e-3;
342
err = cvtest::norm(rPCA.eigenvalues, subEval, NORM_L2 | NORM_RELATIVE);
343
EXPECT_LE(err , evalEps) << "pca.eigenvalues is incorrect (CV_PCA_DATA_AS_ROW)";
344
// check pca eigenvectors
345
for(int i = 0; i < subEvec.rows; i++)
346
{
347
Mat r0 = rPCA.eigenvectors.row(i);
348
Mat r1 = subEvec.row(i);
349
// eigenvectors have normalized length, but both directions v and -v are valid
350
double err1 = cvtest::norm(r0, r1, NORM_L2 | NORM_RELATIVE);
351
double err2 = cvtest::norm(r0, -r1, NORM_L2 | NORM_RELATIVE);
352
err = std::min(err1, err2);
353
if (err > evecEps)
354
{
355
Mat tmp;
356
absdiff(rPCA.eigenvectors, subEvec, tmp);
357
double mval = 0; Point mloc;
358
minMaxLoc(tmp, 0, &mval, 0, &mloc);
359
360
EXPECT_LE(err, evecEps) << "pca.eigenvectors is incorrect (CV_PCA_DATA_AS_ROW) at " << i << " "
361
<< cv::format("max diff is %g at (i=%d, j=%d) (%g vs %g)\n",
362
mval, mloc.y, mloc.x, rPCA.eigenvectors.at<float>(mloc.y, mloc.x),
363
subEvec.at<float>(mloc.y, mloc.x))
364
<< "r0=" << r0 << std::endl
365
<< "r1=" << r1 << std::endl
366
<< "err1=" << err1 << " err2=" << err2
367
;
368
}
369
}
370
371
prjEps = 1.265, backPrjEps = 1.265;
372
for( int i = 0; i < rTestPoints.rows; i++ )
373
{
374
// check pca project
375
Mat subEvec_t = subEvec.t();
376
Mat prj = rTestPoints.row(i) - avg; prj *= subEvec_t;
377
err = cvtest::norm(rPrjTestPoints.row(i), prj, NORM_L2 | NORM_RELATIVE);
378
if (err < prjEps)
379
{
380
EXPECT_LE(err, prjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_ROW)";
381
continue;
382
}
383
// check pca backProject
384
Mat backPrj = rPrjTestPoints.row(i) * subEvec + avg;
385
err = cvtest::norm(rBackPrjTestPoints.row(i), backPrj, NORM_L2 | NORM_RELATIVE);
386
if (err > backPrjEps)
387
{
388
EXPECT_LE(err, backPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_ROW)";
389
continue;
390
}
391
}
392
393
// 2. check C++ PCA & COL
394
cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, maxComponents );
395
diffPrjEps = 1, diffBackPrjEps = 1;
396
Mat ocvPrjTestPoints = cPCA.project(rTestPoints.t());
397
err = cvtest::norm(cv::abs(ocvPrjTestPoints), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE);
398
ASSERT_LE(err, diffPrjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_COL)";
399
err = cvtest::norm(cPCA.backProject(ocvPrjTestPoints), rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE);
400
ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_COL)";
401
402
// 3. check C++ PCA w/retainedVariance
403
cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, retainedVariance );
404
diffPrjEps = 1, diffBackPrjEps = 1;
405
Mat rvPrjTestPoints = cPCA.project(rTestPoints.t());
406
407
if( cPCA.eigenvectors.rows > maxComponents)
408
err = cvtest::norm(cv::abs(rvPrjTestPoints.rowRange(0,maxComponents)), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE);
409
else
410
err = cvtest::norm(cv::abs(rvPrjTestPoints), cv::abs(rPrjTestPoints.colRange(0,cPCA.eigenvectors.rows).t()), NORM_L2 | NORM_RELATIVE);
411
412
ASSERT_LE(err, diffPrjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_COL); retainedVariance=" << retainedVariance;
413
err = cvtest::norm(cPCA.backProject(rvPrjTestPoints), rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE);
414
ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); retainedVariance=" << retainedVariance;
415
416
#ifdef CHECK_C
417
// 4. check C PCA & ROW
418
_points = cvMat(rPoints);
419
_testPoints = cvMat(rTestPoints);
420
_avg = cvMat(avg);
421
_eval = cvMat(eval);
422
_evec = cvMat(evec);
423
prjTestPoints.create(rTestPoints.rows, maxComponents, rTestPoints.type() );
424
backPrjTestPoints.create(rPoints.size(), rPoints.type() );
425
_prjTestPoints = cvMat(prjTestPoints);
426
_backPrjTestPoints = cvMat(backPrjTestPoints);
427
428
cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_ROW );
429
cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
430
cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
431
432
err = cvtest::norm(prjTestPoints, rPrjTestPoints, NORM_L2 | NORM_RELATIVE);
433
ASSERT_LE(err, diffPrjEps) << "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_ROW)";
434
err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints, NORM_L2 | NORM_RELATIVE);
435
ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_ROW)";
436
437
// 5. check C PCA & COL
438
_points = cvMat(cPoints);
439
_testPoints = cvMat(cTestPoints);
440
avg = avg.t(); _avg = cvMat(avg);
441
eval = eval.t(); _eval = cvMat(eval);
442
evec = evec.t(); _evec = cvMat(evec);
443
prjTestPoints = prjTestPoints.t(); _prjTestPoints = cvMat(prjTestPoints);
444
backPrjTestPoints = backPrjTestPoints.t(); _backPrjTestPoints = cvMat(backPrjTestPoints);
445
446
cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_COL );
447
cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
448
cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
449
450
err = cvtest::norm(cv::abs(prjTestPoints), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE);
451
ASSERT_LE(err, diffPrjEps) << "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_COL)";
452
err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE);
453
ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_COL)";
454
#endif
455
// Test read and write
456
FileStorage fs( "PCA_store.yml", FileStorage::WRITE );
457
rPCA.write( fs );
458
fs.release();
459
460
PCA lPCA;
461
fs.open( "PCA_store.yml", FileStorage::READ );
462
lPCA.read( fs.root() );
463
err = cvtest::norm(rPCA.eigenvectors, lPCA.eigenvectors, NORM_L2 | NORM_RELATIVE);
464
EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)";
465
err = cvtest::norm(rPCA.eigenvalues, lPCA.eigenvalues, NORM_L2 | NORM_RELATIVE);
466
EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)";
467
err = cvtest::norm(rPCA.mean, lPCA.mean, NORM_L2 | NORM_RELATIVE);
468
EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)";
469
}
470
471
class Core_ArrayOpTest : public cvtest::BaseTest
472
{
473
public:
474
Core_ArrayOpTest();
475
~Core_ArrayOpTest();
476
protected:
477
void run(int);
478
};
479
480
481
Core_ArrayOpTest::Core_ArrayOpTest()
482
{
483
}
484
Core_ArrayOpTest::~Core_ArrayOpTest() {}
485
486
static string idx2string(const int* idx, int dims)
487
{
488
char buf[256];
489
char* ptr = buf;
490
for( int k = 0; k < dims; k++ )
491
{
492
sprintf(ptr, "%4d ", idx[k]);
493
ptr += strlen(ptr);
494
}
495
ptr[-1] = '\0';
496
return string(buf);
497
}
498
499
static const int* string2idx(const string& s, int* idx, int dims)
500
{
501
const char* ptr = s.c_str();
502
for( int k = 0; k < dims; k++ )
503
{
504
int n = 0;
505
sscanf(ptr, "%d%n", idx + k, &n);
506
ptr += n;
507
}
508
return idx;
509
}
510
511
static double getValue(SparseMat& M, const int* idx, RNG& rng)
512
{
513
int d = M.dims();
514
size_t hv = 0, *phv = 0;
515
if( (unsigned)rng % 2 )
516
{
517
hv = d == 2 ? M.hash(idx[0], idx[1]) :
518
d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
519
phv = &hv;
520
}
521
522
const uchar* ptr = d == 2 ? M.ptr(idx[0], idx[1], false, phv) :
523
d == 3 ? M.ptr(idx[0], idx[1], idx[2], false, phv) :
524
M.ptr(idx, false, phv);
525
return !ptr ? 0 : M.type() == CV_32F ? *(float*)ptr : M.type() == CV_64F ? *(double*)ptr : 0;
526
}
527
528
static double getValue(const CvSparseMat* M, const int* idx)
529
{
530
int type = 0;
531
const uchar* ptr = cvPtrND(M, idx, &type, 0);
532
return !ptr ? 0 : type == CV_32F ? *(float*)ptr : type == CV_64F ? *(double*)ptr : 0;
533
}
534
535
static void eraseValue(SparseMat& M, const int* idx, RNG& rng)
536
{
537
int d = M.dims();
538
size_t hv = 0, *phv = 0;
539
if( (unsigned)rng % 2 )
540
{
541
hv = d == 2 ? M.hash(idx[0], idx[1]) :
542
d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
543
phv = &hv;
544
}
545
546
if( d == 2 )
547
M.erase(idx[0], idx[1], phv);
548
else if( d == 3 )
549
M.erase(idx[0], idx[1], idx[2], phv);
550
else
551
M.erase(idx, phv);
552
}
553
554
static void eraseValue(CvSparseMat* M, const int* idx)
555
{
556
cvClearND(M, idx);
557
}
558
559
static void setValue(SparseMat& M, const int* idx, double value, RNG& rng)
560
{
561
int d = M.dims();
562
size_t hv = 0, *phv = 0;
563
if( (unsigned)rng % 2 )
564
{
565
hv = d == 2 ? M.hash(idx[0], idx[1]) :
566
d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
567
phv = &hv;
568
}
569
570
uchar* ptr = d == 2 ? M.ptr(idx[0], idx[1], true, phv) :
571
d == 3 ? M.ptr(idx[0], idx[1], idx[2], true, phv) :
572
M.ptr(idx, true, phv);
573
if( M.type() == CV_32F )
574
*(float*)ptr = (float)value;
575
else if( M.type() == CV_64F )
576
*(double*)ptr = value;
577
else
578
CV_Error(CV_StsUnsupportedFormat, "");
579
}
580
581
template<typename Pixel>
582
struct InitializerFunctor{
583
/// Initializer for cv::Mat::forEach test
584
void operator()(Pixel & pixel, const int * idx) const {
585
pixel.x = idx[0];
586
pixel.y = idx[1];
587
pixel.z = idx[2];
588
}
589
};
590
591
template<typename Pixel>
592
struct InitializerFunctor5D{
593
/// Initializer for cv::Mat::forEach test (5 dimensional case)
594
void operator()(Pixel & pixel, const int * idx) const {
595
pixel[0] = idx[0];
596
pixel[1] = idx[1];
597
pixel[2] = idx[2];
598
pixel[3] = idx[3];
599
pixel[4] = idx[4];
600
}
601
};
602
603
template<typename Pixel>
604
struct EmptyFunctor
605
{
606
void operator()(const Pixel &, const int *) const {}
607
};
608
609
610
void Core_ArrayOpTest::run( int /* start_from */)
611
{
612
int errcount = 0;
613
614
// dense matrix operations
615
{
616
int sz3[] = {5, 10, 15};
617
MatND A(3, sz3, CV_32F), B(3, sz3, CV_16SC4);
618
CvMatND matA = cvMatND(A), matB = cvMatND(B);
619
RNG rng;
620
rng.fill(A, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
621
rng.fill(B, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
622
623
int idx0[] = {3,4,5}, idx1[] = {0, 9, 7};
624
float val0 = 130;
625
Scalar val1(-1000, 30, 3, 8);
626
cvSetRealND(&matA, idx0, val0);
627
cvSetReal3D(&matA, idx1[0], idx1[1], idx1[2], -val0);
628
cvSetND(&matB, idx0, cvScalar(val1));
629
cvSet3D(&matB, idx1[0], idx1[1], idx1[2], cvScalar(-val1));
630
Ptr<CvMatND> matC(cvCloneMatND(&matB));
631
632
if( A.at<float>(idx0[0], idx0[1], idx0[2]) != val0 ||
633
A.at<float>(idx1[0], idx1[1], idx1[2]) != -val0 ||
634
cvGetReal3D(&matA, idx0[0], idx0[1], idx0[2]) != val0 ||
635
cvGetRealND(&matA, idx1) != -val0 ||
636
637
Scalar(B.at<Vec4s>(idx0[0], idx0[1], idx0[2])) != val1 ||
638
Scalar(B.at<Vec4s>(idx1[0], idx1[1], idx1[2])) != -val1 ||
639
Scalar(cvGet3D(matC, idx0[0], idx0[1], idx0[2])) != val1 ||
640
Scalar(cvGetND(matC, idx1)) != -val1 )
641
{
642
ts->printf(cvtest::TS::LOG, "one of cvSetReal3D, cvSetRealND, cvSet3D, cvSetND "
643
"or the corresponding *Get* functions is not correct\n");
644
errcount++;
645
}
646
}
647
// test cv::Mat::forEach
648
{
649
const int dims[3] = { 101, 107, 7 };
650
typedef cv::Point3i Pixel;
651
652
cv::Mat a = cv::Mat::zeros(3, dims, CV_32SC3);
653
InitializerFunctor<Pixel> initializer;
654
655
a.forEach<Pixel>(initializer);
656
657
uint64 total = 0;
658
bool error_reported = false;
659
for (int i0 = 0; i0 < dims[0]; ++i0) {
660
for (int i1 = 0; i1 < dims[1]; ++i1) {
661
for (int i2 = 0; i2 < dims[2]; ++i2) {
662
Pixel& pixel = a.at<Pixel>(i0, i1, i2);
663
if (pixel.x != i0 || pixel.y != i1 || pixel.z != i2) {
664
if (!error_reported) {
665
ts->printf(cvtest::TS::LOG, "forEach is not correct.\n"
666
"First error detected at (%d, %d, %d).\n", pixel.x, pixel.y, pixel.z);
667
error_reported = true;
668
}
669
errcount++;
670
}
671
total += pixel.x;
672
total += pixel.y;
673
total += pixel.z;
674
}
675
}
676
}
677
uint64 total2 = 0;
678
for (size_t i = 0; i < sizeof(dims) / sizeof(dims[0]); ++i) {
679
total2 += ((dims[i] - 1) * dims[i] / 2) * dims[0] * dims[1] * dims[2] / dims[i];
680
}
681
if (total != total2) {
682
ts->printf(cvtest::TS::LOG, "forEach is not correct because total is invalid.\n");
683
errcount++;
684
}
685
}
686
687
// test cv::Mat::forEach
688
// with a matrix that has more dimensions than columns
689
// See https://github.com/opencv/opencv/issues/8447
690
{
691
const int dims[5] = { 2, 2, 2, 2, 2 };
692
typedef cv::Vec<int, 5> Pixel;
693
694
cv::Mat a = cv::Mat::zeros(5, dims, CV_32SC(5));
695
InitializerFunctor5D<Pixel> initializer;
696
697
a.forEach<Pixel>(initializer);
698
699
uint64 total = 0;
700
bool error_reported = false;
701
for (int i0 = 0; i0 < dims[0]; ++i0) {
702
for (int i1 = 0; i1 < dims[1]; ++i1) {
703
for (int i2 = 0; i2 < dims[2]; ++i2) {
704
for (int i3 = 0; i3 < dims[3]; ++i3) {
705
for (int i4 = 0; i4 < dims[4]; ++i4) {
706
const int i[5] = { i0, i1, i2, i3, i4 };
707
Pixel& pixel = a.at<Pixel>(i);
708
if (pixel[0] != i0 || pixel[1] != i1 || pixel[2] != i2 || pixel[3] != i3 || pixel[4] != i4) {
709
if (!error_reported) {
710
ts->printf(cvtest::TS::LOG, "forEach is not correct.\n"
711
"First error detected at position (%d, %d, %d, %d, %d), got value (%d, %d, %d, %d, %d).\n",
712
i0, i1, i2, i3, i4,
713
pixel[0], pixel[1], pixel[2], pixel[3], pixel[4]);
714
error_reported = true;
715
}
716
errcount++;
717
}
718
total += pixel[0];
719
total += pixel[1];
720
total += pixel[2];
721
total += pixel[3];
722
total += pixel[4];
723
}
724
}
725
}
726
}
727
}
728
uint64 total2 = 0;
729
for (size_t i = 0; i < sizeof(dims) / sizeof(dims[0]); ++i) {
730
total2 += ((dims[i] - 1) * dims[i] / 2) * dims[0] * dims[1] * dims[2] * dims[3] * dims[4] / dims[i];
731
}
732
if (total != total2) {
733
ts->printf(cvtest::TS::LOG, "forEach is not correct because total is invalid.\n");
734
errcount++;
735
}
736
}
737
738
// test const cv::Mat::forEach
739
{
740
const Mat a(10, 10, CV_32SC3);
741
Mat b(10, 10, CV_32SC3);
742
const Mat & c = b;
743
a.forEach<Point3i>(EmptyFunctor<Point3i>());
744
b.forEach<Point3i>(EmptyFunctor<const Point3i>());
745
c.forEach<Point3i>(EmptyFunctor<Point3i>());
746
// tests compilation, no runtime check is needed
747
}
748
749
RNG rng;
750
const int MAX_DIM = 5, MAX_DIM_SZ = 10;
751
// sparse matrix operations
752
for( int si = 0; si < 10; si++ )
753
{
754
int depth = (unsigned)rng % 2 == 0 ? CV_32F : CV_64F;
755
int dims = ((unsigned)rng % MAX_DIM) + 1;
756
int i, k, size[MAX_DIM]={0}, idx[MAX_DIM]={0};
757
vector<string> all_idxs;
758
vector<double> all_vals;
759
vector<double> all_vals2;
760
string sidx, min_sidx, max_sidx;
761
double min_val=0, max_val=0;
762
763
int p = 1;
764
for( k = 0; k < dims; k++ )
765
{
766
size[k] = ((unsigned)rng % MAX_DIM_SZ) + 1;
767
p *= size[k];
768
}
769
SparseMat M( dims, size, depth );
770
map<string, double> M0;
771
772
int nz0 = (unsigned)rng % std::max(p/5,10);
773
nz0 = std::min(std::max(nz0, 1), p);
774
all_vals.resize(nz0);
775
all_vals2.resize(nz0);
776
Mat_<double> _all_vals(all_vals), _all_vals2(all_vals2);
777
rng.fill(_all_vals, CV_RAND_UNI, Scalar(-1000), Scalar(1000));
778
if( depth == CV_32F )
779
{
780
Mat _all_vals_f;
781
_all_vals.convertTo(_all_vals_f, CV_32F);
782
_all_vals_f.convertTo(_all_vals, CV_64F);
783
}
784
_all_vals.convertTo(_all_vals2, _all_vals2.type(), 2);
785
if( depth == CV_32F )
786
{
787
Mat _all_vals2_f;
788
_all_vals2.convertTo(_all_vals2_f, CV_32F);
789
_all_vals2_f.convertTo(_all_vals2, CV_64F);
790
}
791
792
minMaxLoc(_all_vals, &min_val, &max_val);
793
double _norm0 = cv/*test*/::norm(_all_vals, CV_C);
794
double _norm1 = cv/*test*/::norm(_all_vals, CV_L1);
795
double _norm2 = cv/*test*/::norm(_all_vals, CV_L2);
796
797
for( i = 0; i < nz0; i++ )
798
{
799
for(;;)
800
{
801
for( k = 0; k < dims; k++ )
802
idx[k] = (unsigned)rng % size[k];
803
sidx = idx2string(idx, dims);
804
if( M0.count(sidx) == 0 )
805
break;
806
}
807
all_idxs.push_back(sidx);
808
M0[sidx] = all_vals[i];
809
if( all_vals[i] == min_val )
810
min_sidx = sidx;
811
if( all_vals[i] == max_val )
812
max_sidx = sidx;
813
setValue(M, idx, all_vals[i], rng);
814
double v = getValue(M, idx, rng);
815
if( v != all_vals[i] )
816
{
817
ts->printf(cvtest::TS::LOG, "%d. immediately after SparseMat[%s]=%.20g the current value is %.20g\n",
818
i, sidx.c_str(), all_vals[i], v);
819
errcount++;
820
break;
821
}
822
}
823
824
Ptr<CvSparseMat> M2(cvCreateSparseMat(M));
825
MatND Md;
826
M.copyTo(Md);
827
SparseMat M3; SparseMat(Md).convertTo(M3, Md.type(), 2);
828
829
int nz1 = (int)M.nzcount(), nz2 = (int)M3.nzcount();
830
double norm0 = cv/*test*/::norm(M, CV_C);
831
double norm1 = cv/*test*/::norm(M, CV_L1);
832
double norm2 = cv/*test*/::norm(M, CV_L2);
833
double eps = depth == CV_32F ? FLT_EPSILON*100 : DBL_EPSILON*1000;
834
835
if( nz1 != nz0 || nz2 != nz0)
836
{
837
errcount++;
838
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",
839
si, nz1, nz2, nz0 );
840
break;
841
}
842
843
if( fabs(norm0 - _norm0) > fabs(_norm0)*eps ||
844
fabs(norm1 - _norm1) > fabs(_norm1)*eps ||
845
fabs(norm2 - _norm2) > fabs(_norm2)*eps )
846
{
847
errcount++;
848
ts->printf(cvtest::TS::LOG, "%d: The norms are different: %.20g/%.20g/%.20g vs %.20g/%.20g/%.20g\n",
849
si, norm0, norm1, norm2, _norm0, _norm1, _norm2 );
850
break;
851
}
852
853
int n = (unsigned)rng % std::max(p/5,10);
854
n = std::min(std::max(n, 1), p) + nz0;
855
856
for( i = 0; i < n; i++ )
857
{
858
double val1, val2, val3, val0;
859
if(i < nz0)
860
{
861
sidx = all_idxs[i];
862
string2idx(sidx, idx, dims);
863
val0 = all_vals[i];
864
}
865
else
866
{
867
for( k = 0; k < dims; k++ )
868
idx[k] = (unsigned)rng % size[k];
869
sidx = idx2string(idx, dims);
870
val0 = M0[sidx];
871
}
872
val1 = getValue(M, idx, rng);
873
val2 = getValue(M2, idx);
874
val3 = getValue(M3, idx, rng);
875
876
if( val1 != val0 || val2 != val0 || fabs(val3 - val0*2) > fabs(val0*2)*FLT_EPSILON )
877
{
878
errcount++;
879
ts->printf(cvtest::TS::LOG, "SparseMat M[%s] = %g/%g/%g (while it should be %g)\n", sidx.c_str(), val1, val2, val3, val0 );
880
break;
881
}
882
}
883
884
for( i = 0; i < n; i++ )
885
{
886
double val1, val2;
887
if(i < nz0)
888
{
889
sidx = all_idxs[i];
890
string2idx(sidx, idx, dims);
891
}
892
else
893
{
894
for( k = 0; k < dims; k++ )
895
idx[k] = (unsigned)rng % size[k];
896
sidx = idx2string(idx, dims);
897
}
898
eraseValue(M, idx, rng);
899
eraseValue(M2, idx);
900
val1 = getValue(M, idx, rng);
901
val2 = getValue(M2, idx);
902
if( val1 != 0 || val2 != 0 )
903
{
904
errcount++;
905
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 );
906
break;
907
}
908
}
909
910
int nz = (int)M.nzcount();
911
if( nz != 0 )
912
{
913
errcount++;
914
ts->printf(cvtest::TS::LOG, "The number of non-zero elements after removing all the elements = %d (while it should be 0)\n", nz );
915
break;
916
}
917
918
int idx1[MAX_DIM], idx2[MAX_DIM];
919
double val1 = 0, val2 = 0;
920
M3 = SparseMat(Md);
921
cv::minMaxLoc(M3, &val1, &val2, idx1, idx2);
922
string s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
923
if( val1 != min_val || val2 != max_val || s1 != min_sidx || s2 != max_sidx )
924
{
925
errcount++;
926
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"
927
"(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
928
min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
929
break;
930
}
931
932
cv::minMaxIdx(Md, &val1, &val2, idx1, idx2);
933
s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
934
if( (min_val < 0 && (val1 != min_val || s1 != min_sidx)) ||
935
(max_val > 0 && (val2 != max_val || s2 != max_sidx)) )
936
{
937
errcount++;
938
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"
939
"(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
940
min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
941
break;
942
}
943
}
944
945
ts->set_failed_test_info(errcount == 0 ? cvtest::TS::OK : cvtest::TS::FAIL_INVALID_OUTPUT);
946
}
947
948
949
template <class T>
950
int calcDiffElemCountImpl(const vector<Mat>& mv, const Mat& m)
951
{
952
int diffElemCount = 0;
953
const int mChannels = m.channels();
954
for(int y = 0; y < m.rows; y++)
955
{
956
for(int x = 0; x < m.cols; x++)
957
{
958
const T* mElem = &m.at<T>(y, x*mChannels);
959
size_t loc = 0;
960
for(size_t i = 0; i < mv.size(); i++)
961
{
962
const size_t mvChannel = mv[i].channels();
963
const T* mvElem = &mv[i].at<T>(y, x*(int)mvChannel);
964
for(size_t li = 0; li < mvChannel; li++)
965
if(mElem[loc + li] != mvElem[li])
966
diffElemCount++;
967
loc += mvChannel;
968
}
969
CV_Assert(loc == (size_t)mChannels);
970
}
971
}
972
return diffElemCount;
973
}
974
975
static
976
int calcDiffElemCount(const vector<Mat>& mv, const Mat& m)
977
{
978
int depth = m.depth();
979
switch (depth)
980
{
981
case CV_8U:
982
return calcDiffElemCountImpl<uchar>(mv, m);
983
case CV_8S:
984
return calcDiffElemCountImpl<char>(mv, m);
985
case CV_16U:
986
return calcDiffElemCountImpl<unsigned short>(mv, m);
987
case CV_16S:
988
return calcDiffElemCountImpl<short int>(mv, m);
989
case CV_32S:
990
return calcDiffElemCountImpl<int>(mv, m);
991
case CV_32F:
992
return calcDiffElemCountImpl<float>(mv, m);
993
case CV_64F:
994
return calcDiffElemCountImpl<double>(mv, m);
995
}
996
997
return INT_MAX;
998
}
999
1000
class Core_MergeSplitBaseTest : public cvtest::BaseTest
1001
{
1002
protected:
1003
virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng) = 0;
1004
1005
virtual void run(int)
1006
{
1007
// m is Mat
1008
// mv is vector<Mat>
1009
const int minMSize = 1;
1010
const int maxMSize = 100;
1011
const size_t maxMvSize = 10;
1012
1013
RNG& rng = theRNG();
1014
Size mSize(rng.uniform(minMSize, maxMSize), rng.uniform(minMSize, maxMSize));
1015
size_t mvSize = rng.uniform(1, maxMvSize);
1016
1017
int res = cvtest::TS::OK;
1018
int curRes = run_case(CV_8U, mvSize, mSize, rng);
1019
res = curRes != cvtest::TS::OK ? curRes : res;
1020
1021
curRes = run_case(CV_8S, mvSize, mSize, rng);
1022
res = curRes != cvtest::TS::OK ? curRes : res;
1023
1024
curRes = run_case(CV_16U, mvSize, mSize, rng);
1025
res = curRes != cvtest::TS::OK ? curRes : res;
1026
1027
curRes = run_case(CV_16S, mvSize, mSize, rng);
1028
res = curRes != cvtest::TS::OK ? curRes : res;
1029
1030
curRes = run_case(CV_32S, mvSize, mSize, rng);
1031
res = curRes != cvtest::TS::OK ? curRes : res;
1032
1033
curRes = run_case(CV_32F, mvSize, mSize, rng);
1034
res = curRes != cvtest::TS::OK ? curRes : res;
1035
1036
curRes = run_case(CV_64F, mvSize, mSize, rng);
1037
res = curRes != cvtest::TS::OK ? curRes : res;
1038
1039
ts->set_failed_test_info(res);
1040
}
1041
};
1042
1043
class Core_MergeTest : public Core_MergeSplitBaseTest
1044
{
1045
public:
1046
Core_MergeTest() {}
1047
~Core_MergeTest() {}
1048
1049
protected:
1050
virtual int run_case(int depth, size_t matCount, const Size& size, RNG& rng)
1051
{
1052
const int maxMatChannels = 10;
1053
1054
vector<Mat> src(matCount);
1055
int channels = 0;
1056
for(size_t i = 0; i < src.size(); i++)
1057
{
1058
Mat m(size, CV_MAKETYPE(depth, rng.uniform(1,maxMatChannels)));
1059
rng.fill(m, RNG::UNIFORM, 0, 100, true);
1060
channels += m.channels();
1061
src[i] = m;
1062
}
1063
1064
Mat dst;
1065
merge(src, dst);
1066
1067
// check result
1068
std::stringstream commonLog;
1069
commonLog << "Depth " << depth << " :";
1070
if(dst.depth() != depth)
1071
{
1072
ts->printf(cvtest::TS::LOG, "%s incorrect depth of dst (%d instead of %d)\n",
1073
commonLog.str().c_str(), dst.depth(), depth);
1074
return cvtest::TS::FAIL_INVALID_OUTPUT;
1075
}
1076
if(dst.size() != size)
1077
{
1078
ts->printf(cvtest::TS::LOG, "%s incorrect size of dst (%d x %d instead of %d x %d)\n",
1079
commonLog.str().c_str(), dst.rows, dst.cols, size.height, size.width);
1080
return cvtest::TS::FAIL_INVALID_OUTPUT;
1081
}
1082
if(dst.channels() != channels)
1083
{
1084
ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst (%d instead of %d)\n",
1085
commonLog.str().c_str(), dst.channels(), channels);
1086
return cvtest::TS::FAIL_INVALID_OUTPUT;
1087
}
1088
1089
int diffElemCount = calcDiffElemCount(src, dst);
1090
if(diffElemCount > 0)
1091
{
1092
ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n",
1093
commonLog.str().c_str(), static_cast<float>(diffElemCount)/(channels*size.area()));
1094
return cvtest::TS::FAIL_INVALID_OUTPUT;
1095
}
1096
1097
return cvtest::TS::OK;
1098
}
1099
};
1100
1101
class Core_SplitTest : public Core_MergeSplitBaseTest
1102
{
1103
public:
1104
Core_SplitTest() {}
1105
~Core_SplitTest() {}
1106
1107
protected:
1108
virtual int run_case(int depth, size_t channels, const Size& size, RNG& rng)
1109
{
1110
Mat src(size, CV_MAKETYPE(depth, (int)channels));
1111
rng.fill(src, RNG::UNIFORM, 0, 100, true);
1112
1113
vector<Mat> dst;
1114
split(src, dst);
1115
1116
// check result
1117
std::stringstream commonLog;
1118
commonLog << "Depth " << depth << " :";
1119
if(dst.size() != channels)
1120
{
1121
ts->printf(cvtest::TS::LOG, "%s incorrect count of matrices in dst (%d instead of %d)\n",
1122
commonLog.str().c_str(), dst.size(), channels);
1123
return cvtest::TS::FAIL_INVALID_OUTPUT;
1124
}
1125
for(size_t i = 0; i < dst.size(); i++)
1126
{
1127
if(dst[i].size() != size)
1128
{
1129
ts->printf(cvtest::TS::LOG, "%s incorrect size of dst[%d] (%d x %d instead of %d x %d)\n",
1130
commonLog.str().c_str(), i, dst[i].rows, dst[i].cols, size.height, size.width);
1131
return cvtest::TS::FAIL_INVALID_OUTPUT;
1132
}
1133
if(dst[i].depth() != depth)
1134
{
1135
ts->printf(cvtest::TS::LOG, "%s: incorrect depth of dst[%d] (%d instead of %d)\n",
1136
commonLog.str().c_str(), i, dst[i].depth(), depth);
1137
return cvtest::TS::FAIL_INVALID_OUTPUT;
1138
}
1139
if(dst[i].channels() != 1)
1140
{
1141
ts->printf(cvtest::TS::LOG, "%s: incorrect channels count of dst[%d] (%d instead of %d)\n",
1142
commonLog.str().c_str(), i, dst[i].channels(), 1);
1143
return cvtest::TS::FAIL_INVALID_OUTPUT;
1144
}
1145
}
1146
1147
int diffElemCount = calcDiffElemCount(dst, src);
1148
if(diffElemCount > 0)
1149
{
1150
ts->printf(cvtest::TS::LOG, "%s: there are incorrect elements in dst (part of them is %f)\n",
1151
commonLog.str().c_str(), static_cast<float>(diffElemCount)/(channels*size.area()));
1152
return cvtest::TS::FAIL_INVALID_OUTPUT;
1153
}
1154
1155
return cvtest::TS::OK;
1156
}
1157
};
1158
1159
TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); }
1160
TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); }
1161
1162
TEST(Core_Merge, shape_operations) { Core_MergeTest test; test.safe_run(); }
1163
TEST(Core_Split, shape_operations) { Core_SplitTest test; test.safe_run(); }
1164
1165
1166
TEST(Core_IOArray, submat_assignment)
1167
{
1168
Mat1f A = Mat1f::zeros(2,2);
1169
Mat1f B = Mat1f::ones(1,3);
1170
1171
EXPECT_THROW( B.colRange(0,3).copyTo(A.row(0)), cv::Exception );
1172
1173
EXPECT_NO_THROW( B.colRange(0,2).copyTo(A.row(0)) );
1174
1175
EXPECT_EQ( 1.0f, A(0,0) );
1176
EXPECT_EQ( 1.0f, A(0,1) );
1177
}
1178
1179
void OutputArray_create1(OutputArray m) { m.create(1, 2, CV_32S); }
1180
void OutputArray_create2(OutputArray m) { m.create(1, 3, CV_32F); }
1181
1182
TEST(Core_IOArray, submat_create)
1183
{
1184
Mat1f A = Mat1f::zeros(2,2);
1185
1186
EXPECT_THROW( OutputArray_create1(A.row(0)), cv::Exception );
1187
EXPECT_THROW( OutputArray_create2(A.row(0)), cv::Exception );
1188
}
1189
1190
TEST(Core_Mat, issue4457_pass_null_ptr)
1191
{
1192
ASSERT_ANY_THROW(cv::Mat mask(45, 45, CV_32F, 0));
1193
}
1194
1195
TEST(Core_Mat, reshape_1942)
1196
{
1197
cv::Mat A = (cv::Mat_<float>(2,3) << 3.4884074, 1.4159607, 0.78737736, 2.3456569, -0.88010466, 0.3009364);
1198
int cn = 0;
1199
ASSERT_NO_THROW(
1200
cv::Mat_<float> M = A.reshape(3);
1201
cn = M.channels();
1202
);
1203
ASSERT_EQ(1, cn);
1204
}
1205
1206
static void check_ndim_shape(const cv::Mat &mat, int cn, int ndims, const int *sizes)
1207
{
1208
EXPECT_EQ(mat.channels(), cn);
1209
EXPECT_EQ(mat.dims, ndims);
1210
1211
if (mat.dims != ndims)
1212
return;
1213
1214
for (int i = 0; i < ndims; i++)
1215
EXPECT_EQ(mat.size[i], sizes[i]);
1216
}
1217
1218
TEST(Core_Mat, reshape_ndims_2)
1219
{
1220
const cv::Mat A(8, 16, CV_8UC3);
1221
cv::Mat B;
1222
1223
{
1224
int new_sizes_mask[] = { 0, 3, 4, 4 };
1225
int new_sizes_real[] = { 8, 3, 4, 4 };
1226
ASSERT_NO_THROW(B = A.reshape(1, 4, new_sizes_mask));
1227
check_ndim_shape(B, 1, 4, new_sizes_real);
1228
}
1229
{
1230
int new_sizes[] = { 16, 8 };
1231
ASSERT_NO_THROW(B = A.reshape(0, 2, new_sizes));
1232
check_ndim_shape(B, 3, 2, new_sizes);
1233
EXPECT_EQ(B.rows, new_sizes[0]);
1234
EXPECT_EQ(B.cols, new_sizes[1]);
1235
}
1236
{
1237
int new_sizes[] = { 2, 5, 1, 3 };
1238
cv::Mat A_sliced = A(cv::Range::all(), cv::Range(0, 15));
1239
ASSERT_ANY_THROW(A_sliced.reshape(4, 4, new_sizes));
1240
}
1241
}
1242
1243
TEST(Core_Mat, reshape_ndims_4)
1244
{
1245
const int sizes[] = { 2, 6, 4, 12 };
1246
const cv::Mat A(4, sizes, CV_8UC3);
1247
cv::Mat B;
1248
1249
{
1250
int new_sizes_mask[] = { 0, 864 };
1251
int new_sizes_real[] = { 2, 864 };
1252
ASSERT_NO_THROW(B = A.reshape(1, 2, new_sizes_mask));
1253
check_ndim_shape(B, 1, 2, new_sizes_real);
1254
EXPECT_EQ(B.rows, new_sizes_real[0]);
1255
EXPECT_EQ(B.cols, new_sizes_real[1]);
1256
}
1257
{
1258
int new_sizes_mask[] = { 4, 0, 0, 2, 3 };
1259
int new_sizes_real[] = { 4, 6, 4, 2, 3 };
1260
ASSERT_NO_THROW(B = A.reshape(0, 5, new_sizes_mask));
1261
check_ndim_shape(B, 3, 5, new_sizes_real);
1262
}
1263
{
1264
int new_sizes_mask[] = { 1, 1 };
1265
ASSERT_ANY_THROW(A.reshape(0, 2, new_sizes_mask));
1266
}
1267
{
1268
int new_sizes_mask[] = { 4, 6, 3, 3, 0 };
1269
ASSERT_ANY_THROW(A.reshape(0, 5, new_sizes_mask));
1270
}
1271
}
1272
1273
TEST(Core_Mat, push_back)
1274
{
1275
Mat a = (Mat_<float>(1,2) << 3.4884074f, 1.4159607f);
1276
Mat b = (Mat_<float>(1,2) << 0.78737736f, 2.3456569f);
1277
1278
a.push_back(b);
1279
1280
ASSERT_EQ(2, a.cols);
1281
ASSERT_EQ(2, a.rows);
1282
1283
ASSERT_FLOAT_EQ(3.4884074f, a.at<float>(0, 0));
1284
ASSERT_FLOAT_EQ(1.4159607f, a.at<float>(0, 1));
1285
ASSERT_FLOAT_EQ(0.78737736f, a.at<float>(1, 0));
1286
ASSERT_FLOAT_EQ(2.3456569f, a.at<float>(1, 1));
1287
1288
Mat c = (Mat_<float>(2,2) << -0.88010466f, 0.3009364f, 2.22399974f, -5.45933905f);
1289
1290
ASSERT_EQ(c.rows, a.cols);
1291
1292
a.push_back(c.t());
1293
1294
ASSERT_EQ(2, a.cols);
1295
ASSERT_EQ(4, a.rows);
1296
1297
ASSERT_FLOAT_EQ(3.4884074f, a.at<float>(0, 0));
1298
ASSERT_FLOAT_EQ(1.4159607f, a.at<float>(0, 1));
1299
ASSERT_FLOAT_EQ(0.78737736f, a.at<float>(1, 0));
1300
ASSERT_FLOAT_EQ(2.3456569f, a.at<float>(1, 1));
1301
ASSERT_FLOAT_EQ(-0.88010466f, a.at<float>(2, 0));
1302
ASSERT_FLOAT_EQ(2.22399974f, a.at<float>(2, 1));
1303
ASSERT_FLOAT_EQ(0.3009364f, a.at<float>(3, 0));
1304
ASSERT_FLOAT_EQ(-5.45933905f, a.at<float>(3, 1));
1305
1306
a.push_back(Mat::ones(2, 2, CV_32FC1));
1307
1308
ASSERT_EQ(6, a.rows);
1309
1310
for(int row=4; row<a.rows; row++) {
1311
1312
for(int col=0; col<a.cols; col++) {
1313
1314
ASSERT_FLOAT_EQ(1.f, a.at<float>(row, col));
1315
}
1316
}
1317
}
1318
1319
TEST(Core_Mat, copyNx1ToVector)
1320
{
1321
cv::Mat_<uchar> src(5, 1);
1322
cv::Mat_<uchar> ref_dst8;
1323
cv::Mat_<ushort> ref_dst16;
1324
std::vector<uchar> dst8;
1325
std::vector<ushort> dst16;
1326
1327
src << 1, 2, 3, 4, 5;
1328
1329
src.copyTo(ref_dst8);
1330
src.copyTo(dst8);
1331
1332
ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst8, cv::Mat_<uchar>(dst8));
1333
1334
src.convertTo(ref_dst16, CV_16U);
1335
src.convertTo(dst16, CV_16U);
1336
1337
ASSERT_PRED_FORMAT2(cvtest::MatComparator(0, 0), ref_dst16, cv::Mat_<ushort>(dst16));
1338
}
1339
1340
TEST(Core_Matx, fromMat_)
1341
{
1342
Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
1343
Matx22d b(a);
1344
ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.);
1345
}
1346
1347
TEST(Core_Matx, from_initializer_list)
1348
{
1349
Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
1350
Matx22d b = {10, 11, 12, 13};
1351
ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.);
1352
}
1353
1354
TEST(Core_Mat, regression_9507)
1355
{
1356
cv::Mat m = Mat::zeros(5, 5, CV_8UC3);
1357
cv::Mat m2{m};
1358
EXPECT_EQ(25u, m2.total());
1359
}
1360
1361
TEST(Core_InputArray, empty)
1362
{
1363
vector<vector<Point> > data;
1364
ASSERT_TRUE( _InputArray(data).empty() );
1365
}
1366
1367
TEST(Core_CopyMask, bug1918)
1368
{
1369
Mat_<unsigned char> tmpSrc(100,100);
1370
tmpSrc = 124;
1371
Mat_<unsigned char> tmpMask(100,100);
1372
tmpMask = 255;
1373
Mat_<unsigned char> tmpDst(100,100);
1374
tmpDst = 2;
1375
tmpSrc.copyTo(tmpDst,tmpMask);
1376
ASSERT_EQ(sum(tmpDst)[0], 124*100*100);
1377
}
1378
1379
TEST(Core_SVD, orthogonality)
1380
{
1381
for( int i = 0; i < 2; i++ )
1382
{
1383
int type = i == 0 ? CV_32F : CV_64F;
1384
Mat mat_D(2, 2, type);
1385
mat_D.setTo(88.);
1386
Mat mat_U, mat_W;
1387
SVD::compute(mat_D, mat_W, mat_U, noArray(), SVD::FULL_UV);
1388
mat_U *= mat_U.t();
1389
ASSERT_LT(cvtest::norm(mat_U, Mat::eye(2, 2, type), NORM_INF), 1e-5);
1390
}
1391
}
1392
1393
1394
TEST(Core_SparseMat, footprint)
1395
{
1396
int n = 1000000;
1397
int sz[] = { n, n };
1398
SparseMat m(2, sz, CV_64F);
1399
1400
int nodeSize0 = (int)m.hdr->nodeSize;
1401
double dataSize0 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6;
1402
printf("before: node size=%d bytes, data size=%.0f Mbytes\n", nodeSize0, dataSize0);
1403
1404
for (int i = 0; i < n; i++)
1405
{
1406
m.ref<double>(i, i) = 1;
1407
}
1408
1409
double dataSize1 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6;
1410
double threshold = (n*nodeSize0*1.6 + n*2.*sizeof(size_t))*1e-6;
1411
printf("after: data size=%.0f Mbytes, threshold=%.0f MBytes\n", dataSize1, threshold);
1412
1413
ASSERT_LE((int)m.hdr->nodeSize, 32);
1414
ASSERT_LE(dataSize1, threshold);
1415
}
1416
1417
1418
// Can't fix without dirty hacks or broken user code (PR #4159)
1419
TEST(Core_Mat_vector, DISABLED_OutputArray_create_getMat)
1420
{
1421
cv::Mat_<uchar> src_base(5, 1);
1422
std::vector<uchar> dst8;
1423
1424
src_base << 1, 2, 3, 4, 5;
1425
1426
Mat src(src_base);
1427
OutputArray _dst(dst8);
1428
{
1429
_dst.create(src.rows, src.cols, src.type());
1430
Mat dst = _dst.getMat();
1431
EXPECT_EQ(src.dims, dst.dims);
1432
EXPECT_EQ(src.cols, dst.cols);
1433
EXPECT_EQ(src.rows, dst.rows);
1434
}
1435
}
1436
1437
TEST(Core_Mat_vector, copyTo_roi_column)
1438
{
1439
cv::Mat_<uchar> src_base(5, 2);
1440
std::vector<uchar> dst1;
1441
1442
src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1443
1444
Mat src_full(src_base);
1445
Mat src(src_full.col(0));
1446
#if 0 // Can't fix without dirty hacks or broken user code (PR #4159)
1447
OutputArray _dst(dst1);
1448
{
1449
_dst.create(src.rows, src.cols, src.type());
1450
Mat dst = _dst.getMat();
1451
EXPECT_EQ(src.dims, dst.dims);
1452
EXPECT_EQ(src.cols, dst.cols);
1453
EXPECT_EQ(src.rows, dst.rows);
1454
}
1455
#endif
1456
1457
std::vector<uchar> dst2;
1458
src.copyTo(dst2);
1459
std::cout << "src = " << src << std::endl;
1460
std::cout << "dst = " << Mat(dst2) << std::endl;
1461
EXPECT_EQ((size_t)5, dst2.size());
1462
EXPECT_EQ(1, (int)dst2[0]);
1463
EXPECT_EQ(3, (int)dst2[1]);
1464
EXPECT_EQ(5, (int)dst2[2]);
1465
EXPECT_EQ(7, (int)dst2[3]);
1466
EXPECT_EQ(9, (int)dst2[4]);
1467
}
1468
1469
TEST(Core_Mat_vector, copyTo_roi_row)
1470
{
1471
cv::Mat_<uchar> src_base(2, 5);
1472
std::vector<uchar> dst1;
1473
1474
src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1475
1476
Mat src_full(src_base);
1477
Mat src(src_full.row(0));
1478
OutputArray _dst(dst1);
1479
{
1480
_dst.create(src.rows, src.cols, src.type());
1481
Mat dst = _dst.getMat();
1482
EXPECT_EQ(src.dims, dst.dims);
1483
EXPECT_EQ(src.cols, dst.cols);
1484
EXPECT_EQ(src.rows, dst.rows);
1485
}
1486
1487
std::vector<uchar> dst2;
1488
src.copyTo(dst2);
1489
std::cout << "src = " << src << std::endl;
1490
std::cout << "dst = " << Mat(dst2) << std::endl;
1491
EXPECT_EQ((size_t)5, dst2.size());
1492
EXPECT_EQ(1, (int)dst2[0]);
1493
EXPECT_EQ(2, (int)dst2[1]);
1494
EXPECT_EQ(3, (int)dst2[2]);
1495
EXPECT_EQ(4, (int)dst2[3]);
1496
EXPECT_EQ(5, (int)dst2[4]);
1497
}
1498
1499
TEST(Mat, regression_5991)
1500
{
1501
int sz[] = {2,3,2};
1502
Mat mat(3, sz, CV_32F, Scalar(1));
1503
ASSERT_NO_THROW(mat.convertTo(mat, CV_8U));
1504
EXPECT_EQ(sz[0], mat.size[0]);
1505
EXPECT_EQ(sz[1], mat.size[1]);
1506
EXPECT_EQ(sz[2], mat.size[2]);
1507
EXPECT_EQ(0, cvtest::norm(mat, Mat(3, sz, CV_8U, Scalar(1)), NORM_INF));
1508
}
1509
1510
TEST(Mat, regression_9720)
1511
{
1512
Mat mat(1, 1, CV_32FC1);
1513
mat.at<float>(0) = 1.f;
1514
const float a = 0.1f;
1515
Mat me1 = (Mat)(mat.mul((a / mat)));
1516
Mat me2 = (Mat)(mat.mul((Mat)(a / mat)));
1517
Mat me3 = (Mat)(mat.mul((a * mat)));
1518
Mat me4 = (Mat)(mat.mul((Mat)(a * mat)));
1519
EXPECT_EQ(me1.at<float>(0), me2.at<float>(0));
1520
EXPECT_EQ(me3.at<float>(0), me4.at<float>(0));
1521
}
1522
1523
#ifdef OPENCV_TEST_BIGDATA
1524
TEST(Mat, regression_6696_BigData_8Gb)
1525
{
1526
int width = 60000;
1527
int height = 10000;
1528
1529
Mat destImageBGR = Mat(height, width, CV_8UC3, Scalar(1, 2, 3, 0));
1530
Mat destImageA = Mat(height, width, CV_8UC1, Scalar::all(4));
1531
1532
vector<Mat> planes;
1533
split(destImageBGR, planes);
1534
planes.push_back(destImageA);
1535
merge(planes, destImageBGR);
1536
1537
EXPECT_EQ(1, destImageBGR.at<Vec4b>(0)[0]);
1538
EXPECT_EQ(2, destImageBGR.at<Vec4b>(0)[1]);
1539
EXPECT_EQ(3, destImageBGR.at<Vec4b>(0)[2]);
1540
EXPECT_EQ(4, destImageBGR.at<Vec4b>(0)[3]);
1541
1542
EXPECT_EQ(1, destImageBGR.at<Vec4b>(height-1, width-1)[0]);
1543
EXPECT_EQ(2, destImageBGR.at<Vec4b>(height-1, width-1)[1]);
1544
EXPECT_EQ(3, destImageBGR.at<Vec4b>(height-1, width-1)[2]);
1545
EXPECT_EQ(4, destImageBGR.at<Vec4b>(height-1, width-1)[3]);
1546
}
1547
#endif
1548
1549
TEST(Reduce, regression_should_fail_bug_4594)
1550
{
1551
cv::Mat src = cv::Mat::eye(4, 4, CV_8U);
1552
std::vector<int> dst;
1553
1554
EXPECT_THROW(cv::reduce(src, dst, 0, CV_REDUCE_MIN, CV_32S), cv::Exception);
1555
EXPECT_THROW(cv::reduce(src, dst, 0, CV_REDUCE_MAX, CV_32S), cv::Exception);
1556
EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_SUM, CV_32S));
1557
EXPECT_NO_THROW(cv::reduce(src, dst, 0, CV_REDUCE_AVG, CV_32S));
1558
}
1559
1560
TEST(Mat, push_back_vector)
1561
{
1562
cv::Mat result(1, 5, CV_32FC1);
1563
1564
std::vector<float> vec1(result.cols + 1);
1565
std::vector<int> vec2(result.cols);
1566
1567
EXPECT_THROW(result.push_back(vec1), cv::Exception);
1568
EXPECT_THROW(result.push_back(vec2), cv::Exception);
1569
1570
vec1.resize(result.cols);
1571
1572
for (int i = 0; i < 5; ++i)
1573
result.push_back(cv::Mat(vec1).reshape(1, 1));
1574
1575
ASSERT_EQ(6, result.rows);
1576
}
1577
1578
TEST(Mat, regression_5917_clone_empty)
1579
{
1580
Mat cloned;
1581
Mat_<Point2f> source(5, 0);
1582
1583
ASSERT_NO_THROW(cloned = source.clone());
1584
}
1585
1586
TEST(Mat, regression_7873_mat_vector_initialize)
1587
{
1588
std::vector<int> dims;
1589
dims.push_back(12);
1590
dims.push_back(3);
1591
dims.push_back(2);
1592
Mat multi_mat(dims, CV_32FC1, cv::Scalar(0));
1593
1594
ASSERT_EQ(3, multi_mat.dims);
1595
ASSERT_EQ(12, multi_mat.size[0]);
1596
ASSERT_EQ(3, multi_mat.size[1]);
1597
ASSERT_EQ(2, multi_mat.size[2]);
1598
1599
std::vector<Range> ranges;
1600
ranges.push_back(Range(1, 2));
1601
ranges.push_back(Range::all());
1602
ranges.push_back(Range::all());
1603
Mat sub_mat = multi_mat(ranges);
1604
1605
ASSERT_EQ(3, sub_mat.dims);
1606
ASSERT_EQ(1, sub_mat.size[0]);
1607
ASSERT_EQ(3, sub_mat.size[1]);
1608
ASSERT_EQ(2, sub_mat.size[2]);
1609
}
1610
1611
TEST(Mat, regression_10507_mat_setTo)
1612
{
1613
Size sz(6, 4);
1614
Mat test_mask(sz, CV_8UC1, cv::Scalar::all(255));
1615
test_mask.at<uchar>(1,0) = 0;
1616
test_mask.at<uchar>(0,1) = 0;
1617
for (int cn = 1; cn <= 4; cn++)
1618
{
1619
cv::Mat A(sz, CV_MAKE_TYPE(CV_32F, cn), cv::Scalar::all(5));
1620
A.setTo(cv::Scalar::all(std::numeric_limits<float>::quiet_NaN()), test_mask);
1621
int nans = 0;
1622
for (int y = 0; y < A.rows; y++)
1623
{
1624
for (int x = 0; x < A.cols; x++)
1625
{
1626
for (int c = 0; c < cn; c++)
1627
{
1628
float v = A.ptr<float>(y, x)[c];
1629
nans += (v == v) ? 0 : 1;
1630
}
1631
}
1632
}
1633
EXPECT_EQ(nans, cn * (sz.area() - 2)) << "A=" << A << std::endl << "mask=" << test_mask << std::endl;
1634
}
1635
}
1636
1637
TEST(Core_Mat_array, outputArray_create_getMat)
1638
{
1639
cv::Mat_<uchar> src_base(5, 1);
1640
std::array<uchar, 5> dst8;
1641
1642
src_base << 1, 2, 3, 4, 5;
1643
1644
Mat src(src_base);
1645
OutputArray _dst(dst8);
1646
1647
{
1648
_dst.create(src.rows, src.cols, src.type());
1649
Mat dst = _dst.getMat();
1650
EXPECT_EQ(src.dims, dst.dims);
1651
EXPECT_EQ(src.cols, dst.cols);
1652
EXPECT_EQ(src.rows, dst.rows);
1653
}
1654
}
1655
1656
TEST(Core_Mat_array, copyTo_roi_column)
1657
{
1658
cv::Mat_<uchar> src_base(5, 2);
1659
1660
src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1661
1662
Mat src_full(src_base);
1663
Mat src(src_full.col(0));
1664
1665
std::array<uchar, 5> dst1;
1666
src.copyTo(dst1);
1667
std::cout << "src = " << src << std::endl;
1668
std::cout << "dst = " << Mat(dst1) << std::endl;
1669
EXPECT_EQ((size_t)5, dst1.size());
1670
EXPECT_EQ(1, (int)dst1[0]);
1671
EXPECT_EQ(3, (int)dst1[1]);
1672
EXPECT_EQ(5, (int)dst1[2]);
1673
EXPECT_EQ(7, (int)dst1[3]);
1674
EXPECT_EQ(9, (int)dst1[4]);
1675
}
1676
1677
TEST(Core_Mat_array, copyTo_roi_row)
1678
{
1679
cv::Mat_<uchar> src_base(2, 5);
1680
std::array<uchar, 5> dst1;
1681
1682
src_base << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
1683
1684
Mat src_full(src_base);
1685
Mat src(src_full.row(0));
1686
OutputArray _dst(dst1);
1687
{
1688
_dst.create(5, 1, src.type());
1689
Mat dst = _dst.getMat();
1690
EXPECT_EQ(src.dims, dst.dims);
1691
EXPECT_EQ(1, dst.cols);
1692
EXPECT_EQ(5, dst.rows);
1693
}
1694
1695
std::array<uchar, 5> dst2;
1696
src.copyTo(dst2);
1697
std::cout << "src = " << src << std::endl;
1698
std::cout << "dst = " << Mat(dst2) << std::endl;
1699
EXPECT_EQ(1, (int)dst2[0]);
1700
EXPECT_EQ(2, (int)dst2[1]);
1701
EXPECT_EQ(3, (int)dst2[2]);
1702
EXPECT_EQ(4, (int)dst2[3]);
1703
EXPECT_EQ(5, (int)dst2[4]);
1704
}
1705
1706
TEST(Core_Mat_array, SplitMerge)
1707
{
1708
std::array<cv::Mat, 3> src;
1709
for (size_t i = 0; i < src.size(); ++i)
1710
{
1711
src[i] = Mat(10, 10, CV_8U, Scalar((double)(16 * (i + 1))));
1712
}
1713
1714
Mat merged;
1715
merge(src, merged);
1716
1717
std::array<cv::Mat, 3> dst;
1718
split(merged, dst);
1719
1720
for (size_t i = 0; i < dst.size(); ++i)
1721
{
1722
EXPECT_EQ(0, cvtest::norm(src[i], dst[i], NORM_INF));
1723
}
1724
}
1725
1726
TEST(Mat, regression_8680)
1727
{
1728
Mat_<Point2i> mat(3,1);
1729
ASSERT_EQ(mat.channels(), 2);
1730
mat.release();
1731
ASSERT_EQ(mat.channels(), 2);
1732
}
1733
1734
TEST(Mat_, range_based_for)
1735
{
1736
Mat_<uchar> img = Mat_<uchar>::zeros(3, 3);
1737
1738
for(auto& pixel : img)
1739
{
1740
pixel = 1;
1741
}
1742
1743
Mat_<uchar> ref(3, 3);
1744
ref.setTo(Scalar(1));
1745
ASSERT_DOUBLE_EQ(cvtest::norm(img, ref, NORM_INF), 0.);
1746
}
1747
1748
TEST(Mat, from_initializer_list)
1749
{
1750
Mat A({1.f, 2.f, 3.f});
1751
Mat_<float> B(3, 1); B << 1, 2, 3;
1752
Mat_<float> C({3}, {1,2,3});
1753
1754
ASSERT_EQ(A.type(), CV_32F);
1755
ASSERT_DOUBLE_EQ(cvtest::norm(A, B, NORM_INF), 0.);
1756
ASSERT_DOUBLE_EQ(cvtest::norm(A, C, NORM_INF), 0.);
1757
ASSERT_DOUBLE_EQ(cvtest::norm(B, C, NORM_INF), 0.);
1758
1759
auto D = Mat_<double>({2, 3}, {1, 2, 3, 4, 5, 6});
1760
EXPECT_EQ(2, D.rows);
1761
EXPECT_EQ(3, D.cols);
1762
}
1763
1764
TEST(Mat_, from_initializer_list)
1765
{
1766
Mat_<float> A = {1, 2, 3};
1767
Mat_<float> B(3, 1); B << 1, 2, 3;
1768
Mat_<float> C({3}, {1,2,3});
1769
1770
ASSERT_DOUBLE_EQ(cvtest::norm(A, B, NORM_INF), 0.);
1771
ASSERT_DOUBLE_EQ(cvtest::norm(A, C, NORM_INF), 0.);
1772
ASSERT_DOUBLE_EQ(cvtest::norm(B, C, NORM_INF), 0.);
1773
}
1774
1775
1776
TEST(Mat, template_based_ptr)
1777
{
1778
Mat mat = (Mat_<float>(2, 2) << 11.0f, 22.0f, 33.0f, 44.0f);
1779
int idx[2] = {1, 0};
1780
ASSERT_FLOAT_EQ(33.0f, *(mat.ptr<float>(idx)));
1781
idx[0] = 1;
1782
idx[1] = 1;
1783
ASSERT_FLOAT_EQ(44.0f, *(mat.ptr<float>(idx)));
1784
}
1785
1786
TEST(Mat_, template_based_ptr)
1787
{
1788
int dim[4] = {2, 2, 1, 2};
1789
Mat_<float> mat = (Mat_<float>(4, dim) << 11.0f, 22.0f, 33.0f, 44.0f,
1790
55.0f, 66.0f, 77.0f, 88.0f);
1791
int idx[4] = {1, 0, 0, 1};
1792
ASSERT_FLOAT_EQ(66.0f, *(mat.ptr<float>(idx)));
1793
}
1794
1795
1796
BIGDATA_TEST(Mat, push_back_regression_4158) // memory usage: ~10.6 Gb
1797
{
1798
Mat result;
1799
1800
Mat tail(100, 500000, CV_32FC2, Scalar(1, 2));
1801
1802
tail.copyTo(result);
1803
for (int i = 1; i < 15; i++)
1804
{
1805
result.push_back(tail);
1806
std::cout << "i = " << i << " result = " << result.size() << " used = " << (uint64)result.total()*result.elemSize()*(1.0 / (1 << 20)) << " Mb"
1807
<< " allocated=" << (uint64)(result.datalimit - result.datastart)*(1.0 / (1 << 20)) << " Mb" << std::endl;
1808
}
1809
for (int i = 0; i < 15; i++)
1810
{
1811
Rect roi(0, tail.rows * i, tail.cols, tail.rows);
1812
int nz = countNonZero(result(roi).reshape(1) == 2);
1813
EXPECT_EQ(tail.total(), (size_t)nz) << "i=" << i;
1814
}
1815
}
1816
1817
1818
TEST(Core_Merge, hang_12171)
1819
{
1820
Mat src1(4, 24, CV_8UC1, Scalar::all(1));
1821
Mat src2(4, 24, CV_8UC1, Scalar::all(2));
1822
Rect src_roi(0, 0, 23, 4);
1823
Mat src_channels[2] = { src1(src_roi), src2(src_roi) };
1824
Mat dst(4, 24, CV_8UC2, Scalar::all(5));
1825
Rect dst_roi(1, 0, 23, 4);
1826
cv::merge(src_channels, 2, dst(dst_roi));
1827
EXPECT_EQ(5, dst.ptr<uchar>()[0]);
1828
EXPECT_EQ(5, dst.ptr<uchar>()[1]);
1829
EXPECT_EQ(1, dst.ptr<uchar>()[2]);
1830
EXPECT_EQ(2, dst.ptr<uchar>()[3]);
1831
EXPECT_EQ(5, dst.ptr<uchar>(1)[0]);
1832
EXPECT_EQ(5, dst.ptr<uchar>(1)[1]);
1833
EXPECT_EQ(1, dst.ptr<uchar>(1)[2]);
1834
EXPECT_EQ(2, dst.ptr<uchar>(1)[3]);
1835
}
1836
1837
TEST(Core_Split, hang_12171)
1838
{
1839
Mat src(4, 24, CV_8UC2, Scalar(1,2,3,4));
1840
Rect src_roi(0, 0, 23, 4);
1841
Mat dst1(4, 24, CV_8UC1, Scalar::all(5));
1842
Mat dst2(4, 24, CV_8UC1, Scalar::all(10));
1843
Rect dst_roi(0, 0, 23, 4);
1844
Mat dst[2] = { dst1(dst_roi), dst2(dst_roi) };
1845
cv::split(src(src_roi), dst);
1846
EXPECT_EQ(1, dst1.ptr<uchar>()[0]);
1847
EXPECT_EQ(1, dst1.ptr<uchar>()[1]);
1848
EXPECT_EQ(2, dst2.ptr<uchar>()[0]);
1849
EXPECT_EQ(2, dst2.ptr<uchar>()[1]);
1850
EXPECT_EQ(1, dst1.ptr<uchar>(1)[0]);
1851
EXPECT_EQ(1, dst1.ptr<uchar>(1)[1]);
1852
EXPECT_EQ(2, dst2.ptr<uchar>(1)[0]);
1853
EXPECT_EQ(2, dst2.ptr<uchar>(1)[1]);
1854
}
1855
1856
TEST(Core_Split, crash_12171)
1857
{
1858
Mat src(4, 40, CV_8UC2, Scalar(1,2,3,4));
1859
Rect src_roi(0, 0, 39, 4);
1860
Mat dst1(4, 40, CV_8UC1, Scalar::all(5));
1861
Mat dst2(4, 40, CV_8UC1, Scalar::all(10));
1862
Rect dst_roi(0, 0, 39, 4);
1863
Mat dst[2] = { dst1(dst_roi), dst2(dst_roi) };
1864
cv::split(src(src_roi), dst);
1865
EXPECT_EQ(1, dst1.ptr<uchar>()[0]);
1866
EXPECT_EQ(1, dst1.ptr<uchar>()[1]);
1867
EXPECT_EQ(2, dst2.ptr<uchar>()[0]);
1868
EXPECT_EQ(2, dst2.ptr<uchar>()[1]);
1869
EXPECT_EQ(1, dst1.ptr<uchar>(1)[0]);
1870
EXPECT_EQ(1, dst1.ptr<uchar>(1)[1]);
1871
EXPECT_EQ(2, dst2.ptr<uchar>(1)[0]);
1872
EXPECT_EQ(2, dst2.ptr<uchar>(1)[1]);
1873
}
1874
1875
struct CustomType // like cv::Keypoint
1876
{
1877
Point2f pt;
1878
float size;
1879
float angle;
1880
float response;
1881
int octave;
1882
int class_id;
1883
};
1884
1885
static void test_CustomType(InputArray src_, OutputArray dst_)
1886
{
1887
Mat src = src_.getMat();
1888
ASSERT_EQ(sizeof(CustomType), src.elemSize());
1889
CV_CheckTypeEQ(src.type(), CV_MAKETYPE(CV_8U, sizeof(CustomType)), "");
1890
1891
CustomType* kpt = NULL;
1892
{
1893
Mat dst = dst_.getMat();
1894
for (size_t i = 0; i < dst.total(); i++)
1895
{
1896
kpt = dst.ptr<CustomType>(0) + i;
1897
kpt->octave = (int)i;
1898
}
1899
}
1900
const int N = (int)src.total();
1901
dst_.create(1, N * 2, rawType<CustomType>());
1902
Mat dst = dst_.getMat();
1903
for (size_t i = N; i < dst.total(); i++)
1904
{
1905
kpt = dst.ptr<CustomType>(0) + i;
1906
kpt->octave = -(int)i;
1907
}
1908
#if 0 // Compilation error
1909
CustomType& kpt = dst.at<CustomType>(0, 5);
1910
#endif
1911
}
1912
1913
TEST(Core_InputArray, support_CustomType)
1914
{
1915
std::vector<CustomType> kp1(5);
1916
std::vector<CustomType> kp2(3);
1917
test_CustomType(rawIn(kp1), rawOut(kp2));
1918
ASSERT_EQ((size_t)10, kp2.size());
1919
for (int i = 0; i < 3; i++)
1920
{
1921
EXPECT_EQ(i, kp2[i].octave);
1922
}
1923
for (int i = 3; i < 5; i++)
1924
{
1925
EXPECT_EQ(0, kp2[i].octave);
1926
}
1927
for (int i = 5; i < 10; i++)
1928
{
1929
EXPECT_EQ(-i, kp2[i].octave);
1930
}
1931
}
1932
1933
1934
}} // namespace
1935
1936