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