Home | History | Annotate | Download | only in test
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                           License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
     14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
     15 // Third party copyrights are property of their respective owners.
     16 //
     17 // Redistribution and use in source and binary forms, with or without modification,
     18 // are permitted provided that the following conditions are met:
     19 //
     20 //   * Redistribution's of source code must retain the above copyright notice,
     21 //     this list of conditions and the following disclaimer.
     22 //
     23 //   * Redistribution's in binary form must reproduce the above copyright notice,
     24 //     this list of conditions and the following disclaimer in the documentation
     25 //     and/or other materials provided with the distribution.
     26 //
     27 //   * The name of the copyright holders may not be used to endorse or promote products
     28 //     derived from this software without specific prior written permission.
     29 //
     30 // This software is provided by the copyright holders and contributors "as is" and
     31 // any express or implied warranties, including, but not limited to, the implied
     32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     33 // In no event shall the Intel Corporation or contributors be liable for any direct,
     34 // indirect, incidental, special, exemplary, or consequential damages
     35 // (including, but not limited to, procurement of substitute goods or services;
     36 // loss of use, data, or profits; or business interruption) however caused
     37 // and on any theory of liability, whether in contract, strict liability,
     38 // or tort (including negligence or otherwise) arising in any way out of
     39 // the use of this software, even if advised of the possibility of such damage.
     40 //
     41 //M*/
     42 
     43 #include "test_precomp.hpp"
     44 
     45 using namespace cv;
     46 using namespace std;
     47 
     48 class CV_ECC_BaseTest : public cvtest::BaseTest
     49 {
     50 public:
     51     CV_ECC_BaseTest();
     52 
     53 protected:
     54 
     55     double computeRMS(const Mat& mat1, const Mat& mat2);
     56     bool isMapCorrect(const Mat& mat);
     57 
     58 
     59     double MAX_RMS_ECC;//upper bound for RMS error
     60     int ntests;//number of tests per motion type
     61     int ECC_iterations;//number of iterations for ECC
     62     double ECC_epsilon; //we choose a negative value, so that
     63     // ECC_iterations are always executed
     64 };
     65 
     66 CV_ECC_BaseTest::CV_ECC_BaseTest()
     67 {
     68     MAX_RMS_ECC=0.1;
     69     ntests = 3;
     70     ECC_iterations = 50;
     71     ECC_epsilon = -1; //-> negative value means that ECC_Iterations will be executed
     72 }
     73 
     74 
     75 bool CV_ECC_BaseTest::isMapCorrect(const Mat& map)
     76 {
     77     bool tr = true;
     78     float mapVal;
     79     for(int i =0; i<map.rows; i++)
     80         for(int j=0; j<map.cols; j++){
     81             mapVal = map.at<float>(i, j);
     82             tr = tr & (!cvIsNaN(mapVal) && (fabs(mapVal) < 1e9));
     83         }
     84 
     85         return tr;
     86 }
     87 
     88 double CV_ECC_BaseTest::computeRMS(const Mat& mat1, const Mat& mat2){
     89 
     90     CV_Assert(mat1.rows == mat2.rows);
     91     CV_Assert(mat1.cols == mat2.cols);
     92 
     93     Mat errorMat;
     94     subtract(mat1, mat2, errorMat);
     95 
     96     return sqrt(errorMat.dot(errorMat)/(mat1.rows*mat1.cols));
     97 }
     98 
     99 
    100 class CV_ECC_Test_Translation : public CV_ECC_BaseTest
    101 {
    102 public:
    103     CV_ECC_Test_Translation();
    104 protected:
    105     void run(int);
    106 
    107     bool testTranslation(int);
    108 };
    109 
    110 CV_ECC_Test_Translation::CV_ECC_Test_Translation(){}
    111 
    112 bool CV_ECC_Test_Translation::testTranslation(int from)
    113 {
    114     Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
    115 
    116 
    117     if (img.empty())
    118     {
    119         ts->printf( ts->LOG, "test image can not be read");
    120         ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
    121         return false;
    122     }
    123     Mat testImg;
    124     resize(img, testImg, Size(216, 216));
    125 
    126     cv::RNG rng = ts->get_rng();
    127 
    128     int progress=0;
    129 
    130     for (int k=from; k<ntests; k++){
    131 
    132         ts->update_context( this, k, true );
    133         progress = update_progress(progress, k, ntests, 0);
    134 
    135         Mat translationGround = (Mat_<float>(2,3) << 1, 0, (rng.uniform(10.f, 20.f)),
    136             0, 1, (rng.uniform(10.f, 20.f)));
    137 
    138         Mat warpedImage;
    139 
    140         warpAffine(testImg, warpedImage, translationGround,
    141             Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
    142 
    143         Mat mapTranslation = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
    144 
    145         findTransformECC(warpedImage, testImg, mapTranslation, 0,
    146             TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
    147 
    148         if (!isMapCorrect(mapTranslation)){
    149             ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
    150             return false;
    151         }
    152 
    153         if (computeRMS(mapTranslation, translationGround)>MAX_RMS_ECC){
    154             ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
    155             ts->printf( ts->LOG, "RMS = %f",
    156                 computeRMS(mapTranslation, translationGround));
    157             return false;
    158         }
    159 
    160     }
    161     return true;
    162 }
    163 
    164 void CV_ECC_Test_Translation::run(int from)
    165 {
    166 
    167     if (!testTranslation(from))
    168         return;
    169 
    170     ts->set_failed_test_info(cvtest::TS::OK);
    171 }
    172 
    173 
    174 
    175 class CV_ECC_Test_Euclidean : public CV_ECC_BaseTest
    176 {
    177 public:
    178     CV_ECC_Test_Euclidean();
    179 protected:
    180     void run(int);
    181 
    182     bool testEuclidean(int);
    183 };
    184 
    185 CV_ECC_Test_Euclidean::CV_ECC_Test_Euclidean() { }
    186 
    187 bool CV_ECC_Test_Euclidean::testEuclidean(int from)
    188 {
    189     Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
    190 
    191 
    192     if (img.empty())
    193     {
    194         ts->printf( ts->LOG, "test image can not be read");
    195         ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
    196         return false;
    197     }
    198     Mat testImg;
    199     resize(img, testImg, Size(216, 216));
    200 
    201     cv::RNG rng = ts->get_rng();
    202 
    203     int progress = 0;
    204     for (int k=from; k<ntests; k++){
    205         ts->update_context( this, k, true );
    206         progress = update_progress(progress, k, ntests, 0);
    207 
    208         double angle = CV_PI/30 + CV_PI*rng.uniform((double)-2.f, (double)2.f)/180;
    209 
    210         Mat euclideanGround = (Mat_<float>(2,3) << cos(angle), -sin(angle), (rng.uniform(10.f, 20.f)),
    211             sin(angle), cos(angle), (rng.uniform(10.f, 20.f)));
    212 
    213         Mat warpedImage;
    214 
    215         warpAffine(testImg, warpedImage, euclideanGround,
    216             Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
    217 
    218         Mat mapEuclidean = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
    219 
    220         findTransformECC(warpedImage, testImg, mapEuclidean, 1,
    221             TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
    222 
    223         if (!isMapCorrect(mapEuclidean)){
    224             ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
    225             return false;
    226         }
    227 
    228         if (computeRMS(mapEuclidean, euclideanGround)>MAX_RMS_ECC){
    229             ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
    230             ts->printf( ts->LOG, "RMS = %f",
    231                 computeRMS(mapEuclidean, euclideanGround));
    232             return false;
    233         }
    234 
    235     }
    236     return true;
    237 }
    238 
    239 
    240 void CV_ECC_Test_Euclidean::run(int from)
    241 {
    242 
    243     if (!testEuclidean(from))
    244         return;
    245 
    246     ts->set_failed_test_info(cvtest::TS::OK);
    247 }
    248 
    249 class CV_ECC_Test_Affine : public CV_ECC_BaseTest
    250 {
    251 public:
    252     CV_ECC_Test_Affine();
    253 protected:
    254     void run(int);
    255 
    256     bool testAffine(int);
    257 };
    258 
    259 CV_ECC_Test_Affine::CV_ECC_Test_Affine(){}
    260 
    261 
    262 bool CV_ECC_Test_Affine::testAffine(int from)
    263 {
    264     Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
    265 
    266     if (img.empty())
    267     {
    268         ts->printf( ts->LOG, "test image can not be read");
    269         ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
    270         return false;
    271     }
    272     Mat testImg;
    273     resize(img, testImg, Size(216, 216));
    274 
    275     cv::RNG rng = ts->get_rng();
    276 
    277     int progress = 0;
    278     for (int k=from; k<ntests; k++){
    279         ts->update_context( this, k, true );
    280         progress = update_progress(progress, k, ntests, 0);
    281 
    282 
    283         Mat affineGround = (Mat_<float>(2,3) << (1-rng.uniform(-0.05f, 0.05f)),
    284             (rng.uniform(-0.03f, 0.03f)), (rng.uniform(10.f, 20.f)),
    285             (rng.uniform(-0.03f, 0.03f)), (1-rng.uniform(-0.05f, 0.05f)),
    286             (rng.uniform(10.f, 20.f)));
    287 
    288         Mat warpedImage;
    289 
    290         warpAffine(testImg, warpedImage, affineGround,
    291             Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
    292 
    293         Mat mapAffine = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
    294 
    295         findTransformECC(warpedImage, testImg, mapAffine, 2,
    296             TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
    297 
    298         if (!isMapCorrect(mapAffine)){
    299             ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
    300             return false;
    301         }
    302 
    303         if (computeRMS(mapAffine, affineGround)>MAX_RMS_ECC){
    304             ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
    305             ts->printf( ts->LOG, "RMS = %f",
    306                 computeRMS(mapAffine, affineGround));
    307             return false;
    308         }
    309 
    310     }
    311 
    312     return true;
    313 }
    314 
    315 
    316 void CV_ECC_Test_Affine::run(int from)
    317 {
    318 
    319     if (!testAffine(from))
    320         return;
    321 
    322     ts->set_failed_test_info(cvtest::TS::OK);
    323 }
    324 
    325 class CV_ECC_Test_Homography : public CV_ECC_BaseTest
    326 {
    327 public:
    328     CV_ECC_Test_Homography();
    329 protected:
    330     void run(int);
    331 
    332     bool testHomography(int);
    333 };
    334 
    335 CV_ECC_Test_Homography::CV_ECC_Test_Homography(){}
    336 
    337 bool CV_ECC_Test_Homography::testHomography(int from)
    338 {
    339     Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
    340 
    341 
    342     if (img.empty())
    343     {
    344         ts->printf( ts->LOG, "test image can not be read");
    345         ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
    346         return false;
    347     }
    348     Mat testImg;
    349     resize(img, testImg, Size(216, 216));
    350 
    351     cv::RNG rng = ts->get_rng();
    352 
    353     int progress = 0;
    354     for (int k=from; k<ntests; k++){
    355         ts->update_context( this, k, true );
    356         progress = update_progress(progress, k, ntests, 0);
    357 
    358         Mat homoGround = (Mat_<float>(3,3) << (1-rng.uniform(-0.05f, 0.05f)),
    359             (rng.uniform(-0.03f, 0.03f)), (rng.uniform(10.f, 20.f)),
    360             (rng.uniform(-0.03f, 0.03f)), (1-rng.uniform(-0.05f, 0.05f)),(rng.uniform(10.f, 20.f)),
    361             (rng.uniform(0.0001f, 0.0003f)), (rng.uniform(0.0001f, 0.0003f)), 1.f);
    362 
    363         Mat warpedImage;
    364 
    365         warpPerspective(testImg, warpedImage, homoGround,
    366             Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
    367 
    368         Mat mapHomography = Mat::eye(3, 3, CV_32F);
    369 
    370         findTransformECC(warpedImage, testImg, mapHomography, 3,
    371             TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
    372 
    373         if (!isMapCorrect(mapHomography)){
    374             ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
    375             return false;
    376         }
    377 
    378         if (computeRMS(mapHomography, homoGround)>MAX_RMS_ECC){
    379             ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
    380             ts->printf( ts->LOG, "RMS = %f",
    381                 computeRMS(mapHomography, homoGround));
    382             return false;
    383         }
    384 
    385     }
    386     return true;
    387 }
    388 
    389 void CV_ECC_Test_Homography::run(int from)
    390 {
    391     if (!testHomography(from))
    392         return;
    393 
    394     ts->set_failed_test_info(cvtest::TS::OK);
    395 }
    396 
    397 class CV_ECC_Test_Mask : public CV_ECC_BaseTest
    398 {
    399 public:
    400     CV_ECC_Test_Mask();
    401 protected:
    402     void run(int);
    403 
    404     bool testMask(int);
    405 };
    406 
    407 CV_ECC_Test_Mask::CV_ECC_Test_Mask(){}
    408 
    409 bool CV_ECC_Test_Mask::testMask(int from)
    410 {
    411     Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
    412 
    413 
    414     if (img.empty())
    415     {
    416         ts->printf( ts->LOG, "test image can not be read");
    417         ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
    418         return false;
    419     }
    420     Mat scaledImage;
    421     resize(img, scaledImage, Size(216, 216));
    422 
    423     Mat_<float> testImg;
    424     scaledImage.convertTo(testImg, testImg.type());
    425 
    426     cv::RNG rng = ts->get_rng();
    427 
    428     int progress=0;
    429 
    430     for (int k=from; k<ntests; k++){
    431 
    432         ts->update_context( this, k, true );
    433         progress = update_progress(progress, k, ntests, 0);
    434 
    435         Mat translationGround = (Mat_<float>(2,3) << 1, 0, (rng.uniform(10.f, 20.f)),
    436             0, 1, (rng.uniform(10.f, 20.f)));
    437 
    438         Mat warpedImage;
    439 
    440         warpAffine(testImg, warpedImage, translationGround,
    441             Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
    442 
    443         Mat mapTranslation = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
    444 
    445         Mat_<unsigned char> mask = Mat_<unsigned char>::ones(testImg.rows, testImg.cols);
    446         for (int i=testImg.rows*2/3; i<testImg.rows; i++) {
    447           for (int j=testImg.cols*2/3; j<testImg.cols; j++) {
    448             testImg(i, j) = 0;
    449             mask(i, j) = 0;
    450           }
    451         }
    452 
    453         findTransformECC(warpedImage, testImg, mapTranslation, 0,
    454             TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon), mask);
    455 
    456         if (!isMapCorrect(mapTranslation)){
    457             ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
    458             return false;
    459         }
    460 
    461         if (computeRMS(mapTranslation, translationGround)>MAX_RMS_ECC){
    462             ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
    463             ts->printf( ts->LOG, "RMS = %f",
    464                 computeRMS(mapTranslation, translationGround));
    465             return false;
    466         }
    467 
    468     }
    469     return true;
    470 }
    471 
    472 void CV_ECC_Test_Mask::run(int from)
    473 {
    474     if (!testMask(from))
    475         return;
    476 
    477     ts->set_failed_test_info(cvtest::TS::OK);
    478 }
    479 
    480 TEST(Video_ECC_Translation, accuracy) { CV_ECC_Test_Translation test; test.safe_run();}
    481 TEST(Video_ECC_Euclidean, accuracy) { CV_ECC_Test_Euclidean test; test.safe_run(); }
    482 TEST(Video_ECC_Affine, accuracy) { CV_ECC_Test_Affine test; test.safe_run(); }
    483 TEST(Video_ECC_Homography, accuracy) { CV_ECC_Test_Homography test; test.safe_run(); }
    484 TEST(Video_ECC_Mask, accuracy) { CV_ECC_Test_Mask test; test.safe_run(); }
    485