reworked nearly all of the OpenCV tests (except for opencv_gpu tests) - they now use the Google Test engine.

This commit is contained in:
Vadim Pisarevsky
2011-02-09 20:55:11 +00:00
parent 63806c9ab9
commit 061b49e0b2
122 changed files with 39081 additions and 28854 deletions

View File

@@ -0,0 +1,247 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
using namespace cv;
using namespace std;
class CV_AccumBaseTest : public cvtest::ArrayTest
{
public:
CV_AccumBaseTest();
protected:
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
double get_success_error_level( int test_case_idx, int i, int j );
double alpha;
};
CV_AccumBaseTest::CV_AccumBaseTest()
{
test_array[INPUT].push_back(NULL);
test_array[INPUT_OUTPUT].push_back(NULL);
test_array[REF_INPUT_OUTPUT].push_back(NULL);
test_array[MASK].push_back(NULL);
optional_mask = true;
element_wise_relative_error = false;
} // ctor
void CV_AccumBaseTest::get_test_array_types_and_sizes( int test_case_idx,
vector<vector<Size> >& sizes, vector<vector<int> >& types )
{
RNG& rng = ts->get_rng();
int depth = cvtest::randInt(rng) % 3, cn = cvtest::randInt(rng) & 1 ? 3 : 1;
int accdepth = std::max((int)(cvtest::randInt(rng) % 2 + 1), depth);
int i, input_count = test_array[INPUT].size();
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
depth = depth == 0 ? CV_8U : depth == 1 ? CV_32F : CV_64F;
accdepth = accdepth == 1 ? CV_32F : CV_64F;
accdepth = MAX(accdepth, depth);
for( i = 0; i < input_count; i++ )
types[INPUT][i] = CV_MAKETYPE(depth,cn);
types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(accdepth,cn);
alpha = cvtest::randReal(rng);
}
double CV_AccumBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
{
return test_mat[INPUT_OUTPUT][0].depth() < CV_64F ||
test_mat[INPUT][0].depth() == CV_32F ? FLT_EPSILON*100 : DBL_EPSILON*1000;
}
/// acc
class CV_AccTest : public CV_AccumBaseTest
{
public:
CV_AccTest() {};
protected:
void run_func();
void prepare_to_validation( int );
};
void CV_AccTest::run_func(void)
{
cvAcc( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
}
void CV_AccTest::prepare_to_validation( int )
{
const Mat& src = test_mat[INPUT][0];
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
const Mat& mask = test_array[MASK][0] ? test_mat[MASK][0] : Mat();
Mat temp;
cvtest::add( src, 1, dst, 1, cvScalarAll(0.), temp, dst.type() );
cvtest::copy( temp, dst, mask );
}
/// square acc
class CV_SquareAccTest : public CV_AccumBaseTest
{
public:
CV_SquareAccTest();
protected:
void run_func();
void prepare_to_validation( int );
};
CV_SquareAccTest::CV_SquareAccTest()
{
}
void CV_SquareAccTest::run_func()
{
cvSquareAcc( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
}
void CV_SquareAccTest::prepare_to_validation( int )
{
const Mat& src = test_mat[INPUT][0];
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
const Mat& mask = test_array[MASK][0] ? test_mat[MASK][0] : Mat();
Mat temp;
cvtest::convert( src, temp, dst.type() );
cvtest::multiply( temp, temp, temp, 1 );
cvtest::add( temp, 1, dst, 1, cvScalarAll(0.), temp, dst.depth() );
cvtest::copy( temp, dst, mask );
}
/// multiply acc
class CV_MultiplyAccTest : public CV_AccumBaseTest
{
public:
CV_MultiplyAccTest();
protected:
void run_func();
void prepare_to_validation( int );
};
CV_MultiplyAccTest::CV_MultiplyAccTest()
{
test_array[INPUT].push_back(NULL);
}
void CV_MultiplyAccTest::run_func()
{
cvMultiplyAcc( test_array[INPUT][0], test_array[INPUT][1],
test_array[INPUT_OUTPUT][0], test_array[MASK][0] );
}
void CV_MultiplyAccTest::prepare_to_validation( int )
{
const Mat& src1 = test_mat[INPUT][0];
const Mat& src2 = test_mat[INPUT][1];
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
const Mat& mask = test_array[MASK][0] ? test_mat[MASK][0] : Mat();
Mat temp1, temp2;
cvtest::convert( src1, temp1, dst.type() );
cvtest::convert( src2, temp2, dst.type() );
cvtest::multiply( temp1, temp2, temp1, 1 );
cvtest::add( temp1, 1, dst, 1, cvScalarAll(0.), temp1, dst.depth() );
cvtest::copy( temp1, dst, mask );
}
/// running average
class CV_RunningAvgTest : public CV_AccumBaseTest
{
public:
CV_RunningAvgTest();
protected:
void run_func();
void prepare_to_validation( int );
};
CV_RunningAvgTest::CV_RunningAvgTest()
{
}
void CV_RunningAvgTest::run_func()
{
cvRunningAvg( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],
alpha, test_array[MASK][0] );
}
void CV_RunningAvgTest::prepare_to_validation( int )
{
const Mat& src = test_mat[INPUT][0];
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
Mat temp;
const Mat& mask = test_array[MASK][0] ? test_mat[MASK][0] : Mat();
double a[1], b[1];
int accdepth = test_mat[INPUT_OUTPUT][0].depth();
CvMat A = cvMat(1,1,accdepth,a), B = cvMat(1,1,accdepth,b);
cvSetReal1D( &A, 0, alpha);
cvSetReal1D( &B, 0, 1 - cvGetReal1D(&A, 0));
cvtest::convert( src, temp, dst.type() );
cvtest::add( src, cvGetReal1D(&A, 0), dst, cvGetReal1D(&B, 0), cvScalarAll(0.), temp, temp.depth() );
cvtest::copy( temp, dst, mask );
}
TEST(Video_Acc, accuracy) { CV_AccTest test; test.safe_run(); }
TEST(Video_AccSquared, accuracy) { CV_SquareAccTest test; test.safe_run(); }
TEST(Video_AccProduct, accuracy) { CV_MultiplyAccTest test; test.safe_run(); }
TEST(Video_RunningAvg, accuracy) { CV_RunningAvgTest test; test.safe_run(); }

View File

@@ -0,0 +1,511 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
using namespace cv;
using namespace std;
class CV_TrackBaseTest : public cvtest::BaseTest
{
public:
CV_TrackBaseTest();
virtual ~CV_TrackBaseTest();
void clear();
protected:
int read_params( CvFileStorage* fs );
void run_func(void);
int prepare_test_case( int test_case_idx );
int validate_test_results( int test_case_idx );
void generate_object();
int min_log_size, max_log_size;
CvMat* img;
CvBox2D box0;
CvSize img_size;
CvTermCriteria criteria;
int img_type;
};
CV_TrackBaseTest::CV_TrackBaseTest()
{
img = 0;
test_case_count = 100;
min_log_size = 5;
max_log_size = 8;
}
CV_TrackBaseTest::~CV_TrackBaseTest()
{
clear();
}
void CV_TrackBaseTest::clear()
{
cvReleaseMat( &img );
cvtest::BaseTest::clear();
}
int CV_TrackBaseTest::read_params( CvFileStorage* fs )
{
int code = cvtest::BaseTest::read_params( fs );
if( code < 0 )
return code;
test_case_count = cvReadInt( find_param( fs, "test_case_count" ), test_case_count );
min_log_size = cvReadInt( find_param( fs, "min_log_size" ), min_log_size );
max_log_size = cvReadInt( find_param( fs, "max_log_size" ), max_log_size );
min_log_size = cvtest::clipInt( min_log_size, 1, 10 );
max_log_size = cvtest::clipInt( max_log_size, 1, 10 );
if( min_log_size > max_log_size )
{
int t;
CV_SWAP( min_log_size, max_log_size, t );
}
return 0;
}
void CV_TrackBaseTest::generate_object()
{
int x, y;
double cx = box0.center.x;
double cy = box0.center.y;
double width = box0.size.width*0.5;
double height = box0.size.height*0.5;
double angle = box0.angle*CV_PI/180.;
double a = sin(angle), b = -cos(angle);
double inv_ww = 1./(width*width), inv_hh = 1./(height*height);
img = cvCreateMat( img_size.height, img_size.width, img_type );
cvZero( img );
// use the straightforward algorithm: for every pixel check if it is inside the ellipse
for( y = 0; y < img_size.height; y++ )
{
uchar* ptr = img->data.ptr + img->step*y;
float* fl = (float*)ptr;
double x_ = (y - cy)*b, y_ = (y - cy)*a;
for( x = 0; x < img_size.width; x++ )
{
double x1 = (x - cx)*a - x_;
double y1 = (x - cx)*b + y_;
if( x1*x1*inv_hh + y1*y1*inv_ww <= 1. )
{
if( img_type == CV_8U )
ptr[x] = (uchar)1;
else
fl[x] = (float)1.f;
}
}
}
}
int CV_TrackBaseTest::prepare_test_case( int test_case_idx )
{
RNG& rng = ts->get_rng();
cvtest::BaseTest::prepare_test_case( test_case_idx );
float m;
clear();
box0.size.width = (float)exp((cvtest::randReal(rng) * (max_log_size - min_log_size) + min_log_size)*CV_LOG2);
box0.size.height = (float)exp((cvtest::randReal(rng) * (max_log_size - min_log_size) + min_log_size)*CV_LOG2);
box0.angle = (float)(cvtest::randReal(rng)*180.);
if( box0.size.width > box0.size.height )
{
float t;
CV_SWAP( box0.size.width, box0.size.height, t );
}
m = MAX( box0.size.width, box0.size.height );
img_size.width = cvRound(cvtest::randReal(rng)*m*0.5 + m + 1);
img_size.height = cvRound(cvtest::randReal(rng)*m*0.5 + m + 1);
img_type = cvtest::randInt(rng) % 2 ? CV_32F : CV_8U;
img_type = CV_8U;
box0.center.x = (float)(img_size.width*0.5 + (cvtest::randReal(rng)-0.5)*(img_size.width - m));
box0.center.y = (float)(img_size.height*0.5 + (cvtest::randReal(rng)-0.5)*(img_size.height - m));
criteria = cvTermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 0.1 );
generate_object();
return 1;
}
void CV_TrackBaseTest::run_func(void)
{
}
int CV_TrackBaseTest::validate_test_results( int /*test_case_idx*/ )
{
return 0;
}
///////////////////////// CamShift //////////////////////////////
class CV_CamShiftTest : public CV_TrackBaseTest
{
public:
CV_CamShiftTest();
protected:
void run_func(void);
int prepare_test_case( int test_case_idx );
int validate_test_results( int test_case_idx );
void generate_object();
CvBox2D box;
CvRect init_rect;
CvConnectedComp comp;
int area0;
};
CV_CamShiftTest::CV_CamShiftTest()
{
}
int CV_CamShiftTest::prepare_test_case( int test_case_idx )
{
RNG& rng = ts->get_rng();
double m;
int code = CV_TrackBaseTest::prepare_test_case( test_case_idx );
int i, area;
if( code <= 0 )
return code;
area0 = cvCountNonZero(img);
for(i = 0; i < 100; i++)
{
CvMat temp;
m = MAX(box0.size.width,box0.size.height)*0.8;
init_rect.x = cvFloor(box0.center.x - m*(0.45 + cvtest::randReal(rng)*0.2));
init_rect.y = cvFloor(box0.center.y - m*(0.45 + cvtest::randReal(rng)*0.2));
init_rect.width = cvCeil(box0.center.x + m*(0.45 + cvtest::randReal(rng)*0.2) - init_rect.x);
init_rect.height = cvCeil(box0.center.y + m*(0.45 + cvtest::randReal(rng)*0.2) - init_rect.y);
if( init_rect.x < 0 || init_rect.y < 0 ||
init_rect.x + init_rect.width >= img_size.width ||
init_rect.y + init_rect.height >= img_size.height )
continue;
cvGetSubRect( img, &temp, init_rect );
area = cvCountNonZero( &temp );
if( area >= 0.1*area0 )
break;
}
return i < 100 ? code : 0;
}
void CV_CamShiftTest::run_func(void)
{
cvCamShift( img, init_rect, criteria, &comp, &box );
}
int CV_CamShiftTest::validate_test_results( int /*test_case_idx*/ )
{
int code = cvtest::TS::OK;
double m = MAX(box0.size.width, box0.size.height), delta;
double diff_angle;
if( cvIsNaN(box.size.width) || cvIsInf(box.size.width) || box.size.width <= 0 ||
cvIsNaN(box.size.height) || cvIsInf(box.size.height) || box.size.height <= 0 ||
cvIsNaN(box.center.x) || cvIsInf(box.center.x) ||
cvIsNaN(box.center.y) || cvIsInf(box.center.y) ||
cvIsNaN(box.angle) || cvIsInf(box.angle) || box.angle < -180 || box.angle > 180 ||
cvIsNaN(comp.area) || cvIsInf(comp.area) || comp.area <= 0 )
{
ts->printf( cvtest::TS::LOG, "Invalid CvBox2D or CvConnectedComp was returned by cvCamShift\n" );
code = cvtest::TS::FAIL_INVALID_OUTPUT;
goto _exit_;
}
box.angle = (float)(180 - box.angle);
if( fabs(box.size.width - box0.size.width) > box0.size.width*0.2 ||
fabs(box.size.height - box0.size.height) > box0.size.height*0.3 )
{
ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D size (=%.1f x %.1f, should be %.1f x %.1f)\n",
box.size.width, box.size.height, box0.size.width, box0.size.height );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto _exit_;
}
if( fabs(box.center.x - box0.center.x) > m*0.1 ||
fabs(box.center.y - box0.center.y) > m*0.1 )
{
ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D position (=(%.1f, %.1f), should be (%.1f, %.1f))\n",
box.center.x, box.center.y, box0.center.x, box0.center.y );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto _exit_;
}
if( box.angle < 0 )
box.angle += 180;
diff_angle = fabs(box0.angle - box.angle);
diff_angle = MIN( diff_angle, fabs(box0.angle - box.angle + 180));
if( fabs(diff_angle) > 30 && box0.size.height > box0.size.width*1.2 )
{
ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D angle (=%1.f, should be %1.f)\n",
box.angle, box0.angle );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto _exit_;
}
delta = m*0.7;
if( comp.rect.x < box0.center.x - delta ||
comp.rect.y < box0.center.y - delta ||
comp.rect.x + comp.rect.width > box0.center.x + delta ||
comp.rect.y + comp.rect.height > box0.center.y + delta )
{
ts->printf( cvtest::TS::LOG,
"Incorrect CvConnectedComp ((%d,%d,%d,%d) is not within (%.1f,%.1f,%.1f,%.1f))\n",
comp.rect.x, comp.rect.y, comp.rect.x + comp.rect.width, comp.rect.y + comp.rect.height,
box0.center.x - delta, box0.center.y - delta, box0.center.x + delta, box0.center.y + delta );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto _exit_;
}
if( fabs(comp.area - area0) > area0*0.15 )
{
ts->printf( cvtest::TS::LOG,
"Incorrect CvConnectedComp area (=%.1f, should be %d)\n", comp.area, area0 );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto _exit_;
}
_exit_:
if( code < 0 )
{
#if defined _DEBUG && defined WIN32
IplImage* dst = cvCreateImage( img_size, 8, 3 );
cvNamedWindow( "test", 1 );
cvCmpS( img, 0, img, CV_CMP_GT );
cvCvtColor( img, dst, CV_GRAY2BGR );
cvRectangle( dst, cvPoint(init_rect.x, init_rect.y),
cvPoint(init_rect.x + init_rect.width, init_rect.y + init_rect.height),
CV_RGB(255,0,0), 3, 8, 0 );
cvEllipseBox( dst, box, CV_RGB(0,255,0), 3, 8, 0 );
cvShowImage( "test", dst );
cvReleaseImage( &dst );
cvWaitKey();
#endif
ts->set_failed_test_info( code );
}
return code;
}
///////////////////////// MeanShift //////////////////////////////
class CV_MeanShiftTest : public CV_TrackBaseTest
{
public:
CV_MeanShiftTest();
protected:
void run_func(void);
int prepare_test_case( int test_case_idx );
int validate_test_results( int test_case_idx );
void generate_object();
CvRect init_rect;
CvConnectedComp comp;
int area0, area;
};
CV_MeanShiftTest::CV_MeanShiftTest()
{
}
int CV_MeanShiftTest::prepare_test_case( int test_case_idx )
{
RNG& rng = ts->get_rng();
double m;
int code = CV_TrackBaseTest::prepare_test_case( test_case_idx );
int i;
if( code <= 0 )
return code;
area0 = cvCountNonZero(img);
for(i = 0; i < 100; i++)
{
CvMat temp;
m = (box0.size.width + box0.size.height)*0.5;
init_rect.x = cvFloor(box0.center.x - m*(0.4 + cvtest::randReal(rng)*0.2));
init_rect.y = cvFloor(box0.center.y - m*(0.4 + cvtest::randReal(rng)*0.2));
init_rect.width = cvCeil(box0.center.x + m*(0.4 + cvtest::randReal(rng)*0.2) - init_rect.x);
init_rect.height = cvCeil(box0.center.y + m*(0.4 + cvtest::randReal(rng)*0.2) - init_rect.y);
if( init_rect.x < 0 || init_rect.y < 0 ||
init_rect.x + init_rect.width >= img_size.width ||
init_rect.y + init_rect.height >= img_size.height )
continue;
cvGetSubRect( img, &temp, init_rect );
area = cvCountNonZero( &temp );
if( area >= 0.5*area0 )
break;
}
return i < 100 ? code : 0;
}
void CV_MeanShiftTest::run_func(void)
{
cvMeanShift( img, init_rect, criteria, &comp );
}
int CV_MeanShiftTest::validate_test_results( int /*test_case_idx*/ )
{
int code = cvtest::TS::OK;
CvPoint2D32f c;
double m = MAX(box0.size.width, box0.size.height), delta;
if( cvIsNaN(comp.area) || cvIsInf(comp.area) || comp.area <= 0 )
{
ts->printf( cvtest::TS::LOG, "Invalid CvConnectedComp was returned by cvMeanShift\n" );
code = cvtest::TS::FAIL_INVALID_OUTPUT;
goto _exit_;
}
c.x = (float)(comp.rect.x + comp.rect.width*0.5);
c.y = (float)(comp.rect.y + comp.rect.height*0.5);
if( fabs(c.x - box0.center.x) > m*0.1 ||
fabs(c.y - box0.center.y) > m*0.1 )
{
ts->printf( cvtest::TS::LOG, "Incorrect CvBox2D position (=(%.1f, %.1f), should be (%.1f, %.1f))\n",
c.x, c.y, box0.center.x, box0.center.y );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto _exit_;
}
delta = m*0.7;
if( comp.rect.x < box0.center.x - delta ||
comp.rect.y < box0.center.y - delta ||
comp.rect.x + comp.rect.width > box0.center.x + delta ||
comp.rect.y + comp.rect.height > box0.center.y + delta )
{
ts->printf( cvtest::TS::LOG,
"Incorrect CvConnectedComp ((%d,%d,%d,%d) is not within (%.1f,%.1f,%.1f,%.1f))\n",
comp.rect.x, comp.rect.y, comp.rect.x + comp.rect.width, comp.rect.y + comp.rect.height,
box0.center.x - delta, box0.center.y - delta, box0.center.x + delta, box0.center.y + delta );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto _exit_;
}
if( fabs((double)(comp.area - area0)) > fabs((double)(area - area0)) + area0*0.05 )
{
ts->printf( cvtest::TS::LOG,
"Incorrect CvConnectedComp area (=%.1f, should be %d)\n", comp.area, area0 );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto _exit_;
}
_exit_:
if( code < 0 )
{
#if defined _DEBUG && defined WIN32
IplImage* dst = cvCreateImage( img_size, 8, 3 );
cvNamedWindow( "test", 1 );
cvCmpS( img, 0, img, CV_CMP_GT );
cvCvtColor( img, dst, CV_GRAY2BGR );
cvRectangle( dst, cvPoint(init_rect.x, init_rect.y),
cvPoint(init_rect.x + init_rect.width, init_rect.y + init_rect.height),
CV_RGB(255,0,0), 3, 8, 0 );
cvRectangle( dst, cvPoint(comp.rect.x, comp.rect.y),
cvPoint(comp.rect.x + comp.rect.width, comp.rect.y + comp.rect.height),
CV_RGB(0,255,0), 3, 8, 0 );
cvShowImage( "test", dst );
cvReleaseImage( &dst );
cvWaitKey();
#endif
ts->set_failed_test_info( code );
}
return code;
}
TEST(Video_CAMShift, accuracy) { CV_CamShiftTest test; test.safe_run(); }
TEST(Video_MeanShift, accuracy) { CV_MeanShiftTest test; test.safe_run(); }
/* End of file. */

