|
|
|
@ -286,13 +286,8 @@ void Core_ReduceTest::run( int ) |
|
|
|
|
|
|
|
|
|
#define CHECK_C |
|
|
|
|
|
|
|
|
|
class Core_PCATest : public cvtest::BaseTest |
|
|
|
|
TEST(Core_PCA, accuracy) |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
Core_PCATest() {} |
|
|
|
|
protected: |
|
|
|
|
void run(int) |
|
|
|
|
{ |
|
|
|
|
const Size sz(200, 500); |
|
|
|
|
|
|
|
|
|
double diffPrjEps, diffBackPrjEps, |
|
|
|
@ -301,7 +296,7 @@ protected: |
|
|
|
|
int maxComponents = 100; |
|
|
|
|
double retainedVariance = 0.95; |
|
|
|
|
Mat rPoints(sz, CV_32FC1), rTestPoints(sz, CV_32FC1); |
|
|
|
|
RNG& rng = ts->get_rng(); |
|
|
|
|
RNG rng(12345); |
|
|
|
|
|
|
|
|
|
rng.fill( rPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) ); |
|
|
|
|
rng.fill( rTestPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) ); |
|
|
|
@ -326,13 +321,13 @@ protected: |
|
|
|
|
Mat subEval( maxComponents, 1, eval.type(), eval.ptr() ), |
|
|
|
|
subEvec( maxComponents, evec.cols, evec.type(), evec.ptr() ); |
|
|
|
|
|
|
|
|
|
#ifdef CHECK_C |
|
|
|
|
#ifdef CHECK_C |
|
|
|
|
Mat prjTestPoints, backPrjTestPoints, cPoints = rPoints.t(), cTestPoints = rTestPoints.t(); |
|
|
|
|
CvMat _points, _testPoints, _avg, _eval, _evec, _prjTestPoints, _backPrjTestPoints; |
|
|
|
|
#endif |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// check eigen()
|
|
|
|
|
double eigenEps = 1e-6; |
|
|
|
|
double eigenEps = 1e-4; |
|
|
|
|
double err; |
|
|
|
|
for(int i = 0; i < Q.rows; i++ ) |
|
|
|
|
{ |
|
|
|
@ -340,47 +335,37 @@ protected: |
|
|
|
|
Mat Qv = Q * v; |
|
|
|
|
|
|
|
|
|
Mat lv = eval.at<float>(i,0) * v; |
|
|
|
|
err = cvtest::norm( Qv, lv, NORM_L2 ); |
|
|
|
|
if( err > eigenEps ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of eigen(); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
err = cvtest::norm(Qv, lv, NORM_L2 | NORM_RELATIVE); |
|
|
|
|
EXPECT_LE(err, eigenEps) << "bad accuracy of eigen(); i = " << i; |
|
|
|
|
} |
|
|
|
|
// check pca eigenvalues
|
|
|
|
|
evalEps = 1e-6, evecEps = 1e-3; |
|
|
|
|
err = cvtest::norm( rPCA.eigenvalues, subEval, NORM_L2 ); |
|
|
|
|
if( err > evalEps ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "pca.eigenvalues is incorrect (CV_PCA_DATA_AS_ROW); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
evalEps = 1e-5, evecEps = 5e-3; |
|
|
|
|
err = cvtest::norm(rPCA.eigenvalues, subEval, NORM_L2 | NORM_RELATIVE); |
|
|
|
|
EXPECT_LE(err , evalEps) << "pca.eigenvalues is incorrect (CV_PCA_DATA_AS_ROW)"; |
|
|
|
|
// check pca eigenvectors
|
|
|
|
|
for(int i = 0; i < subEvec.rows; i++) |
|
|
|
|
{ |
|
|
|
|
Mat r0 = rPCA.eigenvectors.row(i); |
|
|
|
|
Mat r1 = subEvec.row(i); |
|
|
|
|
err = cvtest::norm( r0, r1, CV_L2 ); |
|
|
|
|
if( err > evecEps ) |
|
|
|
|
{ |
|
|
|
|
r1 *= -1; |
|
|
|
|
double err2 = cvtest::norm(r0, r1, CV_L2); |
|
|
|
|
if( err2 > evecEps ) |
|
|
|
|
// eigenvectors have normalized length, but both directions v and -v are valid
|
|
|
|
|
double err1 = cvtest::norm(r0, r1, NORM_L2 | NORM_RELATIVE); |
|
|
|
|
double err2 = cvtest::norm(r0, -r1, NORM_L2 | NORM_RELATIVE); |
|
|
|
|
err = std::min(err1, err2); |
|
|
|
|
if (err > evecEps) |
|
|
|
|
{ |
|
|
|
|
Mat tmp; |
|
|
|
|
absdiff(rPCA.eigenvectors, subEvec, tmp); |
|
|
|
|
double mval = 0; Point mloc; |
|
|
|
|
minMaxLoc(tmp, 0, &mval, 0, &mloc); |
|
|
|
|
|
|
|
|
|
ts->printf( cvtest::TS::LOG, "pca.eigenvectors is incorrect (CV_PCA_DATA_AS_ROW); err = %f\n", err ); |
|
|
|
|
ts->printf( cvtest::TS::LOG, "max diff is %g at (i=%d, j=%d) (%g vs %g)\n", |
|
|
|
|
EXPECT_LE(err, evecEps) << "pca.eigenvectors is incorrect (CV_PCA_DATA_AS_ROW) at " << i << " " |
|
|
|
|
<< cv::format("max diff is %g at (i=%d, j=%d) (%g vs %g)\n", |
|
|
|
|
mval, mloc.y, mloc.x, rPCA.eigenvectors.at<float>(mloc.y, mloc.x), |
|
|
|
|
subEvec.at<float>(mloc.y, mloc.x)); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
subEvec.at<float>(mloc.y, mloc.x)) |
|
|
|
|
<< "r0=" << r0 << std::endl |
|
|
|
|
<< "r1=" << r1 << std::endl |
|
|
|
|
<< "err1=" << err1 << " err2=" << err2 |
|
|
|
|
; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -390,21 +375,19 @@ protected: |
|
|
|
|
// check pca project
|
|
|
|
|
Mat subEvec_t = subEvec.t(); |
|
|
|
|
Mat prj = rTestPoints.row(i) - avg; prj *= subEvec_t; |
|
|
|
|
err = cvtest::norm(rPrjTestPoints.row(i), prj, CV_RELATIVE_L2); |
|
|
|
|
if( err > prjEps ) |
|
|
|
|
err = cvtest::norm(rPrjTestPoints.row(i), prj, NORM_L2 | NORM_RELATIVE); |
|
|
|
|
if (err < prjEps) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_ROW); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
EXPECT_LE(err, prjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_ROW)"; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
// check pca backProject
|
|
|
|
|
Mat backPrj = rPrjTestPoints.row(i) * subEvec + avg; |
|
|
|
|
err = cvtest::norm( rBackPrjTestPoints.row(i), backPrj, CV_RELATIVE_L2 ); |
|
|
|
|
if( err > backPrjEps ) |
|
|
|
|
err = cvtest::norm(rBackPrjTestPoints.row(i), backPrj, NORM_L2 | NORM_RELATIVE); |
|
|
|
|
if (err > backPrjEps) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_ROW); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
EXPECT_LE(err, backPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_ROW)"; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -412,20 +395,10 @@ protected: |
|
|
|
|
cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, maxComponents ); |
|
|
|
|
diffPrjEps = 1, diffBackPrjEps = 1; |
|
|
|
|
Mat ocvPrjTestPoints = cPCA.project(rTestPoints.t()); |
|
|
|
|
err = cvtest::norm(cv::abs(ocvPrjTestPoints), cv::abs(rPrjTestPoints.t()), CV_RELATIVE_L2 ); |
|
|
|
|
if( err > diffPrjEps ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_COL); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
err = cvtest::norm(cPCA.backProject(ocvPrjTestPoints), rBackPrjTestPoints.t(), CV_RELATIVE_L2 ); |
|
|
|
|
if( err > diffBackPrjEps ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
err = cvtest::norm(cv::abs(ocvPrjTestPoints), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE); |
|
|
|
|
ASSERT_LE(err, diffPrjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_COL)"; |
|
|
|
|
err = cvtest::norm(cPCA.backProject(ocvPrjTestPoints), rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE); |
|
|
|
|
ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_COL)"; |
|
|
|
|
|
|
|
|
|
// 3. check C++ PCA w/retainedVariance
|
|
|
|
|
cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, retainedVariance ); |
|
|
|
@ -433,25 +406,15 @@ protected: |
|
|
|
|
Mat rvPrjTestPoints = cPCA.project(rTestPoints.t()); |
|
|
|
|
|
|
|
|
|
if( cPCA.eigenvectors.rows > maxComponents) |
|
|
|
|
err = cvtest::norm(cv::abs(rvPrjTestPoints.rowRange(0,maxComponents)), cv::abs(rPrjTestPoints.t()), CV_RELATIVE_L2 ); |
|
|
|
|
err = cvtest::norm(cv::abs(rvPrjTestPoints.rowRange(0,maxComponents)), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE); |
|
|
|
|
else |
|
|
|
|
err = cvtest::norm(cv::abs(rvPrjTestPoints), cv::abs(rPrjTestPoints.colRange(0,cPCA.eigenvectors.rows).t()), CV_RELATIVE_L2 ); |
|
|
|
|
err = cvtest::norm(cv::abs(rvPrjTestPoints), cv::abs(rPrjTestPoints.colRange(0,cPCA.eigenvectors.rows).t()), NORM_L2 | NORM_RELATIVE); |
|
|
|
|
|
|
|
|
|
if( err > diffPrjEps ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_COL); retainedVariance=0.95; err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
err = cvtest::norm(cPCA.backProject(rvPrjTestPoints), rBackPrjTestPoints.t(), CV_RELATIVE_L2 ); |
|
|
|
|
if( err > diffBackPrjEps ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); retainedVariance=0.95; err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
ASSERT_LE(err, diffPrjEps) << "bad accuracy of project() (CV_PCA_DATA_AS_COL); retainedVariance=" << retainedVariance; |
|
|
|
|
err = cvtest::norm(cPCA.backProject(rvPrjTestPoints), rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE); |
|
|
|
|
ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); retainedVariance=" << retainedVariance; |
|
|
|
|
|
|
|
|
|
#ifdef CHECK_C |
|
|
|
|
#ifdef CHECK_C |
|
|
|
|
// 4. check C PCA & ROW
|
|
|
|
|
_points = rPoints; |
|
|
|
|
_testPoints = rTestPoints; |
|
|
|
@ -467,20 +430,10 @@ protected: |
|
|
|
|
cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints ); |
|
|
|
|
cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints ); |
|
|
|
|
|
|
|
|
|
err = cvtest::norm(prjTestPoints, rPrjTestPoints, CV_RELATIVE_L2); |
|
|
|
|
if( err > diffPrjEps ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints, CV_RELATIVE_L2); |
|
|
|
|
if( err > diffBackPrjEps ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
err = cvtest::norm(prjTestPoints, rPrjTestPoints, NORM_L2 | NORM_RELATIVE); |
|
|
|
|
ASSERT_LE(err, diffPrjEps) << "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_ROW)"; |
|
|
|
|
err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints, NORM_L2 | NORM_RELATIVE); |
|
|
|
|
ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_ROW)"; |
|
|
|
|
|
|
|
|
|
// 5. check C PCA & COL
|
|
|
|
|
_points = cPoints; |
|
|
|
@ -495,21 +448,11 @@ protected: |
|
|
|
|
cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints ); |
|
|
|
|
cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints ); |
|
|
|
|
|
|
|
|
|
err = cvtest::norm(cv::abs(prjTestPoints), cv::abs(rPrjTestPoints.t()), CV_RELATIVE_L2 ); |
|
|
|
|
if( err > diffPrjEps ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_COL); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints.t(), CV_RELATIVE_L2); |
|
|
|
|
if( err > diffBackPrjEps ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_COL); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
err = cvtest::norm(cv::abs(prjTestPoints), cv::abs(rPrjTestPoints.t()), NORM_L2 | NORM_RELATIVE); |
|
|
|
|
ASSERT_LE(err, diffPrjEps) << "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_COL)"; |
|
|
|
|
err = cvtest::norm(backPrjTestPoints, rBackPrjTestPoints.t(), NORM_L2 | NORM_RELATIVE); |
|
|
|
|
ASSERT_LE(err, diffBackPrjEps) << "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_COL)"; |
|
|
|
|
#endif |
|
|
|
|
// Test read and write
|
|
|
|
|
FileStorage fs( "PCA_store.yml", FileStorage::WRITE ); |
|
|
|
|
rPCA.write( fs ); |
|
|
|
@ -518,26 +461,13 @@ protected: |
|
|
|
|
PCA lPCA; |
|
|
|
|
fs.open( "PCA_store.yml", FileStorage::READ ); |
|
|
|
|
lPCA.read( fs.root() ); |
|
|
|
|
err = cvtest::norm( rPCA.eigenvectors, lPCA.eigenvectors, CV_RELATIVE_L2 ); |
|
|
|
|
if( err > 0 ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of write/load functions (YML); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
} |
|
|
|
|
err = cvtest::norm( rPCA.eigenvalues, lPCA.eigenvalues, CV_RELATIVE_L2 ); |
|
|
|
|
if( err > 0 ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of write/load functions (YML); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
} |
|
|
|
|
err = cvtest::norm( rPCA.mean, lPCA.mean, CV_RELATIVE_L2 ); |
|
|
|
|
if( err > 0 ) |
|
|
|
|
{ |
|
|
|
|
ts->printf( cvtest::TS::LOG, "bad accuracy of write/load functions (YML); err = %f\n", err ); |
|
|
|
|
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
err = cvtest::norm(rPCA.eigenvectors, lPCA.eigenvectors, NORM_L2 | NORM_RELATIVE); |
|
|
|
|
EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)"; |
|
|
|
|
err = cvtest::norm(rPCA.eigenvalues, lPCA.eigenvalues, NORM_L2 | NORM_RELATIVE); |
|
|
|
|
EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)"; |
|
|
|
|
err = cvtest::norm(rPCA.mean, lPCA.mean, NORM_L2 | NORM_RELATIVE); |
|
|
|
|
EXPECT_LE(err, 0) << "bad accuracy of write/load functions (YML)"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class Core_ArrayOpTest : public cvtest::BaseTest |
|
|
|
|
{ |
|
|
|
@ -1227,7 +1157,6 @@ protected: |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
TEST(Core_PCA, accuracy) { Core_PCATest test; test.safe_run(); } |
|
|
|
|
TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); } |
|
|
|
|
TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); } |
|
|
|
|
|
|
|
|
|