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: 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> 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 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 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 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 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 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 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: 292 Core_PCATest() {} 293 protected: 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 552 Core_ArrayOpTest::Core_ArrayOpTest() 553 { 554 } 555 Core_ArrayOpTest::~Core_ArrayOpTest() {} 556 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 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 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 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 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 625 static void eraseValue(CvSparseMat* M, const int* idx) 626 { 627 cvClearND(M, idx); 628 } 629 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 655 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 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> 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 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 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: 1036 Core_MergeTest() {} 1037 ~Core_MergeTest() {} 1038 1039 protected: 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: 1094 Core_SplitTest() {} 1095 ~Core_SplitTest() {} 1096 1097 protected: 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 1149 TEST(Core_PCA, accuracy) { Core_PCATest test; test.safe_run(); } 1150 TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); } 1151 TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); } 1152 1153 TEST(Core_Merge, shape_operations) { Core_MergeTest test; test.safe_run(); } 1154 TEST(Core_Split, shape_operations) { Core_SplitTest test; test.safe_run(); } 1155 1156 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 1170 void OutputArray_create1(OutputArray m) { m.create(1, 2, CV_32S); } 1171 void OutputArray_create2(OutputArray m) { m.create(1, 3, CV_32F); } 1172 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 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 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 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 1220 TEST(Core_InputArray, empty) 1221 { 1222 vector<vector<Point> > data; 1223 ASSERT_TRUE( _InputArray(data).empty() ); 1224 } 1225 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 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 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