View File

@@ -0,0 +1,174 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
#include <string>
#include <iostream>
#include <fstream>
#include <iterator>
#include <limits>
#include <numeric>
using namespace cv;
using namespace std;
class CV_RigidTransform_Test : public cvtest::BaseTest
{
public:
CV_RigidTransform_Test();
~CV_RigidTransform_Test();
protected:
void run(int);
bool testNPoints(int);
bool testImage();
};
CV_RigidTransform_Test::CV_RigidTransform_Test()
{
}
CV_RigidTransform_Test::~CV_RigidTransform_Test() {}
struct WrapAff2D
{
const double *F;
WrapAff2D(const Mat& aff) : F(aff.ptr<double>()) {}
Point2f operator()(const Point2f& p)
{
return Point2d( p.x * F[0] + p.y * F[1] + F[2],
p.x * F[3] + p.y * F[4] + F[5]);
}
};
bool CV_RigidTransform_Test::testNPoints(int from)
{
cv::RNG rng = ts->get_rng();
int progress = 0;
int k, ntests = 10000;
for( k = from; k < ntests; k++ )
{
ts->update_context( this, k, true );
progress = update_progress(progress, k, ntests, 0);
Mat aff(2, 3, CV_64F);
rng.fill(aff, CV_RAND_UNI, Scalar(-2), Scalar(2));
int n = (unsigned)rng % 100 + 10;
Mat fpts(1, n, CV_32FC2);
Mat tpts(1, n, CV_32FC2);
rng.fill(fpts, CV_RAND_UNI, Scalar(0,0), Scalar(10,10));
transform(fpts.ptr<Point2f>(), fpts.ptr<Point2f>() + n, tpts.ptr<Point2f>(), WrapAff2D(aff));
Mat noise(1, n, CV_32FC2);
rng.fill(noise, CV_RAND_NORMAL, Scalar::all(0), Scalar::all(0.001*(n<=7 ? 0 : n <= 30 ? 1 : 10)));
tpts += noise;
Mat aff_est = estimateRigidTransform(fpts, tpts, true);
double thres = 0.1*norm(aff);
double d = norm(aff_est, aff, NORM_L2);
if (d > thres)
{
double dB=0, nB=0;
if (n <= 4)
{
Mat A = fpts.reshape(1, 3);
Mat B = A - repeat(A.row(0), 3, 1), Bt = B.t();
B = Bt*B;
dB = cv::determinant(B);
nB = norm(B);
if( fabs(dB) < 0.01*nB )
continue;
}
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
ts->printf( cvtest::TS::LOG, "Threshold = %f, norm of difference = %f", thres, d );
return false;
}
}
return true;
}
bool CV_RigidTransform_Test::testImage()
{
Mat img;
pyrDown(imread( string(ts->get_data_path()) + "shared/graffiti.png", 1), img);
Mat aff = cv::getRotationMatrix2D(Point(img.cols/2, img.rows/2), 1, 0.99);
aff.ptr<double>()[2]+=3;
aff.ptr<double>()[5]+=3;
Mat rotated;
warpAffine(img, rotated, aff, img.size());
Mat aff_est = estimateRigidTransform(img, rotated, true);
const double thres = 0.03;
if (norm(aff_est, aff, NORM_INF) > thres)
{
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
ts->printf( cvtest::TS::LOG, "Threshold = %f, norm of difference = %f", thres,
norm(aff_est, aff, NORM_INF) );
return false;
}
return true;
}
void CV_RigidTransform_Test::run( int start_from )
{
cvtest::DefaultRngAuto dra;
if (!testNPoints(start_from))
return;
if (!testImage())
return;
ts->set_failed_test_info(cvtest::TS::OK);
}
TEST(Video_RigidFlow, accuracy) { CV_RigidTransform_Test test; test.safe_run(); }

