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 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 #include "test_precomp.hpp"
     43 #include "opencv2/video/tracking_c.h"
     44 
     45 using namespace cv;
     46 using namespace std;
     47 
     48 class CV_TrackBaseTest : public cvtest::BaseTest
     49 {
     50 public:
     51     CV_TrackBaseTest();
     52     virtual ~CV_TrackBaseTest();
     53     void clear();
     54 
     55 protected:
     56     int read_params( CvFileStorage* fs );
     57     void run_func(void);
     58     int prepare_test_case( int test_case_idx );
     59     int validate_test_results( int test_case_idx );
     60     void generate_object();
     61 
     62     int min_log_size, max_log_size;
     63     CvMat* img;
     64     CvBox2D box0;
     65     CvSize img_size;
     66     CvTermCriteria criteria;
     67     int img_type;
     68 };
     69 
     70 
     71 CV_TrackBaseTest::CV_TrackBaseTest()
     72 {
     73     img = 0;
     74     test_case_count = 100;
     75     min_log_size = 5;
     76     max_log_size = 8;
     77 }
     78 
     79 
     80 CV_TrackBaseTest::~CV_TrackBaseTest()
     81 {
     82     clear();
     83 }
     84 
     85 
     86 void CV_TrackBaseTest::clear()
     87 {
     88     cvReleaseMat( &img );
     89     cvtest::BaseTest::clear();
     90 }
     91 
     92 
     93 int CV_TrackBaseTest::read_params( CvFileStorage* fs )
     94 {
     95     int code = cvtest::BaseTest::read_params( fs );
     96     if( code < 0 )
     97         return code;
     98 
     99     test_case_count = cvReadInt( find_param( fs, "test_case_count" ), test_case_count );
    100     min_log_size = cvReadInt( find_param( fs, "min_log_size" ), min_log_size );
    101     max_log_size = cvReadInt( find_param( fs, "max_log_size" ), max_log_size );
    102 
    103     min_log_size = cvtest::clipInt( min_log_size, 1, 10 );
    104     max_log_size = cvtest::clipInt( max_log_size, 1, 10 );
    105     if( min_log_size > max_log_size )
    106     {
    107         int t;
    108         CV_SWAP( min_log_size, max_log_size, t );
    109     }
    110 
    111     return 0;
    112 }
    113 
    114 
    115 void CV_TrackBaseTest::generate_object()
    116 {
    117     int x, y;
    118     double cx = box0.center.x;
    119     double cy = box0.center.y;
    120     double width = box0.size.width*0.5;
    121     double height = box0.size.height*0.5;
    122     double angle = box0.angle*CV_PI/180.;
    123     double a = sin(angle), b = -cos(angle);
    124     double inv_ww = 1./(width*width), inv_hh = 1./(height*height);
    125 
    126     img = cvCreateMat( img_size.height, img_size.width, img_type );
    127     cvZero( img );
    128 
    129     // use the straightforward algorithm: for every pixel check if it is inside the ellipse
    130     for( y = 0; y < img_size.height; y++ )
    131     {
    132         uchar* ptr = img->data.ptr + img->step*y;
    133         float* fl = (float*)ptr;
    134         double x_ = (y - cy)*b, y_ = (y - cy)*a;
    135 
    136         for( x = 0; x < img_size.width; x++ )
    137         {
    138             double x1 = (x - cx)*a - x_;
    139             double y1 = (x - cx)*b + y_;
    140 
    141             if( x1*x1*inv_hh + y1*y1*inv_ww <= 1. )
    142             {
    143                 if( img_type == CV_8U )
    144                     ptr[x] = (uchar)1;
    145                 else
    146                     fl[x] = (float)1.f;
    147             }
    148         }
    149     }
    150 }
    151 
    152 
    153 int CV_TrackBaseTest::prepare_test_case( int test_case_idx )
    154 {
    155     RNG& rng = ts->get_rng();
    156     cvtest::BaseTest::prepare_test_case( test_case_idx );
    157     float m;
    158 
    159     clear();
    160 
    161     box0.size.width = (float)exp((cvtest::randReal(rng) * (max_log_size - min_log_size) + min_log_size)*CV_LOG2);
    162     box0.size.height = (float)exp((cvtest::randReal(rng) * (max_log_size - min_log_size) + min_log_size)*CV_LOG2);
    163     box0.angle = (float)(cvtest::randReal(rng)*180.);
    164 
    165     if( box0.size.width > box0.size.height )
    166     {
    167         float t;
    168         CV_SWAP( box0.size.width, box0.size.height, t );
    169     }
    170 
    171     m = MAX( box0.size.width, box0.size.height );
    172     img_size.width = cvRound(cvtest::randReal(rng)*m*0.5 + m + 1);
    173     img_size.height = cvRound(cvtest::randReal(rng)*m*0.5 + m + 1);
    174     img_type = cvtest::randInt(rng) % 2 ? CV_32F : CV_8U;
    175     img_type = CV_8U;
    176 
    177     box0.center.x = (float)(img_size.width*0.5 + (cvtest::randReal(rng)-0.5)*(img_size.width - m));
    178     box0.center.y = (float)(img_size.height*0.5 + (cvtest::randReal(rng)-0.5)*(img_size.height - m));
    179 
    180     criteria = cvTermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 0.1 );
    181 
    182     generate_object();
    183 
    184     return 1;
    185 }
    186 
    187 
    188 void CV_TrackBaseTest::run_func(void)
    189 {
    190 }
    191 
    192 
    193 int CV_TrackBaseTest::validate_test_results( int /*test_case_idx*/ )
    194 {
    195     return 0;
    196 }
    197 
    198 
    199 
    200 ///////////////////////// CamShift //////////////////////////////
    201 
    202 class CV_CamShiftTest : public CV_TrackBaseTest
    203 {
    204 public:
    205     CV_CamShiftTest();
    206 
    207 protected:
    208     void run_func(void);
    209     int prepare_test_case( int test_case_idx );
    210     int validate_test_results( int test_case_idx );
    211     void generate_object();
    212 
    213     CvBox2D box;
    214     CvRect init_rect;
    215     CvConnectedComp comp;
    216     int area0;
    217 };
    218 
    219 
    220 CV_CamShiftTest::CV_CamShiftTest()
    221 {
    222 }
    223 
    224 
    225 int CV_CamShiftTest::prepare_test_case( int test_case_idx )
    226 {
    227     RNG& rng = ts->get_rng();
    228     double m;
    229     int code = CV_TrackBaseTest::prepare_test_case( test_case_idx );
    230     int i, area;
    231 
    232     if( code <= 0 )
    233         return code;
    234 
    235     area0 = cvCountNonZero(img);
    236 
    237     for(i = 0; i < 100; i++)
    238     {
    239         CvMat temp;
    240 
    241         m = MAX(box0.size.width,box0.size.height)*0.8;
    242         init_rect.x = cvFloor(box0.center.x - m*(0.45 + cvtest::randReal(rng)*0.2));
    243         init_rect.y = cvFloor(box0.center.y - m*(0.45 + cvtest::randReal(rng)*0.2));
    244         init_rect.width = cvCeil(box0.center.x + m*(0.45 + cvtest::randReal(rng)*0.2) - init_rect.x);
    245         init_rect.height = cvCeil(box0.center.y + m*(0.45 + cvtest::randReal(rng)*0.2) - init_rect.y);
    246 
    247         if( init_rect.x < 0 || init_rect.y < 0 ||
    248             init_rect.x + init_rect.width >= img_size.width ||
    249             init_rect.y + init_rect.height >= img_size.height )
    250             continue;
    251 
    252         cvGetSubRect( img, &temp, init_rect );
    253         area = cvCountNonZero( &temp );
    254 
    255         if( area >= 0.1*area0 )
    256             break;
    257     }
    258 
    259     return i < 100 ? code : 0;
    260 }
    261 
    262 
    263 void CV_CamShiftTest::run_func(void)
    264 {
    265     cvCamShift( img, init_rect, criteria, &comp, &box );
    266 }
    267 
    268 
    269 int CV_CamShiftTest::validate_test_results( int /*test_case_idx*/ )
    270 {
    271     int code = cvtest::TS::OK;
    272 
    273     double m = MAX(box0.size.width, box0.size.height), delta;
    274     double diff_angle;
    275 
    276     if( cvIsNaN(box.size.width) || cvIsInf(box.size.width) || box.size.width <= 0 ||
    277         cvIsNaN(box.size.height) || cvIsInf(box.size.height) || box.size.height <= 0 ||
    278         cvIsNaN(box.center.x) || cvIsInf(box.center.x) ||
    279         cvIsNaN(box.center.y) || cvIsInf(box.center.y) ||
    280         cvIsNaN(box.angle) || cvIsInf(box.angle) || box.angle < -180 || box.angle > 180 ||
    281         cvIsNaN(comp.area) || cvIsInf(comp.area) || comp.area <= 0 )
    282     {
    283         ts->printf( cvtest::TS::LOG, "Invalid CvBox2D or CvConnectedComp was returned by cvCamShift\n" );
    284         code = cvtest::TS::FAIL_INVALID_OUTPUT;
    285         goto _exit_;
    286     }
    287 
    288     box.angle = (float)(180 - box.angle);
    289 
    290     if( fabs(box.size.width - box0.size.width) > box0.size.width*0.2 ||
    291         fabs(box.size.height - box0.size.height) > box0.size.height*0.3 )
    292     {
    293         ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D size (=%.1f x %.1f, should be %.1f x %.1f)\n",
    294             box.size.width, box.size.height, box0.size.width, box0.size.height );
    295         code = cvtest::TS::FAIL_BAD_ACCURACY;
    296         goto _exit_;
    297     }
    298 
    299     if( fabs(box.center.x - box0.center.x) > m*0.1 ||
    300         fabs(box.center.y - box0.center.y) > m*0.1 )
    301     {
    302         ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D position (=(%.1f, %.1f), should be (%.1f, %.1f))\n",
    303             box.center.x, box.center.y, box0.center.x, box0.center.y );
    304         code = cvtest::TS::FAIL_BAD_ACCURACY;
    305         goto _exit_;
    306     }
    307 
    308     if( box.angle < 0 )
    309         box.angle += 180;
    310 
    311     diff_angle = fabs(box0.angle - box.angle);
    312     diff_angle = MIN( diff_angle, fabs(box0.angle - box.angle + 180));
    313 
    314     if( fabs(diff_angle) > 30 && box0.size.height > box0.size.width*1.2 )
    315     {
    316         ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D angle (=%1.f, should be %1.f)\n",
    317             box.angle, box0.angle );
    318         code = cvtest::TS::FAIL_BAD_ACCURACY;
    319         goto _exit_;
    320     }
    321 
    322     delta = m*0.7;
    323 
    324     if( comp.rect.x < box0.center.x - delta ||
    325         comp.rect.y < box0.center.y - delta ||
    326         comp.rect.x + comp.rect.width > box0.center.x + delta ||
    327         comp.rect.y + comp.rect.height > box0.center.y + delta )
    328     {
    329         ts->printf( cvtest::TS::LOG,
    330             "Incorrect CvConnectedComp ((%d,%d,%d,%d) is not within (%.1f,%.1f,%.1f,%.1f))\n",
    331             comp.rect.x, comp.rect.y, comp.rect.x + comp.rect.width, comp.rect.y + comp.rect.height,
    332             box0.center.x - delta, box0.center.y - delta, box0.center.x + delta, box0.center.y + delta );
    333         code = cvtest::TS::FAIL_BAD_ACCURACY;
    334         goto _exit_;
    335     }
    336 
    337     if( fabs(comp.area - area0) > area0*0.15 )
    338     {
    339         ts->printf( cvtest::TS::LOG,
    340             "Incorrect CvConnectedComp area (=%.1f, should be %d)\n", comp.area, area0 );
    341         code = cvtest::TS::FAIL_BAD_ACCURACY;
    342         goto _exit_;
    343     }
    344 
    345 _exit_:
    346 
    347     if( code < 0 )
    348     {
    349 #if 0 //defined _DEBUG && defined WIN32
    350         IplImage* dst = cvCreateImage( img_size, 8, 3 );
    351         cvNamedWindow( "test", 1 );
    352         cvCmpS( img, 0, img, CV_CMP_GT );
    353         cvCvtColor( img, dst, CV_GRAY2BGR );
    354         cvRectangle( dst, cvPoint(init_rect.x, init_rect.y),
    355             cvPoint(init_rect.x + init_rect.width, init_rect.y + init_rect.height),
    356             CV_RGB(255,0,0), 3, 8, 0 );
    357         cvEllipseBox( dst, box, CV_RGB(0,255,0), 3, 8, 0 );
    358         cvShowImage( "test", dst );
    359         cvReleaseImage( &dst );
    360         cvWaitKey();
    361 #endif
    362         ts->set_failed_test_info( code );
    363     }
    364     return code;
    365 }
    366 
    367 
    368 ///////////////////////// MeanShift //////////////////////////////
    369 
    370 class CV_MeanShiftTest : public CV_TrackBaseTest
    371 {
    372 public:
    373     CV_MeanShiftTest();
    374 
    375 protected:
    376     void run_func(void);
    377     int prepare_test_case( int test_case_idx );
    378     int validate_test_results( int test_case_idx );
    379     void generate_object();
    380 
    381     CvRect init_rect;
    382     CvConnectedComp comp;
    383     int area0, area;
    384 };
    385 
    386 
    387 CV_MeanShiftTest::CV_MeanShiftTest()
    388 {
    389 }
    390 
    391 
    392 int CV_MeanShiftTest::prepare_test_case( int test_case_idx )
    393 {
    394     RNG& rng = ts->get_rng();
    395     double m;
    396     int code = CV_TrackBaseTest::prepare_test_case( test_case_idx );
    397     int i;
    398 
    399     if( code <= 0 )
    400         return code;
    401 
    402     area0 = cvCountNonZero(img);
    403 
    404     for(i = 0; i < 100; i++)
    405     {
    406         CvMat temp;
    407 
    408         m = (box0.size.width + box0.size.height)*0.5;
    409         init_rect.x = cvFloor(box0.center.x - m*(0.4 + cvtest::randReal(rng)*0.2));
    410         init_rect.y = cvFloor(box0.center.y - m*(0.4 + cvtest::randReal(rng)*0.2));
    411         init_rect.width = cvCeil(box0.center.x + m*(0.4 + cvtest::randReal(rng)*0.2) - init_rect.x);
    412         init_rect.height = cvCeil(box0.center.y + m*(0.4 + cvtest::randReal(rng)*0.2) - init_rect.y);
    413 
    414         if( init_rect.x < 0 || init_rect.y < 0 ||
    415             init_rect.x + init_rect.width >= img_size.width ||
    416             init_rect.y + init_rect.height >= img_size.height )
    417             continue;
    418 
    419         cvGetSubRect( img, &temp, init_rect );
    420         area = cvCountNonZero( &temp );
    421 
    422         if( area >= 0.5*area0 )
    423             break;
    424     }
    425 
    426     return i < 100 ? code : 0;
    427 }
    428 
    429 
    430 void CV_MeanShiftTest::run_func(void)
    431 {
    432     cvMeanShift( img, init_rect, criteria, &comp );
    433 }
    434 
    435 
    436 int CV_MeanShiftTest::validate_test_results( int /*test_case_idx*/ )
    437 {
    438     int code = cvtest::TS::OK;
    439     CvPoint2D32f c;
    440     double m = MAX(box0.size.width, box0.size.height), delta;
    441 
    442     if( cvIsNaN(comp.area) || cvIsInf(comp.area) || comp.area <= 0 )
    443     {
    444         ts->printf( cvtest::TS::LOG, "Invalid CvConnectedComp was returned by cvMeanShift\n" );
    445         code = cvtest::TS::FAIL_INVALID_OUTPUT;
    446         goto _exit_;
    447     }
    448 
    449     c.x = (float)(comp.rect.x + comp.rect.width*0.5);
    450     c.y = (float)(comp.rect.y + comp.rect.height*0.5);
    451 
    452     if( fabs(c.x - box0.center.x) > m*0.1 ||
    453         fabs(c.y - box0.center.y) > m*0.1 )
    454     {
    455         ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D position (=(%.1f, %.1f), should be (%.1f, %.1f))\n",
    456             c.x, c.y, box0.center.x, box0.center.y );
    457         code = cvtest::TS::FAIL_BAD_ACCURACY;
    458         goto _exit_;
    459     }
    460 
    461     delta = m*0.7;
    462 
    463     if( comp.rect.x < box0.center.x - delta ||
    464         comp.rect.y < box0.center.y - delta ||
    465         comp.rect.x + comp.rect.width > box0.center.x + delta ||
    466         comp.rect.y + comp.rect.height > box0.center.y + delta )
    467     {
    468         ts->printf( cvtest::TS::LOG,
    469             "Incorrect CvConnectedComp ((%d,%d,%d,%d) is not within (%.1f,%.1f,%.1f,%.1f))\n",
    470             comp.rect.x, comp.rect.y, comp.rect.x + comp.rect.width, comp.rect.y + comp.rect.height,
    471             box0.center.x - delta, box0.center.y - delta, box0.center.x + delta, box0.center.y + delta );
    472         code = cvtest::TS::FAIL_BAD_ACCURACY;
    473         goto _exit_;
    474     }
    475 
    476     if( fabs((double)(comp.area - area0)) > fabs((double)(area - area0)) + area0*0.05 )
    477     {
    478         ts->printf( cvtest::TS::LOG,
    479             "Incorrect CvConnectedComp area (=%.1f, should be %d)\n", comp.area, area0 );
    480         code = cvtest::TS::FAIL_BAD_ACCURACY;
    481         goto _exit_;
    482     }
    483 
    484 _exit_:
    485 
    486     if( code < 0 )
    487     {
    488 #if 0// defined _DEBUG && defined WIN32
    489         IplImage* dst = cvCreateImage( img_size, 8, 3 );
    490         cvNamedWindow( "test", 1 );
    491         cvCmpS( img, 0, img, CV_CMP_GT );
    492         cvCvtColor( img, dst, CV_GRAY2BGR );
    493         cvRectangle( dst, cvPoint(init_rect.x, init_rect.y),
    494             cvPoint(init_rect.x + init_rect.width, init_rect.y + init_rect.height),
    495             CV_RGB(255,0,0), 3, 8, 0 );
    496         cvRectangle( dst, cvPoint(comp.rect.x, comp.rect.y),
    497             cvPoint(comp.rect.x + comp.rect.width, comp.rect.y + comp.rect.height),
    498             CV_RGB(0,255,0), 3, 8, 0 );
    499         cvShowImage( "test", dst );
    500         cvReleaseImage( &dst );
    501         cvWaitKey();
    502 #endif
    503         ts->set_failed_test_info( code );
    504     }
    505     return code;
    506 }
    507 
    508 
    509 TEST(Video_CAMShift, accuracy) { CV_CamShiftTest test; test.safe_run(); }
    510 TEST(Video_MeanShift, accuracy) { CV_MeanShiftTest test; test.safe_run(); }
    511 
    512 /* End of file. */
    513