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