View File

@@ -0,0 +1,124 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
using namespace cv;
class CV_KalmanTest : public cvtest::BaseTest
{
public:
CV_KalmanTest();
protected:
void run(int);
};
CV_KalmanTest::CV_KalmanTest()
{
}
void CV_KalmanTest::run( int )
{
int code = cvtest::TS::OK;
const int Dim = 7;
const int Steps = 100;
const double max_init = 1;
const double max_noise = 0.1;
const double EPSILON = 1.000;
RNG& rng = ts->get_rng();
CvKalman* Kalm;
int i, j;
CvMat* Sample = cvCreateMat(Dim,1,CV_32F);
CvMat* Temp = cvCreateMat(Dim,1,CV_32F);
Kalm = cvCreateKalman(Dim, Dim);
CvMat Dyn = cvMat(Dim,Dim,CV_32F,Kalm->DynamMatr);
CvMat Mes = cvMat(Dim,Dim,CV_32F,Kalm->MeasurementMatr);
CvMat PNC = cvMat(Dim,Dim,CV_32F,Kalm->PNCovariance);
CvMat MNC = cvMat(Dim,Dim,CV_32F,Kalm->MNCovariance);
CvMat PriErr = cvMat(Dim,Dim,CV_32F,Kalm->PriorErrorCovariance);
CvMat PostErr = cvMat(Dim,Dim,CV_32F,Kalm->PosterErrorCovariance);
CvMat PriState = cvMat(Dim,1,CV_32F,Kalm->PriorState);
CvMat PostState = cvMat(Dim,1,CV_32F,Kalm->PosterState);
cvSetIdentity(&PNC);
cvSetIdentity(&PriErr);
cvSetIdentity(&PostErr);
cvSetZero(&MNC);
cvSetZero(&PriState);
cvSetZero(&PostState);
cvSetIdentity(&Mes);
cvSetIdentity(&Dyn);
Mat _Sample = cvarrToMat(Sample);
cvtest::randUni(rng, _Sample, cvScalarAll(-max_init), cvScalarAll(max_init));
cvKalmanCorrect(Kalm, Sample);
for(i = 0; i<Steps; i++)
{
cvKalmanPredict(Kalm);
for(j = 0; j<Dim; j++)
{
float t = 0;
for(int k=0; k<Dim; k++)
{
t += Dyn.data.fl[j*Dim+k]*Sample->data.fl[k];
}
Temp->data.fl[j]= (float)(t+(cvtest::randReal(rng)*2-1)*max_noise);
}
cvCopy( Temp, Sample );
cvKalmanCorrect(Kalm,Temp);
}
Mat _state_post = cvarrToMat(Kalm->state_post);
code = cvtest::cmpEps2( ts, _Sample, _state_post, EPSILON, false, "The final estimated state" );
cvReleaseMat(&Sample);
cvReleaseMat(&Temp);
cvReleaseKalman(&Kalm);
if( code < 0 )
ts->set_failed_test_info( code );
}
TEST(Video_Kalman, accuracy) { CV_KalmanTest test; test.safe_run(); }
/* End of file. */

View File

@@ -0,0 +1,3 @@
#include "test_precomp.hpp"
CV_TEST_MAIN("cv")

View File

@@ -0,0 +1,497 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
using namespace cv;
using namespace std;
///////////////////// base MHI class ///////////////////////
class CV_MHIBaseTest : public cvtest::ArrayTest
{
public:
CV_MHIBaseTest();
protected:
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
int prepare_test_case( int test_case_idx );
double timestamp, duration, max_log_duration;
int mhi_i, mhi_ref_i;
double silh_ratio;
};
CV_MHIBaseTest::CV_MHIBaseTest()
{
timestamp = duration = 0;
max_log_duration = 9;
mhi_i = mhi_ref_i = -1;
silh_ratio = 0.25;
}
void CV_MHIBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
{
cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
if( i == INPUT && CV_MAT_DEPTH(type) == CV_8U )
{
low = Scalar::all(cvRound(-1./silh_ratio)+2.);
high = Scalar::all(2);
}
else if( i == mhi_i || i == mhi_ref_i )
{
low = Scalar::all(-exp(max_log_duration));
high = Scalar::all(0.);
}
}
void CV_MHIBaseTest::get_test_array_types_and_sizes( int test_case_idx,
vector<vector<Size> >& sizes, vector<vector<int> >& types )
{
RNG& rng = ts->get_rng();
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
types[INPUT][0] = CV_8UC1;
types[mhi_i][0] = types[mhi_ref_i][0] = CV_32FC1;
duration = exp(cvtest::randReal(rng)*max_log_duration);
timestamp = duration + cvtest::randReal(rng)*30.-10.;
}
int CV_MHIBaseTest::prepare_test_case( int test_case_idx )
{
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
if( code > 0 )
{
Mat& mat = test_mat[mhi_i][0];
mat += Scalar::all(duration);
cv::max(mat, 0, mat);
if( mhi_i != mhi_ref_i )
{
Mat& mat0 = test_mat[mhi_ref_i][0];
cvtest::copy( mat, mat0 );
}
}
return code;
}
///////////////////// update motion history ////////////////////////////
static void test_updateMHI( const Mat& silh, Mat& mhi, double timestamp, double duration )
{
int i, j;
float delbound = (float)(timestamp - duration);
for( i = 0; i < mhi.rows; i++ )
{
const uchar* silh_row = silh.ptr(i);
float* mhi_row = mhi.ptr<float>(i);
for( j = 0; j < mhi.cols; j++ )
{
if( silh_row[j] )
mhi_row[j] = (float)timestamp;
else if( mhi_row[j] < delbound )
mhi_row[j] = 0.f;
}
}
}
class CV_UpdateMHITest : public CV_MHIBaseTest
{
public:
CV_UpdateMHITest();
protected:
double get_success_error_level( int test_case_idx, int i, int j );
void run_func();
void prepare_to_validation( int );
};
CV_UpdateMHITest::CV_UpdateMHITest()
{
test_array[INPUT].push_back(NULL);
test_array[INPUT_OUTPUT].push_back(NULL);
test_array[REF_INPUT_OUTPUT].push_back(NULL);
mhi_i = INPUT_OUTPUT; mhi_ref_i = REF_INPUT_OUTPUT;
}
double CV_UpdateMHITest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
{
return 0;
}
void CV_UpdateMHITest::run_func()
{
cvUpdateMotionHistory( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], timestamp, duration );
}
void CV_UpdateMHITest::prepare_to_validation( int /*test_case_idx*/ )
{
test_updateMHI( test_mat[INPUT][0], test_mat[REF_INPUT_OUTPUT][0], timestamp, duration );
}
///////////////////// calc motion gradient ////////////////////////////
static void test_MHIGradient( const Mat& mhi, Mat& mask, Mat& orientation,
double delta1, double delta2, int aperture_size )
{
Point anchor( aperture_size/2, aperture_size/2 );
double limit = 1e-4*aperture_size*aperture_size;
Mat dx, dy, min_mhi, max_mhi;
Mat kernel = cvtest::calcSobelKernel2D( 1, 0, aperture_size );
cvtest::filter2D( mhi, dx, CV_32F, kernel, anchor, 0, BORDER_REPLICATE );
kernel = cvtest::calcSobelKernel2D( 0, 1, aperture_size );
cvtest::filter2D( mhi, dy, CV_32F, kernel, anchor, 0, BORDER_REPLICATE );
kernel = Mat::ones(aperture_size, aperture_size, CV_8U);
cvtest::erode(mhi, min_mhi, kernel, anchor, 0, BORDER_REPLICATE);
cvtest::dilate(mhi, max_mhi, kernel, anchor, 0, BORDER_REPLICATE);
if( delta1 > delta2 )
{
double t;
CV_SWAP( delta1, delta2, t );
}
for( int i = 0; i < mhi.rows; i++ )
{
uchar* mask_row = mask.ptr(i);
float* orient_row = orientation.ptr<float>(i);
const float* dx_row = dx.ptr<float>(i);
const float* dy_row = dy.ptr<float>(i);
const float* min_row = min_mhi.ptr<float>(i);
const float* max_row = max_mhi.ptr<float>(i);
for( int j = 0; j < mhi.cols; j++ )
{
double delta = max_row[j] - min_row[j];
double _dx = dx_row[j], _dy = dy_row[j];
if( delta1 <= delta && delta <= delta2 &&
(fabs(_dx) > limit || fabs(_dy) > limit) )
{
mask_row[j] = 1;
double angle = atan2( _dy, _dx ) * (180/CV_PI);
if( angle < 0 )
angle += 360.;
orient_row[j] = (float)angle;
}
else
{
mask_row[j] = 0;
orient_row[j] = 0.f;
}
}
}
}
class CV_MHIGradientTest : public CV_MHIBaseTest
{
public:
CV_MHIGradientTest();
protected:
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
double get_success_error_level( int test_case_idx, int i, int j );
void run_func();
void prepare_to_validation( int );
double delta1, delta2, delta_range_log;
int aperture_size;
};
CV_MHIGradientTest::CV_MHIGradientTest()
{
mhi_i = mhi_ref_i = INPUT;
test_array[INPUT].push_back(NULL);
test_array[OUTPUT].push_back(NULL);
test_array[OUTPUT].push_back(NULL);
test_array[REF_OUTPUT].push_back(NULL);
test_array[REF_OUTPUT].push_back(NULL);
delta1 = delta2 = 0;
aperture_size = 0;
delta_range_log = 4;
}
void CV_MHIGradientTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
{
RNG& rng = ts->get_rng();
CV_MHIBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_8UC1;
types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_32FC1;
delta1 = exp(cvtest::randReal(rng)*delta_range_log + 1.);
delta2 = exp(cvtest::randReal(rng)*delta_range_log + 1.);
aperture_size = (cvtest::randInt(rng)%3)*2+3;
//duration = exp(cvtest::randReal(rng)*max_log_duration);
//timestamp = duration + cvtest::randReal(rng)*30.-10.;
}
double CV_MHIGradientTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int j )
{
return j == 0 ? 0 : 2e-1;
}
void CV_MHIGradientTest::run_func()
{
cvCalcMotionGradient( test_array[INPUT][0], test_array[OUTPUT][0],
test_array[OUTPUT][1], delta1, delta2, aperture_size );
}
void CV_MHIGradientTest::prepare_to_validation( int /*test_case_idx*/ )
{
test_MHIGradient( test_mat[INPUT][0], test_mat[REF_OUTPUT][0],
test_mat[REF_OUTPUT][1], delta1, delta2, aperture_size );
test_mat[REF_OUTPUT][0] += Scalar::all(1);
test_mat[OUTPUT][0] += Scalar::all(1);
}
////////////////////// calc global orientation /////////////////////////
static double test_calcGlobalOrientation( const Mat& orient, const Mat& mask,
const Mat& mhi, double timestamp, double duration )
{
const int HIST_SIZE = 12;
int y, x;
int histogram[HIST_SIZE];
int max_bin = 0;
double base_orientation = 0, delta_orientation = 0, weight = 0;
double low_time, global_orientation;
memset( histogram, 0, sizeof( histogram ));
timestamp = 0;
for( y = 0; y < orient.rows; y++ )
{
const float* orient_data = orient.ptr<float>(y);
const uchar* mask_data = mask.ptr(y);
const float* mhi_data = mhi.ptr<float>(y);
for( x = 0; x < orient.cols; x++ )
if( mask_data[x] )
{
int bin = cvFloor( (orient_data[x]*HIST_SIZE)/360 );
histogram[bin < 0 ? 0 : bin >= HIST_SIZE ? HIST_SIZE-1 : bin]++;
if( mhi_data[x] > timestamp )
timestamp = mhi_data[x];
}
}
low_time = timestamp - duration;
for( x = 1; x < HIST_SIZE; x++ )
{
if( histogram[x] > histogram[max_bin] )
max_bin = x;
}
base_orientation = ((double)max_bin*360)/HIST_SIZE;
for( y = 0; y < orient.rows; y++ )
{
const float* orient_data = orient.ptr<float>(y);
const float* mhi_data = mhi.ptr<float>(y);
const uchar* mask_data = mask.ptr(y);
for( x = 0; x < orient.cols; x++ )
{
if( mask_data[x] && mhi_data[x] > low_time )
{
double diff = orient_data[x] - base_orientation;
double delta_weight = (((mhi_data[x] - low_time)/duration)*254 + 1)/255;
if( diff < -180 ) diff += 360;
if( diff > 180 ) diff -= 360;
if( delta_weight > 0 && fabs(diff) < 45 )
{
delta_orientation += diff*delta_weight;
weight += delta_weight;
}
}
}
}
if( weight == 0 )
global_orientation = base_orientation;
else
{
global_orientation = base_orientation + delta_orientation/weight;
if( global_orientation < 0 ) global_orientation += 360;
if( global_orientation > 360 ) global_orientation -= 360;
}
return global_orientation;
}
class CV_MHIGlobalOrientTest : public CV_MHIBaseTest
{
public:
CV_MHIGlobalOrientTest();
protected:
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
double get_success_error_level( int test_case_idx, int i, int j );
int validate_test_results( int test_case_idx );
void run_func();
double angle, min_angle, max_angle;
};
CV_MHIGlobalOrientTest::CV_MHIGlobalOrientTest()
{
mhi_i = mhi_ref_i = INPUT;
test_array[INPUT].push_back(NULL);
test_array[INPUT].push_back(NULL);
test_array[INPUT].push_back(NULL);
min_angle = max_angle = 0;
}
void CV_MHIGlobalOrientTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
{
RNG& rng = ts->get_rng();
CV_MHIBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
CvSize size = sizes[INPUT][0];
size.width = MAX( size.width, 16 );
size.height = MAX( size.height, 16 );
sizes[INPUT][0] = sizes[INPUT][1] = sizes[INPUT][2] = size;
types[INPUT][1] = CV_8UC1; // mask
types[INPUT][2] = CV_32FC1; // orientation
min_angle = cvtest::randReal(rng)*359.9;
max_angle = cvtest::randReal(rng)*359.9;
if( min_angle >= max_angle )
{
double t;
CV_SWAP( min_angle, max_angle, t );
}
max_angle += 0.1;
duration = exp(cvtest::randReal(rng)*max_log_duration);
timestamp = duration + cvtest::randReal(rng)*30.-10.;
}
void CV_MHIGlobalOrientTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
{
CV_MHIBaseTest::get_minmax_bounds( i, j, type, low, high );
if( i == INPUT && j == 2 )
{
low = Scalar::all(min_angle);
high = Scalar::all(max_angle);
}
}
double CV_MHIGlobalOrientTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
{
return 15;
}
void CV_MHIGlobalOrientTest::run_func()
{
angle = cvCalcGlobalOrientation( test_array[INPUT][2], test_array[INPUT][1],
test_array[INPUT][0], timestamp, duration );
}
int CV_MHIGlobalOrientTest::validate_test_results( int test_case_idx )
{
//printf("%d. rows=%d, cols=%d, nzmask=%d\n", test_case_idx, test_mat[INPUT][1].rows, test_mat[INPUT][1].cols,
// cvCountNonZero(test_array[INPUT][1]));
double ref_angle = test_calcGlobalOrientation( test_mat[INPUT][2], test_mat[INPUT][1],
test_mat[INPUT][0], timestamp, duration );
double err_level = get_success_error_level( test_case_idx, 0, 0 );
int code = cvtest::TS::OK;
int nz = cvCountNonZero( test_array[INPUT][1] );
if( nz > 32 && !(min_angle - err_level <= angle &&
max_angle + err_level >= angle) &&
!(min_angle - err_level <= angle+360 &&
max_angle + err_level >= angle+360) )
{
ts->printf( cvtest::TS::LOG, "The angle=%g is outside (%g,%g) range\n",
angle, min_angle - err_level, max_angle + err_level );
code = cvtest::TS::FAIL_BAD_ACCURACY;
}
else if( fabs(angle - ref_angle) > err_level &&
fabs(360 - fabs(angle - ref_angle)) > err_level )
{
ts->printf( cvtest::TS::LOG, "The angle=%g differs too much from reference value=%g\n",
angle, ref_angle );
code = cvtest::TS::FAIL_BAD_ACCURACY;
}
if( code < 0 )
ts->set_failed_test_info( code );
return code;
}
TEST(Video_MHIUpdate, accuracy) { CV_UpdateMHITest test; test.safe_run(); }
TEST(Video_MHIGradient, accuracy) { CV_MHIGradientTest test; test.safe_run(); }
TEST(Video_MHIGlobalOrient, accuracy) { CV_MHIGlobalOrientTest test; test.safe_run(); }

View File

@@ -0,0 +1,355 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
#include <string>
#include <iostream>
#include <fstream>
#include <iterator>
#include <limits>
using namespace cv;
using namespace std;
class CV_OptFlowTest : public cvtest::BaseTest
{
public:
CV_OptFlowTest();
~CV_OptFlowTest();
protected:
void run(int);
bool runDense(const Point& shift = Point(3, 0));
bool runSparse();
};
CV_OptFlowTest::CV_OptFlowTest() {}
CV_OptFlowTest::~CV_OptFlowTest() {}
Mat copnvert2flow(const Mat& velx, const Mat& vely)
{
Mat flow(velx.size(), CV_32FC2);
for(int y = 0 ; y < flow.rows; ++y)
for(int x = 0 ; x < flow.cols; ++x)
flow.at<Point2f>(y, x) = Point2f(velx.at<float>(y, x), vely.at<float>(y, x));
return flow;
}
void calcOpticalFlowLK( const Mat& prev, const Mat& curr, Size winSize, Mat& flow )
{
Mat velx(prev.size(), CV_32F), vely(prev.size(), CV_32F);
CvMat cvvelx = velx; CvMat cvvely = vely;
CvMat cvprev = prev; CvMat cvcurr = curr;
cvCalcOpticalFlowLK( &cvprev, &cvcurr, winSize, &cvvelx, &cvvely );
flow = copnvert2flow(velx, vely);
}
void calcOpticalFlowBM( const Mat& prev, const Mat& curr, Size bSize, Size shiftSize, Size maxRange, int usePrevious, Mat& flow )
{
Size sz((curr.cols - bSize.width)/shiftSize.width, (curr.rows - bSize.height)/shiftSize.height);
Mat velx(sz, CV_32F), vely(sz, CV_32F);
CvMat cvvelx = velx; CvMat cvvely = vely;
CvMat cvprev = prev; CvMat cvcurr = curr;
cvCalcOpticalFlowBM( &cvprev, &cvcurr, bSize, shiftSize, maxRange, usePrevious, &cvvelx, &cvvely);
flow = copnvert2flow(velx, vely);
}
void calcOpticalFlowHS( const Mat& prev, const Mat& curr, int usePrevious, double lambda, TermCriteria criteria, Mat& flow)
{
Mat velx(prev.size(), CV_32F), vely(prev.size(), CV_32F);
CvMat cvvelx = velx; CvMat cvvely = vely;
CvMat cvprev = prev; CvMat cvcurr = curr;
cvCalcOpticalFlowHS( &cvprev, &cvcurr, usePrevious, &cvvelx, &cvvely, lambda, criteria );
flow = copnvert2flow(velx, vely);
}
void calcAffineFlowPyrLK( const Mat& prev, const Mat& curr,
const vector<Point2f>& prev_features, vector<Point2f>& curr_features,
vector<uchar>& status, vector<float>& track_error, vector<float>& matrices,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS,30, 0.01),
Size win_size = Size(15, 15), int level = 3, int flags = 0)
{
CvMat cvprev = prev;
CvMat cvcurr = curr;
size_t count = prev_features.size();
curr_features.resize(count);
status.resize(count);
track_error.resize(count);
matrices.resize(count * 6);
cvCalcAffineFlowPyrLK( &cvprev, &cvcurr, 0, 0,
(const CvPoint2D32f*)&prev_features[0], (CvPoint2D32f*)&curr_features[0], &matrices[0],
(int)count, win_size, level, (char*)&status[0], &track_error[0], criteria, flags );
}
double showFlowAndCalcError(const string& name, const Mat& gray, const Mat& flow,
const Rect& where, const Point& d,
bool showImages = false, bool writeError = false)
{
const int mult = 16;
if (showImages)
{
Mat tmp, cflow;
resize(gray, tmp, gray.size() * mult, 0, 0, INTER_NEAREST);
cvtColor(tmp, cflow, CV_GRAY2BGR);
const float m2 = 0.3f;
const float minVel = 0.1f;
for(int y = 0; y < flow.rows; ++y)
for(int x = 0; x < flow.cols; ++x)
{
Point2f f = flow.at<Point2f>(y, x);
if (f.x * f.x + f.y * f.y > minVel * minVel)
{
Point p1 = Point(x, y) * mult;
Point p2 = Point(cvRound((x + f.x*m2) * mult), cvRound((y + f.y*m2) * mult));
line(cflow, p1, p2, CV_RGB(0, 255, 0));
circle(cflow, Point(x, y) * mult, 2, CV_RGB(255, 0, 0));
}
}
rectangle(cflow, (where.tl() + d) * mult, (where.br() + d - Point(1,1)) * mult, CV_RGB(0, 0, 255));
namedWindow(name, 1); imshow(name, cflow);
}
double angle = atan2((float)d.y, (float)d.x);
double error = 0;
bool all = true;
Mat inner = flow(where);
for(int y = 0; y < inner.rows; ++y)
for(int x = 0; x < inner.cols; ++x)
{
const Point2f f = inner.at<Point2f>(y, x);
if (f.x == 0 && f.y == 0)
continue;
all = false;
double a = atan2(f.y, f.x);
error += fabs(angle - a);
}
double res = all ? numeric_limits<double>::max() : error / (inner.cols * inner.rows);
if (writeError)
cout << "Error " + name << " = " << res << endl;
return res;
}
Mat generateImage(const Size& sz, bool doBlur = true)
{
RNG rng;
Mat mat(sz, CV_8U);
mat = Scalar(0);
for(int y = 0; y < mat.rows; ++y)
for(int x = 0; x < mat.cols; ++x)
mat.at<uchar>(y, x) = (uchar)rng;
if (doBlur)
blur(mat, mat, Size(3, 3));
return mat;
}
Mat generateSample(const Size& sz)
{
Mat smpl(sz, CV_8U);
smpl = Scalar(0);
Point sc(smpl.cols/2, smpl.rows/2);
rectangle(smpl, Point(0,0), sc - Point(1,1), Scalar(255), CV_FILLED);
rectangle(smpl, sc, Point(smpl.cols, smpl.rows), Scalar(255), CV_FILLED);
return smpl;
}
bool CV_OptFlowTest::runDense(const Point& d)
{
Size matSize(40, 40);
Size movSize(8, 8);
Mat smpl = generateSample(movSize);
Mat prev = generateImage(matSize);
Mat curr = prev.clone();
Rect rect(Point(prev.cols/2, prev.rows/2) - Point(movSize.width/2, movSize.height/2), movSize);
Mat flowLK, flowBM, flowHS, flowFB, flowFB_G, flowBM_received, m1;
m1 = prev(rect); smpl.copyTo(m1);
m1 = curr(Rect(rect.tl() + d, rect.br() + d)); smpl.copyTo(m1);
calcOpticalFlowLK( prev, curr, Size(15, 15), flowLK);
calcOpticalFlowBM( prev, curr, Size(15, 15), Size(1, 1), Size(15, 15), 0, flowBM_received);
calcOpticalFlowHS( prev, curr, 0, 5, TermCriteria(TermCriteria::MAX_ITER, 400, 0), flowHS);
calcOpticalFlowFarneback( prev, curr, flowFB, 0.5, 3, std::max(d.x, d.y) + 10, 100, 6, 2, 0);
calcOpticalFlowFarneback( prev, curr, flowFB_G, 0.5, 3, std::max(d.x, d.y) + 10, 100, 6, 2, OPTFLOW_FARNEBACK_GAUSSIAN);
flowBM.create(prev.size(), CV_32FC2);
flowBM = Scalar(0);
Point origin((flowBM.cols - flowBM_received.cols)/2, (flowBM.rows - flowBM_received.rows)/2);
Mat wcp = flowBM(Rect(origin, flowBM_received.size()));
flowBM_received.copyTo(wcp);
double errorLK = showFlowAndCalcError("LK", prev, flowLK, rect, d);
double errorBM = showFlowAndCalcError("BM", prev, flowBM, rect, d);
double errorFB = showFlowAndCalcError("FB", prev, flowFB, rect, d);
double errorFBG = showFlowAndCalcError("FBG", prev, flowFB_G, rect, d);
double errorHS = showFlowAndCalcError("HS", prev, flowHS, rect, d); (void)errorHS;
//waitKey();
const double thres = 0.2;
if (errorLK > thres || errorBM > thres || errorFB > thres || errorFBG > thres /*|| errorHS > thres */)
{
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
return false;
}
return true;
}
bool CV_OptFlowTest::runSparse()
{
Mat prev = imread(string(ts->get_data_path()) + "optflow/rock_1.bmp", 0);
Mat next = imread(string(ts->get_data_path()) + "optflow/rock_2.bmp", 0);
if (prev.empty() || next.empty())
{
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
return false;
}
Mat cprev, cnext;
cvtColor(prev, cprev, CV_GRAY2BGR);
cvtColor(next, cnext, CV_GRAY2BGR);
vector<Point2f> prev_pts;
vector<Point2f> next_ptsOpt;
vector<Point2f> next_ptsAff;
vector<uchar> status_Opt;
vector<uchar> status_Aff;
vector<float> error;
vector<float> matrices;
Size netSize(10, 10);
Point2f center = Point(prev.cols/2, prev.rows/2);
for(int i = 0 ; i < netSize.width; ++i)
for(int j = 0 ; j < netSize.width; ++j)
{
Point2f p(i * float(prev.cols)/netSize.width, j * float(prev.rows)/netSize.height);
prev_pts.push_back((p - center) * 0.5f + center);
}
calcOpticalFlowPyrLK( prev, next, prev_pts, next_ptsOpt, status_Opt, error );
calcAffineFlowPyrLK ( prev, next, prev_pts, next_ptsAff, status_Aff, error, matrices);
const double expected_shift = 25;
const double thres = 1;
for(size_t i = 0; i < prev_pts.size(); ++i)
{
circle(cprev, prev_pts[i], 2, CV_RGB(255, 0, 0));
if (status_Opt[i])
{
circle(cnext, next_ptsOpt[i], 2, CV_RGB(0, 0, 255));
Point2f shift = prev_pts[i] - next_ptsOpt[i];
double n = sqrt(shift.ddot(shift));
if (fabs(n - expected_shift) > thres)
{
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
return false;
}
}
if (status_Aff[i])
{
circle(cnext, next_ptsAff[i], 4, CV_RGB(0, 255, 0));
Point2f shift = prev_pts[i] - next_ptsAff[i];
double n = sqrt(shift.ddot(shift));
if (fabs(n - expected_shift) > thres)
{
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
return false;
}
}
}
/*namedWindow("P"); imshow("P", cprev);
namedWindow("N"); imshow("N", cnext);
waitKey();*/
return true;
}
void CV_OptFlowTest::run( int /* start_from */)
{
if (!runDense(Point(3, 0)))
return;
if (!runDense(Point(0, 3)))
return;
//if (!runDense(Point(3, 3))) return; //probably LK works incorrectly in this case.
if (!runSparse())
return;
ts->set_failed_test_info(cvtest::TS::OK);
}
TEST(Video_OpticalFlow, accuracy) { CV_OptFlowTest test; test.safe_run(); }

View File

@@ -0,0 +1,214 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
/* ///////////////////// pyrlk_test ///////////////////////// */
class CV_OptFlowPyrLKTest : public cvtest::BaseTest
{
public:
CV_OptFlowPyrLKTest();
protected:
void run(int);
};
CV_OptFlowPyrLKTest::CV_OptFlowPyrLKTest() {}
void CV_OptFlowPyrLKTest::run( int )
{
int code = cvtest::TS::OK;
const double success_error_level = 0.2;
const int bad_points_max = 2;
/* test parameters */
double max_err = 0., sum_err = 0;
int pt_cmpd = 0;
int pt_exceed = 0;
int merr_i = 0, merr_j = 0, merr_k = 0;
char filename[1000];
CvPoint2D32f *u = 0, *v = 0, *v2 = 0;
CvMat *_u = 0, *_v = 0, *_v2 = 0;
char* status = 0;
IplImage* imgI = 0;
IplImage* imgJ = 0;
int n = 0, i = 0;
sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "lk_prev.dat" );
_u = (CvMat*)cvLoad( filename );
if( !_u )
{
ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
goto _exit_;
}
sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "lk_next.dat" );
_v = (CvMat*)cvLoad( filename );
if( !_v )
{
ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
goto _exit_;
}
if( _u->cols != 2 || CV_MAT_TYPE(_u->type) != CV_32F ||
_v->cols != 2 || CV_MAT_TYPE(_v->type) != CV_32F || _v->rows != _u->rows )
{
ts->printf( cvtest::TS::LOG, "the loaded matrices of points are not valid\n" );
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
goto _exit_;
}
u = (CvPoint2D32f*)_u->data.fl;
v = (CvPoint2D32f*)_v->data.fl;
/* allocate adidtional buffers */
_v2 = cvCloneMat( _u );
v2 = (CvPoint2D32f*)_v2->data.fl;
/* read first image */
sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "rock_1.bmp" );
imgI = cvLoadImage( filename, -1 );
if( !imgI )
{
ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
goto _exit_;
}
/* read second image */
sprintf( filename, "%soptflow/%s", ts->get_data_path().c_str(), "rock_2.bmp" );
imgJ = cvLoadImage( filename, -1 );
if( !imgJ )
{
ts->printf( cvtest::TS::LOG, "could not read %s\n", filename );
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
goto _exit_;
}
n = _u->rows;
status = (char*)cvAlloc(n*sizeof(status[0]));
/* calculate flow */
cvCalcOpticalFlowPyrLK( imgI, imgJ, 0, 0, u, v2, n, cvSize( 20, 20 ),
4, status, 0, cvTermCriteria( CV_TERMCRIT_ITER|
CV_TERMCRIT_EPS, 30, 0.01f ), 0 );
/* compare results */
for( i = 0; i < n; i++ )
{
if( status[i] != 0 )
{
double err;
if( cvIsNaN(v[i].x) )
{
merr_j++;
continue;
}
err = fabs(v2[i].x - v[i].x) + fabs(v2[i].y - v[i].y);
if( err > max_err )
{
max_err = err;
merr_i = i;
}
pt_exceed += err > success_error_level;
if( pt_exceed > bad_points_max )
{
ts->printf( cvtest::TS::LOG,
"The number of poorly tracked points is too big (>=%d)\n", pt_exceed );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto _exit_;
}
sum_err += err;
pt_cmpd++;
}
else
{
if( !cvIsNaN( v[i].x ))
{
merr_i = i;
merr_k++;
ts->printf( cvtest::TS::LOG, "The algorithm lost the point #%d\n", i );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto _exit_;
}
}
}
if( max_err > 1 )
{
ts->printf( cvtest::TS::LOG, "Maximum tracking error is too big (=%g)\n", max_err );
code = cvtest::TS::FAIL_BAD_ACCURACY;
goto _exit_;
}
_exit_:
cvFree( &status );
cvReleaseMat( &_u );
cvReleaseMat( &_v );
cvReleaseMat( &_v2 );
cvReleaseImage( &imgI );
cvReleaseImage( &imgJ );
if( code < 0 )
ts->set_failed_test_info( code );
}
TEST(Video_OpticalFlowPyrLK, accuracy) { CV_OptFlowPyrLKTest test; test.safe_run(); }
/* End of file. */

View File

@@ -0,0 +1 @@
#include "test_precomp.hpp"

View File

@@ -0,0 +1,11 @@
#ifndef __OPENCV_TEST_PRECOMP_HPP__
#define __OPENCV_TEST_PRECOMP_HPP__
#include "opencv2/ts/ts.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/video/tracking.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#endif