Commit 07fa62f0 authored by Alexander Reshetnikov's avatar Alexander Reshetnikov

some design code changes in new tests

parent ea5d0155
...@@ -30,41 +30,24 @@ using namespace std; ...@@ -30,41 +30,24 @@ using namespace std;
class CV_HomographyTest: public cvtest::ArrayTest class CV_HomographyTest: public cvtest::ArrayTest
{ {
public: public:
CV_HomographyTest();
CV_HomographyTest(); ~CV_HomographyTest();
~CV_HomographyTest();
void run (int);
int read_params( CvFileStorage* fs );
void fill_array( int test_case_idx, int i, int j, Mat& arr ); protected:
int prepare_test_case( int test_case_idx );
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types ); int method;
void run (int); int image_size;
double reproj_threshold;
bool check_matrix (const Mat& H); double sigma;
bool check_transform (const Mat& src, const Mat& dst, const Mat& H);
private:
void prepare_to_validation( int test_case_idx );
protected:
int method;
int image_size;
int square_size;
double reproj_threshold;
double sigma;
bool test_cpp;
double get_success_error_level( int test_case_idx, int i, int j );
void test_projectPoints(Mat& src_2d, Mat& dst_2d, const Mat& H, RNG* rng, double sigma); // checking for quality of perpective transformation
private:
float max_diff, max_2diff; float max_diff, max_2diff;
bool check_matrix_size(const cv::Mat& H); bool check_matrix_size(const cv::Mat& H);
bool check_matrix_diff(const cv::Mat& original, const cv::Mat& found, const int norm_type, double &diff); bool check_matrix_diff(const cv::Mat& original, const cv::Mat& found, const int norm_type, double &diff);
// bool check_reproj_error(const cv::Mat& src_3d, const cv::Mat& dst_3d, const int norm_type = NORM_L2); int check_ransac_mask_1(const Mat& src, const Mat& mask);
int check_ransac_mask_1(const Mat& src, const Mat& mask);
int check_ransac_mask_2(const Mat& original_mask, const Mat& found_mask); int check_ransac_mask_2(const Mat& original_mask, const Mat& found_mask);
void print_information_1(int j, int N, int method, const Mat& H); void print_information_1(int j, int N, int method, const Mat& H);
...@@ -75,934 +58,472 @@ class CV_HomographyTest: public cvtest::ArrayTest ...@@ -75,934 +58,472 @@ class CV_HomographyTest: public cvtest::ArrayTest
void print_information_6(int j, int N, int k, double diff, bool value); void print_information_6(int j, int N, int k, double diff, bool value);
void print_information_7(int j, int N, int k, double diff, bool original_value, bool found_value); void print_information_7(int j, int N, int k, double diff, bool original_value, bool found_value);
void print_information_8(int j, int N, int k, int l, double diff); void print_information_8(int j, int N, int k, int l, double diff);
void check_transform_quality(cv::InputArray src_points, cv::InputArray dst_poits, const cv::Mat& H, const int norm_type = NORM_L2);
void check_transform_quality(const cv::InputArray src_points, const vector <cv::Point2f> dst_points, const cv::Mat& H, const int norm_type = NORM_L2);
void check_transform_quality(const vector <cv::Point2f> src_points, const cv::InputArray dst_points, const cv::Mat& H, const int norm_type = NORM_L2);
void check_transform_quality(const vector <cv::Point2f> src_points, const vector <cv::Point2f> dst_points, const cv::Mat& H, const int norm_type = NORM_L2);
}; };
CV_HomographyTest::CV_HomographyTest() : max_diff(1e-2), max_2diff(2e-2) CV_HomographyTest::CV_HomographyTest() : max_diff(1e-2), max_2diff(2e-2)
{ {
test_array[INPUT].push_back(NULL); method = 0;
test_array[INPUT].push_back(NULL); image_size = 1e+2;
test_array[INPUT].push_back(NULL); reproj_threshold = 3.0;
test_array[INPUT].push_back(NULL); sigma = 0.01;
test_array[INPUT].push_back(NULL);
test_array[INPUT].push_back(NULL);
test_array[TEMP].push_back(NULL);
test_array[TEMP].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);
element_wise_relative_error = false;
method = 0;
image_size = 1e+2;
reproj_threshold = 3.0;
sigma = 0.01;
test_cpp = false;
} }
CV_HomographyTest::~CV_HomographyTest() {} CV_HomographyTest::~CV_HomographyTest() {}
void CV_HomographyTest::get_test_array_types_and_sizes( int /*test_case_idx*/, vector<vector<Size> >& sizes, vector<vector<int> >& types ) bool CV_HomographyTest::check_matrix_size(const cv::Mat& H)
{ {
RNG& rng = ts->get_rng(); return (H.rows == 3) && (H.cols == 3);
int pt_depth = CV_32F; }
double pt_count_exp = cvtest::randReal(rng)*6 + 1;
int pt_count = cvRound(exp(pt_count_exp));
/* dims = cvtest::randInt(rng) % 2 + 2;
method = 1 << (cvtest::randInt(rng) % 4);
if( method == CV_FM_7POINT )
pt_count = 7;
else
{
pt_count = MAX( pt_count, 8 + (method == CV_FM_8POINT) );
if( pt_count >= 8 && cvtest::randInt(rng) % 2 )
method |= CV_FM_8POINT;
} */
types[INPUT][0] = CV_MAKETYPE(pt_depth, 2);
types[INPUT][1] = types[INPUT][0];
types[OUTPUT][0] = CV_MAKETYPE(pt_depth, 1);
/* if( cvtest::randInt(rng) % 2 )
sizes[INPUT][0] = cvSize(pt_count, dims);
else
{
sizes[INPUT][0] = cvSize(dims, pt_count);
if( cvtest::randInt(rng) % 2 )
{
types[INPUT][0] = CV_MAKETYPE(pt_depth, dims);
if( cvtest::randInt(rng) % 2 )
sizes[INPUT][0] = cvSize(pt_count, 1);
else
sizes[INPUT][0] = cvSize(1, pt_count);
}
}
sizes[INPUT][1] = sizes[INPUT][0];
types[INPUT][1] = types[INPUT][0];
sizes[INPUT][2] = cvSize(pt_count, 1 );
types[INPUT][2] = CV_64FC3;
sizes[INPUT][3] = cvSize(4,3);
types[INPUT][3] = CV_64FC1;
sizes[INPUT][4] = sizes[INPUT][5] = cvSize(3,3); bool CV_HomographyTest::check_matrix_diff(const cv::Mat& original, const cv::Mat& found, const int norm_type, double &diff)
types[INPUT][4] = types[INPUT][5] = CV_MAKETYPE(CV_64F, 1); {
diff = cv::norm(original, found, norm_type);
return diff <= max_diff;
}
sizes[TEMP][0] = cvSize(3,3); int CV_HomographyTest::check_ransac_mask_1(const Mat& src, const Mat& mask)
types[TEMP][0] = CV_64FC1; {
sizes[TEMP][1] = cvSize(pt_count,1); if (!(mask.cols == 1) && (mask.rows == src.cols)) return 1;
types[TEMP][1] = CV_8UC1; if (countNonZero(mask) < mask.rows) return 2;
for (int i = 0; i < mask.rows; ++i) if (mask.at<uchar>(i, 0) > 1) return 3;
return 0;
}
sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(3,1); int CV_HomographyTest::check_ransac_mask_2(const Mat& original_mask, const Mat& found_mask)
types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1; {
sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = cvSize(pt_count,1); if (!(found_mask.cols == 1) && (found_mask.rows == original_mask.rows)) return 1;
types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_8UC1; for (int i = 0; i < found_mask.rows; ++i) if (found_mask.at<uchar>(i, 0) > 1) return 2;
return 0;
test_cpp = (cvtest::randInt(rng) & 256) == 0;
*/
} }
int CV_HomographyTest::read_params(CvFileStorage *fs) void CV_HomographyTest::print_information_1(int j, int N, int method, const Mat& H)
{ {
int code = cvtest::ArrayTest::read_params(fs); cout << endl; cout << "Checking for homography matrix sizes..." << endl; cout << endl;
return code; cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Count of points: " << N << endl; cout << endl;
cout << "Method: "; if (method == 0) cout << 0; else if (method == 8) cout << "RANSAC"; else cout << "LMEDS"; cout << endl;
cout << "Homography matrix:" << endl; cout << endl;
cout << H << endl; cout << endl;
cout << "Number of rows: " << H.rows << " Number of cols: " << H.cols << endl; cout << endl;
} }
double CV_HomographyTest::get_success_error_level(int test_case_idx, int i, int j) void CV_HomographyTest::print_information_2(int j, int N, int method, const Mat& H, const Mat& H_res, int k, double diff)
{ {
return max_diff; cout << endl; cout << "Checking for accuracy of homography matrix computing..." << endl; cout << endl;
cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Count of points: " << N << endl; cout << endl;
cout << "Method: "; if (method == 0) cout << 0; else if (method == 8) cout << "RANSAC"; else cout << "LMEDS"; cout << endl;
cout << "Original matrix:" << endl; cout << endl;
cout << H << endl; cout << endl;
cout << "Found matrix:" << endl; cout << endl;
cout << H_res << endl; cout << endl;
cout << "Norm type using in criteria: "; if (NORM_TYPE[k] == 1) cout << "INF"; else if (NORM_TYPE[k] == 2) cout << "L1"; else cout << "L2"; cout << endl;
cout << "Difference between matrices: " << diff << endl;
cout << "Maximum allowed difference: " << max_diff << endl; cout << endl;
} }
void CV_HomographyTest::fill_array( int test_case_idx, int i, int j, Mat& arr ) void CV_HomographyTest::print_information_3(int j, int N, const Mat& mask)
{ {
double t[9]={0}; cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;
RNG& rng = ts->get_rng(); cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Count of points: " << N << endl; cout << endl;
cout << "Method: RANSAC" << endl;
cout << "Found mask:" << endl; cout << endl;
cout << mask << endl; cout << endl;
cout << "Number of rows: " << mask.rows << " Number of cols: " << mask.cols << endl; cout << endl;
}
if ( i != INPUT ) void CV_HomographyTest::print_information_4(int method, int j, int N, int k, int l, double diff)
{ {
cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr ); cout << endl; cout << "Checking for accuracy of reprojection error computing..." << endl; cout << endl;
return; cout << "Method: "; if (method == 0) cout << 0 << endl; else cout << "CV_LMEDS" << endl;
} cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Sigma of normal noise: " << sigma << endl;
cout << "Count of points: " << N << endl;
cout << "Number of point: " << k << endl;
cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;
cout << "Difference with noise of point: " << diff << endl;
cout << "Maxumum allowed difference: " << max_2diff << endl; cout << endl;
}
switch( j ) void CV_HomographyTest::print_information_5(int method, int j, int N, int l, double diff)
{ {
case 0: cout << endl; cout << "Checking for accuracy of reprojection error computing..." << endl; cout << endl;
case 1: cout << "Method: "; if (method == 0) cout << 0 << endl; else cout << "CV_LMEDS" << endl;
return; // fill them later in prepare_test_case cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
case 2: cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
{ cout << "Sigma of normal noise: " << sigma << endl;
double* p = arr.ptr<double>(); cout << "Count of points: " << N << endl;
for( i = 0; i < arr.cols*3; i += 3 ) cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;
{ cout << "Difference with noise of points: " << diff << endl;
/* p[i] = cvtest::randReal(rng)*square_size; cout << "Maxumum allowed difference: " << max_diff << endl; cout << endl;
p[i+1] = cvtest::randReal(rng)*square_size;
p[i+2] = cvtest::randReal(rng)*square_size + square_size; */
}
}
break;
case 3:
{
double r[3];
Mat rot_vec( 3, 1, CV_64F, r );
Mat rot_mat( 3, 3, CV_64F, t, 4*sizeof(t[0]) );
r[0] = cvtest::randReal(rng)*CV_PI*2;
r[1] = cvtest::randReal(rng)*CV_PI*2;
r[2] = cvtest::randReal(rng)*CV_PI*2;
cvtest::Rodrigues( rot_vec, rot_mat );
/* t[3] = cvtest::randReal(rng)*square_size;
t[7] = cvtest::randReal(rng)*square_size;
t[11] = cvtest::randReal(rng)*square_size; */
Mat( 3, 4, CV_64F, t ).convertTo(arr, arr.type());
}
break;
case 4:
case 5:
{
/* t[0] = t[4] = cvtest::randReal(rng)*(max_f - min_f) + min_f;
t[2] = (img_size*0.5 + cvtest::randReal(rng)*4. - 2.)*t[0];
t[5] = (img_size*0.5 + cvtest::randReal(rng)*4. - 2.)*t[4];
t[8] = 1.0f;
Mat( 3, 3, CV_64F, t ).convertTo( arr, arr.type() ); */
break;
}
}
} }
int CV_HomographyTest::prepare_test_case(int test_case_idx) void CV_HomographyTest::print_information_6(int j, int N, int k, double diff, bool value)
{ {
int code = cvtest::ArrayTest::prepare_test_case(test_case_idx); cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;
cout << "Method: RANSAC" << endl;
if (code > 0) cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
{ cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
Mat& src = test_mat[INPUT][0]; cout << "Count of points: " << N << " " << endl;
RNG& rng = ts->get_rng(); cout << "Number of point: " << k << " " << endl;
cout << "Reprojection error for this point: " << diff << " " << endl;
float Hdata[] = { sqrt(2.0f)/2, -sqrt(2.0f)/2, 0.0f, cout << "Reprojection error threshold: " << reproj_threshold << " " << endl;
sqrt(2.0f)/2, sqrt(2.0f)/2, 0.0f, cout << "Value of found mask: "<< value << endl; cout << endl;
0.0f, 0.0f, 1.0f };
Mat H( 3, 3, CV_32F, Hdata );
cv::Mat dst(1, src.cols, CV_32FC2);
int k;
for( k = 0; k < 2; k++ )
{
const Mat& H = test_mat[OUTPUT][0];
Mat& dst = test_mat[INPUT][k == 0 ? 1 : 2];
for (int i = 0; i < src.cols; ++i)
{
float *s = src.ptr<float>()+2*i;
float *d = dst.ptr<float>()+2*i;
d[0] = Hdata[0]*s[0] + Hdata[1]*s[1] + Hdata[2];
d[1] = Hdata[3]*s[0] + Hdata[4]*s[1] + Hdata[5];
}
test_projectPoints( src, dst, H, &rng, sigma );
}
}
return code;
} }
static void test_convertHomogeneous( const Mat& _src, Mat& _dst ) void CV_HomographyTest::print_information_7(int j, int N, int k, double diff, bool original_value, bool found_value)
{ {
Mat src = _src, dst = _dst; cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;
cout << "Method: RANSAC" << endl;
int i, count, sdims, ddims; cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
int sstep1, sstep2, dstep1, dstep2; cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Count of points: " << N << " " << endl;
if( src.depth() != CV_64F ) _src.convertTo(src, CV_64F); cout << "Number of point: " << k << " " << endl;
cout << "Reprojection error for this point: " << diff << " " << endl;
if( dst.depth() != CV_64F ) dst.create(dst.size(), CV_MAKETYPE(CV_64F, _dst.channels())); cout << "Reprojection error threshold: " << reproj_threshold << " " << endl;
cout << "Value of original mask: "<< original_value << " Value of found mask: " << found_value << endl; cout << endl;
if( src.rows > src.cols ) }
{
count = src.rows;
sdims = src.channels()*src.cols;
sstep1 = (int)(src.step/sizeof(double));
sstep2 = 1;
}
else
{
count = src.cols;
sdims = src.channels()*src.rows;
if( src.rows == 1 )
{
sstep1 = sdims;
sstep2 = 1;
}
else
{
sstep1 = 1;
sstep2 = (int)(src.step/sizeof(double));
}
}
if( dst.rows > dst.cols )
{
if (count != dst.rows) ; // CV_Error should be here
CV_Assert( count == dst.rows );
ddims = dst.channels()*dst.cols;
dstep1 = (int)(dst.step/sizeof(double));
dstep2 = 1;
}
else
{
assert( count == dst.cols );
ddims = dst.channels()*dst.rows;
if( dst.rows == 1 )
{
dstep1 = ddims;
dstep2 = 1;
}
else
{
dstep1 = 1;
dstep2 = (int)(dst.step/sizeof(double));
}
}
double* s = src.ptr<double>(); void CV_HomographyTest::print_information_8(int j, int N, int k, int l, double diff)
double* d = dst.ptr<double>(); {
cout << endl; cout << "Checking for reprojection error of inlier..." << endl; cout << endl;
cout << "Method: RANSAC" << endl;
cout << "Sigma of normal noise: " << sigma << endl;
cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Count of points: " << N << " " << endl;
cout << "Number of point: " << k << " " << endl;
cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;
cout << "Difference with noise of point: " << diff << endl;
cout << "Maxumum allowed difference: " << max_2diff << endl; cout << endl;
}
if( sdims <= ddims ) void CV_HomographyTest::run(int)
{
for (size_t N = 4; N <= MAX_COUNT_OF_POINTS; ++N)
{ {
int wstep = dstep2*(ddims - 1); RNG& rng = ts->get_rng();
for( i = 0; i < count; i++, s += sstep1, d += dstep1 ) float *src_data = new float [2*N];
{
double x = s[0];
double y = s[sstep2];
d[wstep] = 1;
d[0] = x;
d[dstep2] = y;
if( sdims >= 3 ) for (size_t i = 0; i < N; ++i)
{ {
d[dstep2*2] = s[sstep2*2]; src_data[2*i] = (float)cvtest::randReal(rng)*image_size;
if( sdims == 4 ) src_data[2*i+1] = (float)cvtest::randReal(rng)*image_size;
d[dstep2*3] = s[sstep2*3];
}
} }
}
else
{
int wstep = sstep2*(sdims - 1);
for( i = 0; i < count; i++, s += sstep1, d += dstep1 ) cv::Mat src_mat_2f(1, N, CV_32FC2, src_data),
{ src_mat_2d(2, N, CV_32F, src_data),
double w = s[wstep]; src_mat_3d(3, N, CV_32F);
double x = s[0]; cv::Mat dst_mat_2f, dst_mat_2d, dst_mat_3d;
double y = s[sstep2];
w = w ? 1./w : 1; vector <Point2f> src_vec, dst_vec;
d[0] = x*w; for (size_t i = 0; i < N; ++i)
d[dstep2] = y*w; {
float *tmp = src_mat_2d.ptr<float>()+2*i;
src_mat_3d.at<float>(0, i) = tmp[0];
src_mat_3d.at<float>(1, i) = tmp[1];
src_mat_3d.at<float>(2, i) = 1.0f;
if( ddims == 3 ) src_vec.push_back(Point2f(tmp[0], tmp[1]));
d[dstep2*2] = s[sstep2*2]*w;
} }
}
if( dst.data != _dst.data ) double fi = cvtest::randReal(rng)*2*CV_PI;
dst.convertTo(_dst, _dst.depth());
}
void CV_HomographyTest::test_projectPoints( Mat& src_2d, Mat& dst, const Mat& H, RNG* rng, double sigma ) double t_x = cvtest::randReal(rng)*sqrt(image_size*1.0),
{ t_y = cvtest::randReal(rng)*sqrt(image_size*1.0);
if (!src_2d.isContinuous())
{
CV_Error(-1, "");
return;
}
cv::Mat src_3d(1, src_2d.cols, CV_32FC3);
for (int i = 0; i < src_2d.cols; ++i)
{
float *c_3d = src_3d.ptr<float>()+3*i;
float *c_2d = src_2d.ptr<float>()+2*i;
c_3d[0] = c_2d[0]; c_3d[1] = c_2d[1]; c_3d[2] = 1.0f;
}
cv::Mat dst_3d; gemm(H, src_3d, 1, Mat(), 0, dst_3d);
int i, count = src_2d.cols;
Mat noise;
if ( rng )
{
if( sigma == 0 ) rng = 0;
else
{
noise.create( 1, count, CV_32FC2 );
rng->fill(noise, RNG::NORMAL, Scalar::all(0), Scalar::all(sigma) );
}
}
cv::Mat dst_2d(1, count, CV_32FC2);
for (size_t i = 0; i < count; ++i)
{
float *c_3d = dst_3d.ptr<float>()+3*i;
float *c_2d = dst_2d.ptr<float>()+2*i;
c_2d[0] = c_3d[0]/c_3d[2];
c_2d[1] = c_3d[1]/c_3d[2];
}
Mat temp( 1, count, CV_32FC2 );
for( i = 0; i < count; i++ )
{
const double* M = src_2d.ptr<double>() + 2*i;
double* m = temp.ptr<double>() + 2*i;
double X = M[0], Y = M[1], Z = M[2];
double u = H.at<float>(0, 0)*X + H.at<float>(0, 1)*Y + H.at<float>(0, 2);
double v = H.at<float>(1, 0)*X + H.at<float>(1, 1)*Y + H.at<float>(1, 2);
double s = H.at<float>(2, 0)*X + H.at<float>(2, 1)*Y + H.at<float>(2, 2);
if( !noise.empty() )
{
u += noise.at<Point2f>(i).x*s;
v += noise.at<Point2f>(i).y*s;
}
m[0] = u;
m[1] = v;
m[2] = s;
}
test_convertHomogeneous( dst_2d, dst );
}
void CV_HomographyTest::prepare_to_validation(int test_case_idx) double Hdata[9] = { cos(fi), -sin(fi), t_x,
{ sin(fi), cos(fi), t_y,
const Mat& H = test_mat[INPUT][3]; 0.0f, 0.0f, 1.0f };
const Mat& A1 = test_mat[INPUT][4];
const Mat& A2 = test_mat[INPUT][5];
double h0[9], h[9];
Mat H0(3, 3, CV_32FC1, h0);
Mat invA1, invA2, T; cv::Mat H_64(3, 3, CV_64F, Hdata), H_32;
cv::invert(A1, invA1, CV_SVD); H_64.convertTo(H_32, CV_32F);
cv::invert(A2, invA2, CV_SVD);
double tx = H.at<double>(0, 2); dst_mat_3d = H_32*src_mat_3d;
double ty = H.at<double>(1, 2);
double tz = H.at<double>(2, 2);
// double _t_x[] = { 0, -tz, ty, tz, 0, -tx, -ty, tx, 0 }; dst_mat_2d.create(2, N, CV_32F); dst_mat_2f.create(1, N, CV_32FC2);
// F = (A2^-T)*[t]_x*R*(A1^-1) for (size_t i = 0; i < N; ++i)
/* cv::gemm( invA2, Mat( 3, 3, CV_64F, _t_x ), 1, Mat(), 0, T, CV_GEMM_A_T ); {
cv::gemm( R, invA1, 1, Mat(), 0, invA2 ); float *tmp_2f = dst_mat_2f.ptr<float>()+2*i;
cv::gemm( T, invA2, 1, Mat(), 0, F0 ); */ tmp_2f[0] = dst_mat_2d.at<float>(0, i) = dst_mat_3d.at<float>(0, i) /= dst_mat_3d.at<float>(2, i);
H0 *= 1./h0[8]; tmp_2f[1] = dst_mat_2d.at<float>(1, i) = dst_mat_3d.at<float>(1, i) /= dst_mat_3d.at<float>(2, i);
dst_mat_3d.at<float>(2, i) = 1.0f;
uchar* status = test_mat[TEMP][1].data; dst_vec.push_back(Point2f(tmp_2f[0], tmp_2f[1]));
double err_level = get_success_error_level( test_case_idx, OUTPUT, 1 ); }
uchar* mtfm1 = test_mat[REF_OUTPUT][1].data;
uchar* mtfm2 = test_mat[OUTPUT][1].data;
double* f_prop1 = (double*)test_mat[REF_OUTPUT][0].data;
double* f_prop2 = (double*)test_mat[OUTPUT][0].data;
int i, pt_count = test_mat[INPUT][2].cols; for (size_t i = 0; i < METHODS_COUNT; ++i)
Mat p1( 1, pt_count, CV_64FC2 ); {
Mat p2( 1, pt_count, CV_64FC2 ); method = METHOD[i];
switch (method)
{
case 0:
case CV_LMEDS:
{
Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, method),
cv::findHomography(src_mat_2f, dst_vec, method),
cv::findHomography(src_vec, dst_mat_2f, method),
cv::findHomography(src_vec, dst_vec, method) };
for (size_t j = 0; j < 4; ++j)
{
if (!check_matrix_size(H_res_64[j]))
{
print_information_1(j, N, method, H_res_64[j]);
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);
return;
}
double diff;
for (size_t k = 0; k < COUNT_NORM_TYPES; ++k)
if (!check_matrix_diff(H_64, H_res_64[j], NORM_TYPE[k], diff))
{
print_information_2(j, N, method, H_64, H_res_64[j], k, diff);
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF, MESSAGE_MATRIX_DIFF);
return;
}
}
continue;
}
case CV_RANSAC:
{
cv::Mat mask [4]; double diff;
Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, CV_RANSAC, reproj_threshold, mask[0]),
cv::findHomography(src_mat_2f, dst_vec, CV_RANSAC, reproj_threshold, mask[1]),
cv::findHomography(src_vec, dst_mat_2f, CV_RANSAC, reproj_threshold, mask[2]),
cv::findHomography(src_vec, dst_vec, CV_RANSAC, reproj_threshold, mask[3]) };
for (size_t j = 0; j < 4; ++j)
{
if (!check_matrix_size(H_res_64[j]))
{
print_information_1(j, N, method, H_res_64[j]);
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);
return;
}
for (size_t k = 0; k < COUNT_NORM_TYPES; ++k)
if (!check_matrix_diff(H_64, H_res_64[j], NORM_TYPE[k], diff))
{
print_information_2(j, N, method, H_64, H_res_64[j], k, diff);
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF, MESSAGE_MATRIX_DIFF);
return;
}
int code = check_ransac_mask_1(src_mat_2f, mask[j]);
if (code)
{
print_information_3(j, N, mask[j]);
switch (code)
{
case 1: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_1); break; }
case 2: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_2); break; }
case 3: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_3); break; }
default: break;
}
return;
}
test_convertHomogeneous( test_mat[INPUT][0], p1 ); }
test_convertHomogeneous( test_mat[INPUT][1], p2 );
cvtest::convert(test_mat[TEMP][0], H0, H.type()); continue;
}
if( method <= CV_FM_8POINT ) default: continue;
memset( status, 1, pt_count ); }
}
for( i = 0; i < pt_count; i++ ) Mat noise_2f(1, N, CV_32FC2);
{ rng.fill(noise_2f, RNG::NORMAL, Scalar::all(0), Scalar::all(sigma));
double x1 = p1.at<Point2f>(i).x;
double y1 = p1.at<Point2f>(i).y;
double x2 = p2.at<Point2f>(i).x;
double y2 = p2.at<Point2f>(i).y;
double n1 = 1./sqrt(x1*x1 + y1*y1 + 1);
double n2 = 1./sqrt(x2*x2 + y2*y2 + 1);
double t0 = fabs(h0[0]*x2*x1 + h0[1]*x2*y1 + h0[2]*x2 +
h0[3]*y2*x1 + h0[4]*y2*y1 + h0[5]*y2 +
h0[6]*x1 + h0[7]*y1 + h0[8])*n1*n2;
double t = fabs(h[0]*x2*x1 + h[1]*x2*y1 + h[2]*x2 +
h[3]*y2*x1 + h[4]*y2*y1 + h[5]*y2 +
h[6]*x1 + h[7]*y1 + h[8])*n1*n2;
mtfm1[i] = 1;
mtfm2[i] = !status[i] || t0 > err_level || t < err_level;
}
f_prop1[0] = 1; cv::Mat mask(N, 1, CV_8UC1);
f_prop1[1] = 1;
f_prop1[2] = 0;
// f_prop2[0] = f_result != 0; for (size_t i = 0; i < N; ++i)
f_prop2[1] = h[8]; {
f_prop2[2] = cv::determinant( H ); float *a = noise_2f.ptr<float>()+2*i, *_2f = dst_mat_2f.ptr<float>()+2*i;
} _2f[0] += a[0]; _2f[1] += a[1];
mask.at<bool>(i, 0) = !(sqrt(a[0]*a[0]+a[1]*a[1]) > reproj_threshold);
}
bool CV_HomographyTest::check_matrix_size(const cv::Mat& H) for (size_t i = 0; i < METHODS_COUNT; ++i)
{ {
return (H.rows == 3) && (H.cols == 3); method = METHOD[i];
} switch (method)
{
case 0:
case CV_LMEDS:
{
Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f),
cv::findHomography(src_mat_2f, dst_vec),
cv::findHomography(src_vec, dst_mat_2f),
cv::findHomography(src_vec, dst_vec) };
bool CV_HomographyTest::check_matrix_diff(const cv::Mat& original, const cv::Mat& found, const int norm_type, double &diff) for (size_t j = 0; j < 4; ++j)
{ {
diff = cv::norm(original, found, norm_type);
return diff <= max_diff;
}
int CV_HomographyTest::check_ransac_mask_1(const Mat& src, const Mat& mask) if (!check_matrix_size(H_res_64[j]))
{ {
if (!(mask.cols == 1) && (mask.rows == src.cols)) return 1; print_information_1(j, N, method, H_res_64[j]);
if (countNonZero(mask) < mask.rows) return 2; CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);
for (size_t i = 0; i < mask.rows; ++i) if (mask.at<uchar>(i, 0) > 1) return 3; return;
return 0; }
}
int CV_HomographyTest::check_ransac_mask_2(const Mat& original_mask, const Mat& found_mask) Mat H_res_32; H_res_64[j].convertTo(H_res_32, CV_32F);
{
if (!(found_mask.cols == 1) && (found_mask.rows == original_mask.rows)) return 1;
for (size_t i = 0; i < found_mask.rows; ++i) if (found_mask.at<uchar>(i, 0) > 1) return 2;
return 0;
}
void CV_HomographyTest::print_information_1(int j, int N, int method, const Mat& H) cv::Mat dst_res_3d(3, N, CV_32F), noise_2d(2, N, CV_32F);
{
cout << endl; cout << "Checking for homography matrix sizes..." << endl; cout << endl;
cout << "Type of srcPoints: "; if (0 <= j < 2) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Count of points: " << N << endl; cout << endl;
cout << "Method: "; if (method == 0) cout << 0; else if (method == 8) cout << "RANSAC"; else cout << "LMEDS"; cout << endl;
cout << "Homography matrix:" << endl; cout << endl;
cout << H << endl; cout << endl;
cout << "Number of rows: " << H.rows << " Number of cols: " << H.cols << endl; cout << endl;
}
void CV_HomographyTest::print_information_2(int j, int N, int method, const Mat& H, const Mat& H_res, int k, double diff) for (size_t k = 0; k < N; ++k)
{ {
cout << endl; cout << "Checking for accuracy of homography matrix computing..." << endl; cout << endl;
cout << "Type of srcPoints: "; if (0 <= j < 2) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Count of points: " << N << endl; cout << endl;
cout << "Method: "; if (method == 0) cout << 0; else if (method == 8) cout << "RANSAC"; else cout << "LMEDS"; cout << endl;
cout << "Original matrix:" << endl; cout << endl;
cout << H << endl; cout << endl;
cout << "Found matrix:" << endl; cout << endl;
cout << H_res << endl; cout << endl;
cout << "Norm type using in criteria: "; if (NORM_TYPE[k] == 1) cout << "INF"; else if (NORM_TYPE[k] == 2) cout << "L1"; else cout << "L2"; cout << endl;
cout << "Difference between matrix: " << diff << endl;
cout << "Maximum allowed difference: " << max_diff << endl; cout << endl;
}
void CV_HomographyTest::print_information_3(int j, int N, const Mat& mask) Mat tmp_mat_3d = H_res_32*src_mat_3d.col(k);
{
cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;
cout << "Type of srcPoints: "; if (0 <= j < 2) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Count of points: " << N << endl; cout << endl;
cout << "Method: RANSAC" << endl;
cout << "Found mask:" << endl; cout << endl;
cout << mask << endl; cout << endl;
cout << "Number of rows: " << mask.rows << " Number of cols: " << mask.cols << endl; cout << endl;
}
void CV_HomographyTest::print_information_4(int method, int j, int N, int k, int l, double diff) dst_res_3d.at<float>(0, k) = tmp_mat_3d.at<float>(0, 0) /= tmp_mat_3d.at<float>(2, 0);
{ dst_res_3d.at<float>(1, k) = tmp_mat_3d.at<float>(1, 0) /= tmp_mat_3d.at<float>(2, 0);
cout << endl; cout << "Checking for accuracy of reprojection error computing..." << endl; cout << endl; dst_res_3d.at<float>(2, k) = tmp_mat_3d.at<float>(2, 0) = 1.0f;
cout << "Method: "; if (method == 0) cout << 0 << endl; else cout << "CV_LMEDS" << endl;
cout << "Type of srcPoints: "; if (0 <= j < 2) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Sigma of normal noise: " << sigma << endl;
cout << "Count of points: " << N << endl;
cout << "Number of point: " << k << endl;
cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;
cout << "Difference with noise of point: " << diff << endl;
cout << "Maxumum allowed difference: " << max_2diff << endl; cout << endl;
}
void CV_HomographyTest::print_information_5(int method, int j, int N, int l, double diff) float *a = noise_2f.ptr<float>()+2*k;
{ noise_2d.at<float>(0, k) = a[0]; noise_2d.at<float>(1, k) = a[1];
cout << endl; cout << "Checking for accuracy of reprojection error computing..." << endl; cout << endl;
cout << "Method: "; if (method == 0) cout << 0 << endl; else cout << "CV_LMEDS" << endl;
cout << "Type of srcPoints: "; if (0 <= j < 2) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Sigma of normal noise: " << sigma << endl;
cout << "Count of points: " << N << endl;
cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;
cout << "Difference with noise of points: " << diff << endl;
cout << "Maxumum allowed difference: " << max_diff << endl; cout << endl;
}
void CV_HomographyTest::print_information_6(int j, int N, int k, double diff, bool value) for (size_t l = 0; l < COUNT_NORM_TYPES; ++l)
{ if (cv::norm(tmp_mat_3d, dst_mat_3d.col(k), NORM_TYPE[l]) - cv::norm(noise_2d.col(k), NORM_TYPE[l]) > max_2diff)
cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl; {
cout << "Method: RANSAC" << endl; print_information_4(method, j, N, k, l, cv::norm(tmp_mat_3d, dst_mat_3d.col(k), NORM_TYPE[l]) - cv::norm(noise_2d.col(k), NORM_TYPE[l]));
cout << "Type of srcPoints: "; if (0 <= j < 2) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; CV_Error(CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF, MESSAGE_REPROJ_DIFF_1);
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl; return;
cout << "Count of points: " << N << " " << endl; }
cout << "Number of point: " << k << " " << endl;
cout << "Reprojection error for this point: " << diff << " " << endl;
cout << "Reprojection error threshold: " << reproj_threshold << " " << endl;
cout << "Value of found mask: "<< value << endl; cout << endl;
}
void CV_HomographyTest::print_information_7(int j, int N, int k, double diff, bool original_value, bool found_value) }
{
cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;
cout << "Method: RANSAC" << endl;
cout << "Type of srcPoints: "; if (0 <= j < 2) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Count of points: " << N << " " << endl;
cout << "Number of point: " << k << " " << endl;
cout << "Reprojection error for this point: " << diff << " " << endl;
cout << "Reprojection error threshold: " << reproj_threshold << " " << endl;
cout << "Value of original mask: "<< original_value << " Value of found mask: " << found_value << endl; cout << endl;
}
void CV_HomographyTest::print_information_8(int j, int N, int k, int l, double diff) Mat tmp_mat_3d = H_res_32*src_mat_3d;
{
cout << endl; cout << "Checking for reprojection error of inlier..." << endl; cout << endl;
cout << "Method: RANSAC" << endl;
cout << "Sigma of normal noise: " << sigma << endl;
cout << "Type of srcPoints: "; if (0 <= j < 2) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
cout << "Count of points: " << N << " " << endl;
cout << "Number of point: " << k << " " << endl;
cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;
cout << "Difference with noise of point: " << diff << endl;
cout << "Maxumum allowed difference: " << max_2diff << endl; cout << endl;
}
void CV_HomographyTest::check_transform_quality(cv::InputArray src_points, cv::InputArray dst_points, const cv::Mat& H, const int norm_type) for (size_t l = 0; l < COUNT_NORM_TYPES; ++l)
{ if (cv::norm(dst_res_3d, dst_mat_3d, NORM_TYPE[l]) - cv::norm(noise_2d, NORM_TYPE[l]) > max_diff)
Mat src, dst_original; {
cv::transpose(src_points.getMat(), src); cv::transpose(dst_points.getMat(), dst_original); print_information_5(method, j, N, l, cv::norm(dst_res_3d, dst_mat_3d, NORM_TYPE[l]) - cv::norm(noise_2d, NORM_TYPE[l]));
cv::Mat src_3d(src.rows+1, src.cols, CV_32FC1); CV_Error(CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF, MESSAGE_REPROJ_DIFF_2);
src_3d(Rect(0, 0, src.rows, src.cols)) = src; return;
src_3d(Rect(src.rows, 0, 1, src.cols)) = Mat(1, src.cols, CV_32FC1, Scalar(1.0f)); }
cv::Mat dst_found, dst_found_3d;
cv::multiply(H, src_3d, dst_found_3d);
dst_found = dst_found_3d/dst_found_3d.row(dst_found_3d.rows-1);
double reprojection_error = cv::norm(dst_original, dst_found, norm_type);
CV_Assert ( reprojection_error > max_diff );
}
void CV_HomographyTest::run(int) }
{
for (size_t N = 4; N <= MAX_COUNT_OF_POINTS; ++N) continue;
{
RNG& rng = ts->get_rng();
float *src_data = new float [2*N];
for (int i = 0; i < N; ++i)
{
src_data[2*i] = (float)cvtest::randReal(rng)*image_size;
src_data[2*i+1] = (float)cvtest::randReal(rng)*image_size;
}
cv::Mat src_mat_2f(1, N, CV_32FC2, src_data),
src_mat_2d(2, N, CV_32F, src_data),
src_mat_3d(3, N, CV_32F);
cv::Mat dst_mat_2f, dst_mat_2d, dst_mat_3d;
vector <Point2f> src_vec, dst_vec;
for (size_t i = 0; i < N; ++i)
{
float *tmp = src_mat_2d.ptr<float>()+2*i;
src_mat_3d.at<float>(0, i) = tmp[0];
src_mat_3d.at<float>(1, i) = tmp[1];
src_mat_3d.at<float>(2, i) = 1.0f;
src_vec.push_back(Point2f(tmp[0], tmp[1]));
}
double fi = cvtest::randReal(rng)*2*CV_PI;
double t_x = cvtest::randReal(rng)*sqrt(image_size*1.0),
t_y = cvtest::randReal(rng)*sqrt(image_size*1.0);
double Hdata[9] = { cos(fi), -sin(fi), t_x,
sin(fi), cos(fi), t_y,
0.0f, 0.0f, 1.0f };
cv::Mat H_64(3, 3, CV_64F, Hdata), H_32;
H_64.convertTo(H_32, CV_32F);
dst_mat_3d = H_32*src_mat_3d;
dst_mat_2d.create(2, N, CV_32F); dst_mat_2f.create(1, N, CV_32FC2);
for (size_t i = 0; i < N; ++i)
{
float *tmp_2f = dst_mat_2f.ptr<float>()+2*i;
tmp_2f[0] = dst_mat_2d.at<float>(0, i) = dst_mat_3d.at<float>(0, i) /= dst_mat_3d.at<float>(2, i);
tmp_2f[1] = dst_mat_2d.at<float>(1, i) = dst_mat_3d.at<float>(1, i) /= dst_mat_3d.at<float>(2, i);
dst_mat_3d.at<float>(2, i) = 1.0f;
dst_vec.push_back(Point2f(tmp_2f[0], tmp_2f[1]));
}
for (size_t i = 0; i < METHODS_COUNT; ++i)
{
method = METHOD[i];
switch (method)
{
case 0:
case CV_LMEDS:
{
Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, method),
cv::findHomography(src_mat_2f, dst_vec, method),
cv::findHomography(src_vec, dst_mat_2f, method),
cv::findHomography(src_vec, dst_vec, method) };
for (size_t j = 0; j < 4; ++j)
{
if (!check_matrix_size(H_res_64[j]))
{
print_information_1(j, N, method, H_res_64[j]);
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);
return;
}
double diff;
for (size_t k = 0; k < COUNT_NORM_TYPES; ++k)
if (!check_matrix_diff(H_64, H_res_64[j], NORM_TYPE[k], diff))
{
print_information_2(j, N, method, H_64, H_res_64[j], k, diff);
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF, MESSAGE_MATRIX_DIFF);
return;
}
}
continue;
}
case CV_RANSAC:
{
cv::Mat mask [4]; double diff;
Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, CV_RANSAC, reproj_threshold, mask[0]),
cv::findHomography(src_mat_2f, dst_vec, CV_RANSAC, reproj_threshold, mask[1]),
cv::findHomography(src_vec, dst_mat_2f, CV_RANSAC, reproj_threshold, mask[2]),
cv::findHomography(src_vec, dst_vec, CV_RANSAC, reproj_threshold, mask[3]) };
for (size_t j = 0; j < 4; ++j)
{
if (!check_matrix_size(H_res_64[j]))
{
print_information_1(j, N, method, H_res_64[j]);
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);
return;
}
for (size_t k = 0; k < COUNT_NORM_TYPES; ++k)
if (!check_matrix_diff(H_64, H_res_64[j], NORM_TYPE[k], diff))
{
print_information_2(j, N, method, H_64, H_res_64[j], k, diff);
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF, MESSAGE_MATRIX_DIFF);
return;
}
int code = check_ransac_mask_1(src_mat_2f, mask[j]);
if (code)
{
print_information_3(j, N, mask[j]);
switch (code)
{
case 1: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_1); break; }
case 2: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_2); break; }
case 3: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_3); break; }
default: break;
}
return;
}
}
continue;
}
default: continue;
}
}
Mat noise_2f(1, N, CV_32FC2);
rng.fill(noise_2f, RNG::NORMAL, Scalar::all(0), Scalar::all(sigma));
cv::Mat mask(N, 1, CV_8UC1);
for (int i = 0; i < N; ++i)
{
float *a = noise_2f.ptr<float>()+2*i, *_2f = dst_mat_2f.ptr<float>()+2*i;
_2f[0] /* = dst_mat_2d.at<float>(0, i) = dst_mat_3d.at<float>(0, i) */ += a[0];
_2f[1] /* = dst_mat_2d.at<float>(1, i) = dst_mat_3d.at<float>(1, i) */ += a[1];
mask.at<bool>(i, 0) = !(sqrt(a[0]*a[0]+a[1]*a[1]) > reproj_threshold);
}
for (size_t i = 0; i < METHODS_COUNT; ++i)
{
method = METHOD[i];
switch (method)
{
case 0:
case CV_LMEDS:
{
Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f),
cv::findHomography(src_mat_2f, dst_vec),
cv::findHomography(src_vec, dst_mat_2f),
cv::findHomography(src_vec, dst_vec) };
for (size_t j = 0; j < 4; ++j)
{
if (!check_matrix_size(H_res_64[j]))
{
print_information_1(j, N, method, H_res_64[j]);
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);
return;
}
Mat H_res_32; H_res_64[j].convertTo(H_res_32, CV_32F);
cv::Mat dst_res_3d(3, N, CV_32F), noise_2d(2, N, CV_32F);
for (size_t k = 0; k < N; ++k)
{
Mat tmp_mat_3d = H_res_32*src_mat_3d.col(k);
dst_res_3d.at<float>(0, k) = tmp_mat_3d.at<float>(0, 0) /= tmp_mat_3d.at<float>(2, 0);
dst_res_3d.at<float>(1, k) = tmp_mat_3d.at<float>(1, 0) /= tmp_mat_3d.at<float>(2, 0);
dst_res_3d.at<float>(2, k) = tmp_mat_3d.at<float>(2, 0) = 1.0f;
float *a = noise_2f.ptr<float>()+2*k;
noise_2d.at<float>(0, k) = a[0]; noise_2d.at<float>(1, k) = a[1];
for (size_t l = 0; l < COUNT_NORM_TYPES; ++l)
if (cv::norm(tmp_mat_3d, dst_mat_3d.col(k), NORM_TYPE[l]) - cv::norm(noise_2d.col(k), NORM_TYPE[l]) > max_2diff)
{
print_information_4(method, j, N, k, l, cv::norm(tmp_mat_3d, dst_mat_3d.col(k), NORM_TYPE[l]) - cv::norm(noise_2d.col(k), NORM_TYPE[l]));
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF, MESSAGE_REPROJ_DIFF_1);
return;
}
}
Mat tmp_mat_3d = H_res_32*src_mat_3d;
for (size_t l = 0; l < COUNT_NORM_TYPES; ++l)
if (cv::norm(dst_res_3d, dst_mat_3d, NORM_TYPE[l]) - cv::norm(noise_2d, NORM_TYPE[l]) > max_diff)
{
print_information_5(method, j, N, l, cv::norm(dst_res_3d, dst_mat_3d, NORM_TYPE[l]) - cv::norm(noise_2d, NORM_TYPE[l]));
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF, MESSAGE_REPROJ_DIFF_2);
return;
}
}
continue;
} }
case CV_RANSAC: case CV_RANSAC:
{ {
cv::Mat mask_res [4]; cv::Mat mask_res [4];
Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, CV_RANSAC, reproj_threshold, mask_res[0]), Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, CV_RANSAC, reproj_threshold, mask_res[0]),
cv::findHomography(src_mat_2f, dst_vec, CV_RANSAC, reproj_threshold, mask_res[1]), cv::findHomography(src_mat_2f, dst_vec, CV_RANSAC, reproj_threshold, mask_res[1]),
cv::findHomography(src_vec, dst_mat_2f, CV_RANSAC, reproj_threshold, mask_res[2]), cv::findHomography(src_vec, dst_mat_2f, CV_RANSAC, reproj_threshold, mask_res[2]),
cv::findHomography(src_vec, dst_vec, CV_RANSAC, reproj_threshold, mask_res[3]) }; cv::findHomography(src_vec, dst_vec, CV_RANSAC, reproj_threshold, mask_res[3]) };
for (size_t j = 0; j < 4; ++j) for (size_t j = 0; j < 4; ++j)
{ {
if (!check_matrix_size(H_res_64[j])) if (!check_matrix_size(H_res_64[j]))
{ {
print_information_1(j, N, method, H_res_64[j]); print_information_1(j, N, method, H_res_64[j]);
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE); CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);
return; return;
} }
int code = check_ransac_mask_2(mask, mask_res[j]); int code = check_ransac_mask_2(mask, mask_res[j]);
if (code) if (code)
{ {
print_information_3(j, N, mask_res[j]); print_information_3(j, N, mask_res[j]);
switch (code) switch (code)
{ {
case 1: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_1); break; } case 1: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_1); break; }
case 2: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_3); break; } case 2: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_3); break; }
default: break; default: break;
} }
return; return;
} }
cv::Mat H_res_32; H_res_64[j].convertTo(H_res_32, CV_32F); cv::Mat H_res_32; H_res_64[j].convertTo(H_res_32, CV_32F);
cv::Mat dst_res_3d = H_res_32*src_mat_3d; cv::Mat dst_res_3d = H_res_32*src_mat_3d;
for (size_t k = 0; k < N; ++k) for (size_t k = 0; k < N; ++k)
{ {
dst_res_3d.at<float>(0, k) /= dst_res_3d.at<float>(2, k); dst_res_3d.at<float>(0, k) /= dst_res_3d.at<float>(2, k);
dst_res_3d.at<float>(1, k) /= dst_res_3d.at<float>(2, k); dst_res_3d.at<float>(1, k) /= dst_res_3d.at<float>(2, k);
dst_res_3d.at<float>(2, k) = 1.0f; dst_res_3d.at<float>(2, k) = 1.0f;
float *p = dst_mat_2f.ptr<float>()+2*k; float *p = dst_mat_2f.ptr<float>()+2*k;
dst_mat_3d.at<float>(0, k) = p[0]; dst_mat_3d.at<float>(0, k) = p[0];
dst_mat_3d.at<float>(1, k) = p[1]; dst_mat_3d.at<float>(1, k) = p[1];
double diff = cv::norm(dst_res_3d.col(k), dst_mat_3d.col(k), NORM_L2); double diff = cv::norm(dst_res_3d.col(k), dst_mat_3d.col(k), NORM_L2);
if (mask_res[j].at<bool>(k, 0) != (diff <= reproj_threshold)) if (mask_res[j].at<bool>(k, 0) != (diff <= reproj_threshold))
{ {
print_information_6(j, N, k, diff, mask_res[j].at<bool>(k, 0)); print_information_6(j, N, k, diff, mask_res[j].at<bool>(k, 0));
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_4); CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_4);
return; return;
} }
if (mask.at<bool>(k, 0) && !mask_res[j].at<bool>(k, 0)) if (mask.at<bool>(k, 0) && !mask_res[j].at<bool>(k, 0))
{ {
print_information_7(j, N, k, diff, mask.at<bool>(k, 0), mask_res[j].at<bool>(k, 0)); print_information_7(j, N, k, diff, mask.at<bool>(k, 0), mask_res[j].at<bool>(k, 0));
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_5); CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_5);
return; return;
} }
if (mask_res[j].at<bool>(k, 0)) if (mask_res[j].at<bool>(k, 0))
{ {
float *a = noise_2f.ptr<float>()+2*k; float *a = noise_2f.ptr<float>()+2*k;
dst_mat_3d.at<float>(0, k) -= a[0]; dst_mat_3d.at<float>(0, k) -= a[0];
dst_mat_3d.at<float>(1, k) -= a[1]; dst_mat_3d.at<float>(1, k) -= a[1];
cv::Mat noise_2d(2, 1, CV_32F); cv::Mat noise_2d(2, 1, CV_32F);
noise_2d.at<float>(0, 0) = a[0]; noise_2d.at<float>(1, 0) = a[1]; noise_2d.at<float>(0, 0) = a[0]; noise_2d.at<float>(1, 0) = a[1];
for (size_t l = 0; l < COUNT_NORM_TYPES; ++l) for (size_t l = 0; l < COUNT_NORM_TYPES; ++l)
{ {
diff = cv::norm(dst_res_3d.col(k), dst_mat_3d.col(k), NORM_TYPE[l]); diff = cv::norm(dst_res_3d.col(k), dst_mat_3d.col(k), NORM_TYPE[l]);
if (diff - cv::norm(noise_2d, NORM_TYPE[l]) > max_2diff) if (diff - cv::norm(noise_2d, NORM_TYPE[l]) > max_2diff)
{ {
print_information_8(j, N, k, l, diff - cv::norm(noise_2d, NORM_TYPE[l])); print_information_8(j, N, k, l, diff - cv::norm(noise_2d, NORM_TYPE[l]));
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_DIFF, MESSAGE_RANSAC_DIFF); CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_DIFF, MESSAGE_RANSAC_DIFF);
return; return;
} }
} }
} }
} }
} }
continue; continue;
} }
default: continue; default: continue;
} }
} }
} }
} }
TEST(Calib3d_Homography, complex_test) { CV_HomographyTest test; test.safe_run(); } TEST(Calib3d_Homography, accuracy) { CV_HomographyTest test; test.safe_run(); }
\ No newline at end of file
...@@ -18,26 +18,26 @@ const int INT_TYPE [5] = {CV_8U, CV_8S, CV_16U, CV_16S, CV_32S}; ...@@ -18,26 +18,26 @@ const int INT_TYPE [5] = {CV_8U, CV_8S, CV_16U, CV_16S, CV_32S};
class CV_CountNonZeroTest: public cvtest::BaseTest class CV_CountNonZeroTest: public cvtest::BaseTest
{ {
public: public:
CV_CountNonZeroTest(); CV_CountNonZeroTest();
~CV_CountNonZeroTest(); ~CV_CountNonZeroTest();
protected: protected:
void run (int); void run (int);
private: private:
float eps_32; float eps_32;
double eps_64; double eps_64;
Mat src; Mat src;
int current_type; int current_type;
void generate_src_data(cv::Size size, int type); void generate_src_data(cv::Size size, int type);
void generate_src_data(cv::Size size, int type, int count_non_zero); void generate_src_data(cv::Size size, int type, int count_non_zero);
void generate_src_stat_data(cv::Size size, int type, int distribution); void generate_src_stat_data(cv::Size size, int type, int distribution);
int get_count_non_zero(); int get_count_non_zero();
void print_information(int right, int result); void print_information(int right, int result);
}; };
CV_CountNonZeroTest::CV_CountNonZeroTest(): eps_32(1e-8), eps_64(1e-16), src(Mat()), current_type(-1) {} CV_CountNonZeroTest::CV_CountNonZeroTest(): eps_32(1e-8), eps_64(1e-16), src(Mat()), current_type(-1) {}
...@@ -45,174 +45,174 @@ CV_CountNonZeroTest::~CV_CountNonZeroTest() {} ...@@ -45,174 +45,174 @@ CV_CountNonZeroTest::~CV_CountNonZeroTest() {}
void CV_CountNonZeroTest::generate_src_data(cv::Size size, int type) void CV_CountNonZeroTest::generate_src_data(cv::Size size, int type)
{ {
src.create(size, CV_MAKETYPE(type, 1)); src.create(size, CV_MAKETYPE(type, 1));
for (size_t j = 0; j < size.width; ++j) for (int j = 0; j < size.width; ++j)
for (size_t i = 0; i < size.height; ++i) for (int i = 0; i < size.height; ++i)
switch (type) switch (type)
{ {
case CV_8U: { src.at<uchar>(i, j) = cv::randu<uchar>(); break; } case CV_8U: { src.at<uchar>(i, j) = cv::randu<uchar>(); break; }
case CV_8S: { src.at<char>(i, j) = cv::randu<uchar>() - 128; break; } case CV_8S: { src.at<char>(i, j) = cv::randu<uchar>() - 128; break; }
case CV_16U: { src.at<ushort>(i, j) = cv::randu<ushort>(); break; } case CV_16U: { src.at<ushort>(i, j) = cv::randu<ushort>(); break; }
case CV_16S: { src.at<short>(i, j) = cv::randu<short>(); break; } case CV_16S: { src.at<short>(i, j) = cv::randu<short>(); break; }
case CV_32S: { src.at<int>(i, j) = cv::randu<int>(); break; } case CV_32S: { src.at<int>(i, j) = cv::randu<int>(); break; }
case CV_32F: { src.at<float>(i, j) = cv::randu<float>(); break; } case CV_32F: { src.at<float>(i, j) = cv::randu<float>(); break; }
case CV_64F: { src.at<double>(i, j) = cv::randu<double>(); break; } case CV_64F: { src.at<double>(i, j) = cv::randu<double>(); break; }
default: break; default: break;
} }
} }
void CV_CountNonZeroTest::generate_src_data(cv::Size size, int type, int count_non_zero) void CV_CountNonZeroTest::generate_src_data(cv::Size size, int type, int count_non_zero)
{ {
src = Mat::zeros(size, CV_MAKETYPE(type, 1)); src = Mat::zeros(size, CV_MAKETYPE(type, 1));
int n = 0; RNG& rng = ts->get_rng(); int n = 0; RNG& rng = ts->get_rng();
while (n < count_non_zero) while (n < count_non_zero)
{ {
size_t i = rng.next()%size.height, j = rng.next()%size.width; size_t i = rng.next()%size.height, j = rng.next()%size.width;
switch (type) switch (type)
{ {
case CV_8U: { if (!src.at<uchar>(i, j)) {src.at<uchar>(i, j) = cv::randu<uchar>(); n += (src.at<uchar>(i, j) > 0);} break; } case CV_8U: { if (!src.at<uchar>(i, j)) {src.at<uchar>(i, j) = cv::randu<uchar>(); n += (src.at<uchar>(i, j) > 0);} break; }
case CV_8S: { if (!src.at<char>(i, j)) {src.at<char>(i, j) = cv::randu<uchar>() - 128; n += abs(sign(src.at<char>(i, j)));} break; } case CV_8S: { if (!src.at<char>(i, j)) {src.at<char>(i, j) = cv::randu<uchar>() - 128; n += abs(sign(src.at<char>(i, j)));} break; }
case CV_16U: { if (!src.at<ushort>(i, j)) {src.at<ushort>(i, j) = cv::randu<ushort>(); n += (src.at<ushort>(i, j) > 0);} break; } case CV_16U: { if (!src.at<ushort>(i, j)) {src.at<ushort>(i, j) = cv::randu<ushort>(); n += (src.at<ushort>(i, j) > 0);} break; }
case CV_16S: { if (!src.at<short>(i, j)) {src.at<short>(i, j) = cv::randu<short>(); n += abs(sign(src.at<short>(i, j)));} break; } case CV_16S: { if (!src.at<short>(i, j)) {src.at<short>(i, j) = cv::randu<short>(); n += abs(sign(src.at<short>(i, j)));} break; }
case CV_32S: { if (!src.at<int>(i, j)) {src.at<int>(i, j) = cv::randu<int>(); n += abs(sign(src.at<int>(i, j)));} break; } case CV_32S: { if (!src.at<int>(i, j)) {src.at<int>(i, j) = cv::randu<int>(); n += abs(sign(src.at<int>(i, j)));} break; }
case CV_32F: { if (fabs(src.at<float>(i, j)) <= eps_32) {src.at<float>(i, j) = cv::randu<float>(); n += (fabs(src.at<float>(i, j)) > eps_32);} break; } case CV_32F: { if (fabs(src.at<float>(i, j)) <= eps_32) {src.at<float>(i, j) = cv::randu<float>(); n += (fabs(src.at<float>(i, j)) > eps_32);} break; }
case CV_64F: { if (fabs(src.at<double>(i, j)) <= eps_64) {src.at<double>(i, j) = cv::randu<double>(); n += (fabs(src.at<double>(i, j)) > eps_64);} break; } case CV_64F: { if (fabs(src.at<double>(i, j)) <= eps_64) {src.at<double>(i, j) = cv::randu<double>(); n += (fabs(src.at<double>(i, j)) > eps_64);} break; }
default: break; default: break;
} }
} }
} }
void CV_CountNonZeroTest::generate_src_stat_data(cv::Size size, int type, int distribution) void CV_CountNonZeroTest::generate_src_stat_data(cv::Size size, int type, int distribution)
{ {
src.create(size, CV_MAKETYPE(type, 1)); src.create(size, CV_MAKETYPE(type, 1));
double mean = 0.0, sigma = 1.0; double mean = 0.0, sigma = 1.0;
double left = -1.0, right = 1.0; double left = -1.0, right = 1.0;
RNG& rng = ts->get_rng(); RNG& rng = ts->get_rng();
if (distribution == RNG::NORMAL) if (distribution == RNG::NORMAL)
rng.fill(src, RNG::NORMAL, Scalar::all(mean), Scalar::all(sigma)); rng.fill(src, RNG::NORMAL, Scalar::all(mean), Scalar::all(sigma));
else if (distribution == RNG::UNIFORM) else if (distribution == RNG::UNIFORM)
rng.fill(src, RNG::UNIFORM, Scalar::all(left), Scalar::all(right)); rng.fill(src, RNG::UNIFORM, Scalar::all(left), Scalar::all(right));
} }
int CV_CountNonZeroTest::get_count_non_zero() int CV_CountNonZeroTest::get_count_non_zero()
{ {
int result = 0; int result = 0;
for (int i = 0; i < src.rows; ++i)
for (int j = 0; j < src.cols; ++j)
for (size_t i = 0; i < src.rows; ++i) if (current_type == CV_8U) result += (src.at<uchar>(i, j) > 0);
for (size_t j = 0; j < src.cols; ++j)
if (current_type == CV_8U) result += (src.at<uchar>(i, j) > 0); else if (current_type == CV_8S) result += abs(sign(src.at<char>(i, j)));
else if (current_type == CV_8S) result += abs(sign(src.at<char>(i, j)));
else if (current_type == CV_16U) result += (src.at<ushort>(i, j) > 0); else if (current_type == CV_16U) result += (src.at<ushort>(i, j) > 0);
else if (current_type == CV_16S) result += abs(sign(src.at<short>(i, j))); else if (current_type == CV_16S) result += abs(sign(src.at<short>(i, j)));
else if (current_type == CV_32S) result += abs(sign(src.at<int>(i, j))); else if (current_type == CV_32S) result += abs(sign(src.at<int>(i, j)));
else if (current_type == CV_32F) result += (fabs(src.at<float>(i, j)) > eps_32); else if (current_type == CV_32F) result += (fabs(src.at<float>(i, j)) > eps_32);
else result += (fabs(src.at<double>(i, j)) > eps_64); else result += (fabs(src.at<double>(i, j)) > eps_64);
return result; return result;
} }
void CV_CountNonZeroTest::print_information(int right, int result) void CV_CountNonZeroTest::print_information(int right, int result)
{ {
cout << endl; cout << "Checking for the work of countNonZero function..." << endl; cout << endl; cout << endl; cout << "Checking for the work of countNonZero function..." << endl; cout << endl;
cout << "Type of Mat: "; cout << "Type of Mat: ";
switch (current_type) switch (current_type)
{ {
case 0: {cout << "CV_8U"; break;} case 0: {cout << "CV_8U"; break;}
case 1: {cout << "CV_8S"; break;} case 1: {cout << "CV_8S"; break;}
case 2: {cout << "CV_16U"; break;} case 2: {cout << "CV_16U"; break;}
case 3: {cout << "CV_16S"; break;} case 3: {cout << "CV_16S"; break;}
case 4: {cout << "CV_32S"; break;} case 4: {cout << "CV_32S"; break;}
case 5: {cout << "CV_32F"; break;} case 5: {cout << "CV_32F"; break;}
case 6: {cout << "CV_64F"; break;} case 6: {cout << "CV_64F"; break;}
default: break; default: break;
} }
cout << endl; cout << endl;
cout << "Number of rows: " << src.rows << " Number of cols: " << src.cols << endl; cout << "Number of rows: " << src.rows << " Number of cols: " << src.cols << endl;
cout << "True count non zero elements: " << right << " Result: " << result << endl; cout << "True count non zero elements: " << right << " Result: " << result << endl;
cout << endl; cout << endl;
} }
void CV_CountNonZeroTest::run(int) void CV_CountNonZeroTest::run(int)
{ {
const size_t N = 1500; const size_t N = 1500;
for (int k = 1; k <= 3; ++k) for (int k = 1; k <= 3; ++k)
for (size_t i = 0; i < N; ++i) for (size_t i = 0; i < N; ++i)
{ {
RNG& rng = ts->get_rng(); RNG& rng = ts->get_rng();
int w = rng.next()%MAX_WIDTH + 1, h = rng.next()%MAX_HEIGHT + 1; int w = rng.next()%MAX_WIDTH + 1, h = rng.next()%MAX_HEIGHT + 1;
current_type = rng.next()%7; current_type = rng.next()%7;
switch (k) switch (k)
{ {
case 1: { case 1: {
generate_src_data(Size(w, h), current_type); generate_src_data(Size(w, h), current_type);
int right = get_count_non_zero(), result = countNonZero(src); int right = get_count_non_zero(), result = countNonZero(src);
if (result != right) if (result != right)
{ {
cout << "Number of experiment: " << i << endl; cout << "Number of experiment: " << i << endl;
cout << "Method of data generation: RANDOM" << endl; cout << "Method of data generation: RANDOM" << endl;
print_information(right, result); print_information(right, result);
CV_Error(CORE_COUNTNONZERO_ERROR_COUNT, MESSAGE_ERROR_COUNT); CV_Error(CORE_COUNTNONZERO_ERROR_COUNT, MESSAGE_ERROR_COUNT);
return; return;
} }
break; break;
} }
case 2: { case 2: {
int count_non_zero = rng.next()%(w*h); int count_non_zero = rng.next()%(w*h);
generate_src_data(Size(w, h), current_type, count_non_zero); generate_src_data(Size(w, h), current_type, count_non_zero);
int result = countNonZero(src); int result = countNonZero(src);
if (result != count_non_zero) if (result != count_non_zero)
{ {
cout << "Number of experiment: " << i << endl; cout << "Number of experiment: " << i << endl;
cout << "Method of data generation: HALF-RANDOM" << endl; cout << "Method of data generation: HALF-RANDOM" << endl;
print_information(count_non_zero, result); print_information(count_non_zero, result);
CV_Error(CORE_COUNTNONZERO_ERROR_COUNT, MESSAGE_ERROR_COUNT); CV_Error(CORE_COUNTNONZERO_ERROR_COUNT, MESSAGE_ERROR_COUNT);
return; return;
} }
break; break;
} }
case 3: { case 3: {
int distribution = cv::randu<uchar>()%2; int distribution = cv::randu<uchar>()%2;
generate_src_stat_data(Size(w, h), current_type, distribution); generate_src_stat_data(Size(w, h), current_type, distribution);
int right = get_count_non_zero(), result = countNonZero(src); int right = get_count_non_zero(), result = countNonZero(src);
if (right != result) if (right != result)
{ {
cout << "Number of experiment: " << i << endl; cout << "Number of experiment: " << i << endl;
cout << "Method of data generation: STATISTIC" << endl; cout << "Method of data generation: STATISTIC" << endl;
print_information(right, result); print_information(right, result);
CV_Error(CORE_COUNTNONZERO_ERROR_COUNT, MESSAGE_ERROR_COUNT); CV_Error(CORE_COUNTNONZERO_ERROR_COUNT, MESSAGE_ERROR_COUNT);
return; return;
} }
break; break;
} }
default: break; default: break;
} }
} }
} }
// TEST (Core_CountNonZero, accuracy) { CV_CountNonZeroTest test; test.safe_run(); } // TEST (Core_CountNonZero, accuracy) { CV_CountNonZeroTest test; test.safe_run(); }
\ No newline at end of file
...@@ -12,50 +12,65 @@ using namespace std; ...@@ -12,50 +12,65 @@ using namespace std;
#define CORE_EIGEN_ERROR_ORTHO 4 #define CORE_EIGEN_ERROR_ORTHO 4
#define CORE_EIGEN_ERROR_ORDER 5 #define CORE_EIGEN_ERROR_ORDER 5
#define MESSAGE_ERROR_COUNT "Matrix of eigen values must have the same rows as source matrix and 1 column."
#define MESSAGE_ERROR_SIZE "Source matrix and matrix of eigen vectors must have the same sizes."
#define MESSAGE_ERROR_DIFF_1 "Accurasy of eigen values computing less than required."
#define MESSAGE_ERROR_DIFF_2 "Accuracy of eigen vectors computing less than required."
#define MESSAGE_ERROR_ORTHO "Matrix of eigen vectors is not orthogonal."
#define MESSAGE_ERROR_ORDER "Eigen values are not sorted in ascending order."
const size_t COUNT_NORM_TYPES = 3;
const size_t NORM_TYPE[COUNT_NORM_TYPES] = {cv::NORM_L1, cv::NORM_L2, cv::NORM_INF};
enum TASK_TYPE_EIGEN {VALUES, VECTORS};
class Core_EigenTest: public cvtest::BaseTest class Core_EigenTest: public cvtest::BaseTest
{ {
public: public:
Core_EigenTest(); Core_EigenTest();
~Core_EigenTest(); ~Core_EigenTest();
protected: protected:
bool test_values(const cv::Mat& src); // complex test for eigen without vectors bool test_values(const cv::Mat& src); // complex test for eigen without vectors
bool check_full(int type); // compex test for symmetric matrix bool check_full(int type); // compex test for symmetric matrix
virtual void run (int) = 0; // main testing method virtual void run (int) = 0; // main testing method
private: private:
float eps_val_32, eps_vec_32; float eps_val_32, eps_vec_32;
float eps_val_64, eps_vec_64; float eps_val_64, eps_vec_64;
bool check_pair_count(const cv::Mat& src, const cv::Mat& evalues, int low_index = -1, int high_index = -1); bool check_pair_count(const cv::Mat& src, const cv::Mat& evalues, int low_index = -1, int high_index = -1);
bool check_pair_count(const cv::Mat& src, const cv::Mat& evalues, const cv::Mat& evectors, int low_index = -1, int high_index = -1); bool check_pair_count(const cv::Mat& src, const cv::Mat& evalues, const cv::Mat& evectors, int low_index = -1, int high_index = -1);
bool check_pairs_order(const cv::Mat& eigen_values); // checking order of eigen values & vectors (it should be none up) bool check_pairs_order(const cv::Mat& eigen_values); // checking order of eigen values & vectors (it should be none up)
bool check_orthogonality(const cv::Mat& U); // checking is matrix of eigen vectors orthogonal bool check_orthogonality(const cv::Mat& U); // checking is matrix of eigen vectors orthogonal
bool test_pairs(const cv::Mat& src); // complex test for eigen with vectors bool test_pairs(const cv::Mat& src); // complex test for eigen with vectors
void print_information(const size_t norm_idx, const cv::Mat& src, double diff, double max_diff);
}; };
class Core_EigenTest_Scalar : public Core_EigenTest class Core_EigenTest_Scalar : public Core_EigenTest
{ {
public: public:
Core_EigenTest_Scalar() : Core_EigenTest() {} Core_EigenTest_Scalar() : Core_EigenTest() {}
~Core_EigenTest_Scalar(); ~Core_EigenTest_Scalar();
virtual void run(int) = 0;
virtual void run(int) = 0;
}; };
class Core_EigenTest_Scalar_32 : public Core_EigenTest_Scalar class Core_EigenTest_Scalar_32 : public Core_EigenTest_Scalar
{ {
public: public:
Core_EigenTest_Scalar_32() : Core_EigenTest_Scalar() {} Core_EigenTest_Scalar_32() : Core_EigenTest_Scalar() {}
~Core_EigenTest_Scalar_32(); ~Core_EigenTest_Scalar_32();
void run(int); void run(int);
}; };
class Core_EigenTest_Scalar_64 : public Core_EigenTest_Scalar class Core_EigenTest_Scalar_64 : public Core_EigenTest_Scalar
{ {
public: public:
Core_EigenTest_Scalar_64() : Core_EigenTest_Scalar() {} Core_EigenTest_Scalar_64() : Core_EigenTest_Scalar() {}
~Core_EigenTest_Scalar_64(); ~Core_EigenTest_Scalar_64();
void run(int); void run(int);
...@@ -63,7 +78,7 @@ class Core_EigenTest_Scalar_64 : public Core_EigenTest_Scalar ...@@ -63,7 +78,7 @@ class Core_EigenTest_Scalar_64 : public Core_EigenTest_Scalar
class Core_EigenTest_32 : public Core_EigenTest class Core_EigenTest_32 : public Core_EigenTest
{ {
public: public:
Core_EigenTest_32(): Core_EigenTest() {} Core_EigenTest_32(): Core_EigenTest() {}
~Core_EigenTest_32() {} ~Core_EigenTest_32() {}
void run(int); void run(int);
...@@ -71,10 +86,10 @@ class Core_EigenTest_32 : public Core_EigenTest ...@@ -71,10 +86,10 @@ class Core_EigenTest_32 : public Core_EigenTest
class Core_EigenTest_64 : public Core_EigenTest class Core_EigenTest_64 : public Core_EigenTest
{ {
public: public:
Core_EigenTest_64(): Core_EigenTest() {} Core_EigenTest_64(): Core_EigenTest() {}
~Core_EigenTest_64() {} ~Core_EigenTest_64() {}
void run(int); void run(int);
}; };
Core_EigenTest_Scalar::~Core_EigenTest_Scalar() {} Core_EigenTest_Scalar::~Core_EigenTest_Scalar() {}
...@@ -83,18 +98,18 @@ Core_EigenTest_Scalar_64::~Core_EigenTest_Scalar_64() {} ...@@ -83,18 +98,18 @@ Core_EigenTest_Scalar_64::~Core_EigenTest_Scalar_64() {}
void Core_EigenTest_Scalar_32::run(int) void Core_EigenTest_Scalar_32::run(int)
{ {
float value = cv::randu<float>(); float value = cv::randu<float>();
cv::Mat src(1, 1, CV_32FC1, Scalar::all((float)value)); cv::Mat src(1, 1, CV_32FC1, Scalar::all((float)value));
test_values(src); test_values(src);
src.~Mat(); src.~Mat();
} }
void Core_EigenTest_Scalar_64::run(int) void Core_EigenTest_Scalar_64::run(int)
{ {
float value = cv::randu<float>(); float value = cv::randu<float>();
cv::Mat src(1, 1, CV_64FC1, Scalar::all((double)value)); cv::Mat src(1, 1, CV_64FC1, Scalar::all((double)value));
test_values(src); test_values(src);
src.~Mat(); src.~Mat();
} }
void Core_EigenTest_32::run(int) { check_full(CV_32FC1); } void Core_EigenTest_32::run(int) { check_full(CV_32FC1); }
...@@ -105,207 +120,245 @@ Core_EigenTest::~Core_EigenTest() {} ...@@ -105,207 +120,245 @@ Core_EigenTest::~Core_EigenTest() {}
bool Core_EigenTest::check_pair_count(const cv::Mat& src, const cv::Mat& evalues, int low_index, int high_index) bool Core_EigenTest::check_pair_count(const cv::Mat& src, const cv::Mat& evalues, int low_index, int high_index)
{ {
int n = src.rows, s = sign(high_index); int n = src.rows, s = sign(high_index);
if (!( (evalues.rows == n - max<int>(0, low_index) - ((int)((n/2.0)*(s*s-s)) + (1+s-s*s)*(n - (high_index+1)))) && (evalues.cols == 1))) if (!( (evalues.rows == n - max<int>(0, low_index) - ((int)((n/2.0)*(s*s-s)) + (1+s-s*s)*(n - (high_index+1)))) && (evalues.cols == 1)))
{ {
std::cout << "Checking sizes of eigen values matrix " << evalues << "..." << endl; std::cout << endl; std::cout << "Checking sizes of eigen values matrix " << evalues << "..." << endl;
CV_Error(CORE_EIGEN_ERROR_COUNT, "Matrix of eigen values must have the same rows as source matrix and 1 column."); std::cout << "Number of rows: " << evalues.rows << " Number of cols: " << evalues.cols << endl;
return false; std:: cout << "Size of src symmetric matrix: " << src.rows << " * " << src.cols << endl; std::cout << endl;
} CV_Error(CORE_EIGEN_ERROR_COUNT, MESSAGE_ERROR_COUNT);
return true; return false;
}
return true;
} }
bool Core_EigenTest::check_pair_count(const cv::Mat& src, const cv::Mat& evalues, const cv::Mat& evectors, int low_index, int high_index) bool Core_EigenTest::check_pair_count(const cv::Mat& src, const cv::Mat& evalues, const cv::Mat& evectors, int low_index, int high_index)
{ {
int n = src.rows, s = sign(high_index); int n = src.rows, s = sign(high_index);
int right_eigen_pair_count = n - max<int>(0, low_index) - ((int)((n/2.0)*(s*s-s)) + (1+s-s*s)*(n - (high_index+1))); int right_eigen_pair_count = n - max<int>(0, low_index) - ((int)((n/2.0)*(s*s-s)) + (1+s-s*s)*(n - (high_index+1)));
if (!((evectors.rows == right_eigen_pair_count) && (evectors.cols == right_eigen_pair_count))) if (!((evectors.rows == right_eigen_pair_count) && (evectors.cols == right_eigen_pair_count)))
{ {
std::cout << "Checking sizes of eigen vectors matrix " << evectors << "..." << endl; std::cout << endl; std::cout << "Checking sizes of eigen vectors matrix " << evectors << "..." << endl;
CV_Error (CORE_EIGEN_ERROR_SIZE, "Source matrix and matrix of eigen vectors must have the same sizes."); std::cout << "Number of rows: " << evectors.rows << " Number of cols: " << evectors.cols << endl;
return false; std:: cout << "Size of src symmetric matrix: " << src.rows << " * " << src.cols << endl; std::cout << endl;
} CV_Error (CORE_EIGEN_ERROR_SIZE, MESSAGE_ERROR_SIZE);
return false;
if (!((evalues.rows == right_eigen_pair_count) && (evalues.cols == 1))) }
{
std::cout << "Checking sizes of eigen values matrix " << evalues << "..." << endl; if (!((evalues.rows == right_eigen_pair_count) && (evalues.cols == 1)))
CV_Error (CORE_EIGEN_ERROR_COUNT, "Matrix of eigen values must have the same rows as source matrix and 1 column."); {
return false; std::cout << endl; std::cout << "Checking sizes of eigen values matrix " << evalues << "..." << endl;
} std::cout << "Number of rows: " << evalues.rows << " Number of cols: " << evalues.cols << endl;
std:: cout << "Size of src symmetric matrix: " << src.rows << " * " << src.cols << endl; std::cout << endl;
return true; CV_Error (CORE_EIGEN_ERROR_COUNT, MESSAGE_ERROR_COUNT);
return false;
}
return true;
} }
bool Core_EigenTest::check_orthogonality(const cv::Mat& U) void Core_EigenTest::print_information(const size_t norm_idx, const cv::Mat& src, double diff, double max_diff)
{ {
int type = U.type(); switch (NORM_TYPE[norm_idx])
double eps_vec = type == CV_32FC1 ? eps_vec_32 : eps_vec_64; {
cv::Mat UUt; cv::mulTransposed(U, UUt, false); case cv::NORM_L1: {std::cout << "L1"; break;}
case cv::NORM_L2: {std::cout << "L2"; break;}
cv::Mat E = Mat::eye(U.rows, U.cols, type); case cv::NORM_INF: {std::cout << "INF"; break;}
default: break;
double diff_L1 = cv::norm(UUt, E, NORM_L1); }
double diff_L2 = cv::norm(UUt, E, NORM_L2);
double diff_INF = cv::norm(UUt, E, NORM_INF); cout << "-criteria... " << endl;
cout << "Source size: " << src.rows << " * " << src.cols << endl;
if (diff_L1 > eps_vec) { std::cout << "Checking orthogonality of matrix " << U << "..." << endl; CV_Error(CORE_EIGEN_ERROR_ORTHO, "Matrix of eigen vectors is not orthogonal."); return false; } cout << "Difference between original eigen vectors matrix and result: " << diff << endl;
if (diff_L2 > eps_vec) { std::cout << "Checking orthogonality of matrix " << U << "..." << endl; CV_Error(CORE_EIGEN_ERROR_ORTHO, "Matrix of eigen vectors is not orthogonal."); return false; } cout << "Maximum allowed difference: " << max_diff << endl; cout << endl;
if (diff_INF > eps_vec) { std::cout << "Checking orthogonality of matrix " << U << "..." << endl; CV_Error(CORE_EIGEN_ERROR_ORTHO, "Matrix of eigen vectors is not orthogonal."); return false; } }
return true; bool Core_EigenTest::check_orthogonality(const cv::Mat& U)
{
int type = U.type();
double eps_vec = type == CV_32FC1 ? eps_vec_32 : eps_vec_64;
cv::Mat UUt; cv::mulTransposed(U, UUt, false);
cv::Mat E = Mat::eye(U.rows, U.cols, type);
for (size_t i = 0; i < COUNT_NORM_TYPES; ++i)
{
double diff = cv::norm(UUt, E, NORM_TYPE[i]);
if (diff > eps_vec)
{
std::cout << endl; std::cout << "Checking orthogonality of matrix " << U << ": ";
print_information(i, U, diff, eps_vec);
CV_Error(CORE_EIGEN_ERROR_ORTHO, MESSAGE_ERROR_ORTHO);
return false;
}
}
return true;
} }
bool Core_EigenTest::check_pairs_order(const cv::Mat& eigen_values) bool Core_EigenTest::check_pairs_order(const cv::Mat& eigen_values)
{ {
switch (eigen_values.type()) switch (eigen_values.type())
{ {
case CV_32FC1: case CV_32FC1:
{ {
for (int i = 0; i < eigen_values.total() - 1; ++i) for (size_t i = 0; i < eigen_values.total() - 1; ++i)
if (!(eigen_values.at<float>(i, 0) > eigen_values.at<float>(i+1, 0))) if (!(eigen_values.at<float>(i, 0) > eigen_values.at<float>(i+1, 0)))
{ {
std::cout << "Checking order of eigen values vector " << eigen_values << "..." << endl; std::cout << endl; std::cout << "Checking order of eigen values vector " << eigen_values << "..." << endl;
CV_Error(CORE_EIGEN_ERROR_ORDER, "Eigen values are not sorted in ascending order."); std::cout << "Pair of indexes with non ascending of eigen values: (" << i << ", " << i+1 << ")." << endl;
return false; std::cout << endl;
} CV_Error(CORE_EIGEN_ERROR_ORDER, MESSAGE_ERROR_ORDER);
return false;
break; }
}
break;
case CV_64FC1: }
{
for (int i = 0; i < eigen_values.total() - 1; ++i) case CV_64FC1:
if (!(eigen_values.at<double>(i, 0) > eigen_values.at<double>(i+1, 0))) {
{ for (size_t i = 0; i < eigen_values.total() - 1; ++i)
std::cout << "Checking order of eigen values vector " << eigen_values << "..." << endl; if (!(eigen_values.at<double>(i, 0) > eigen_values.at<double>(i+1, 0)))
CV_Error(CORE_EIGEN_ERROR_ORDER, "Eigen values are not sorted in ascending order."); {
return false; std::cout << endl; std::cout << "Checking order of eigen values vector " << eigen_values << "..." << endl;
} std::cout << "Pair of indexes with non ascending of eigen values: (" << i << ", " << i+1 << ")." << endl;
std::cout << endl;
break; CV_Error(CORE_EIGEN_ERROR_ORDER, "Eigen values are not sorted in ascending order.");
} return false;
}
default:;
} break;
}
return true;
default:;
}
return true;
} }
bool Core_EigenTest::test_pairs(const cv::Mat& src) bool Core_EigenTest::test_pairs(const cv::Mat& src)
{ {
int type = src.type(); int type = src.type();
double eps_vec = type == CV_32FC1 ? eps_vec_32 : eps_vec_64; double eps_vec = type == CV_32FC1 ? eps_vec_32 : eps_vec_64;
cv::Mat eigen_values, eigen_vectors;
cv::Mat eigen_values, eigen_vectors; cv::eigen(src, true, eigen_values, eigen_vectors);
cv::eigen(src, true, eigen_values, eigen_vectors);
if (!check_pair_count(src, eigen_values, eigen_vectors)) return false; if (!check_pair_count(src, eigen_values, eigen_vectors)) return false;
if (!check_orthogonality (eigen_vectors)) return false; if (!check_orthogonality (eigen_vectors)) return false;
if (!check_pairs_order(eigen_values)) return false; if (!check_pairs_order(eigen_values)) return false;
cv::Mat eigen_vectors_t; cv::transpose(eigen_vectors, eigen_vectors_t); cv::Mat eigen_vectors_t; cv::transpose(eigen_vectors, eigen_vectors_t);
cv::Mat src_evec(src.rows, src.cols, type); cv::Mat src_evec(src.rows, src.cols, type);
src_evec = src*eigen_vectors_t; src_evec = src*eigen_vectors_t;
cv::Mat eval_evec(src.rows, src.cols, type); cv::Mat eval_evec(src.rows, src.cols, type);
switch (type) switch (type)
{ {
case CV_32FC1: case CV_32FC1:
{ {
for (size_t i = 0; i < src.cols; ++i) for (int i = 0; i < src.cols; ++i)
{ {
cv::Mat tmp = eigen_values.at<float>(i, 0) * eigen_vectors_t.col(i); cv::Mat tmp = eigen_values.at<float>(i, 0) * eigen_vectors_t.col(i);
for (size_t j = 0; j < src.rows; ++j) eval_evec.at<float>(j, i) = tmp.at<float>(j, 0); for (int j = 0; j < src.rows; ++j) eval_evec.at<float>(j, i) = tmp.at<float>(j, 0);
} }
break; break;
} }
case CV_64FC1:
{
for (size_t i = 0; i < src.cols; ++i)
{
cv::Mat tmp = eigen_values.at<double>(i, 0) * eigen_vectors_t.col(i);
for (size_t j = 0; j < src.rows; ++j) eval_evec.at<double>(j, i) = tmp.at<double>(j, 0);
}
break; case CV_64FC1:
} {
for (int i = 0; i < src.cols; ++i)
{
cv::Mat tmp = eigen_values.at<double>(i, 0) * eigen_vectors_t.col(i);
for (int j = 0; j < src.rows; ++j) eval_evec.at<double>(j, i) = tmp.at<double>(j, 0);
}
default:; break;
} }
cv::Mat disparity = src_evec - eval_evec; default:;
}
double diff_L1 = cv::norm(disparity, NORM_L1); cv::Mat disparity = src_evec - eval_evec;
double diff_L2 = cv::norm(disparity, NORM_L2);
double diff_INF = cv::norm(disparity, NORM_INF);
if (diff_L1 > eps_vec) { std::cout << "Checking accuracy of eigen vectors computing for matrix " << src << ": L1-criteria..." << endl; CV_Error(CORE_EIGEN_ERROR_DIFF, "Accuracy of eigen vectors computing less than required."); return false; } for (size_t i = 0; i < COUNT_NORM_TYPES; ++i)
if (diff_L2 > eps_vec) { std::cout << "Checking accuracy of eigen vectors computing for matrix " << src << ": L2-criteria..." << endl; CV_Error(CORE_EIGEN_ERROR_DIFF, "Accuracy of eigen vectors computing less than required."); return false; } {
if (diff_INF > eps_vec) { std::cout << "Checking accuracy of eigen vectors computing for matrix " << src << ": INF-criteria..." << endl; CV_Error(CORE_EIGEN_ERROR_DIFF, "Accuracy of eigen vectors computing less than required."); return false; } double diff = cv::norm(disparity, NORM_TYPE[i]);
if (diff > eps_vec)
{
std::cout << endl; std::cout << "Checking accuracy of eigen vectors computing for matrix " << src << ": ";
print_information(i, src, diff, eps_vec);
CV_Error(CORE_EIGEN_ERROR_DIFF, MESSAGE_ERROR_DIFF_2);
return false;
}
}
return true; return true;
} }
bool Core_EigenTest::test_values(const cv::Mat& src) bool Core_EigenTest::test_values(const cv::Mat& src)
{ {
int type = src.type(); int type = src.type();
double eps_val = type == CV_32FC1 ? eps_val_32 : eps_val_64; double eps_val = type == CV_32FC1 ? eps_val_32 : eps_val_64;
cv::Mat eigen_values_1, eigen_values_2, eigen_vectors; cv::Mat eigen_values_1, eigen_values_2, eigen_vectors;
if (!test_pairs(src)) return false; if (!test_pairs(src)) return false;
cv::eigen(src, true, eigen_values_1, eigen_vectors); cv::eigen(src, true, eigen_values_1, eigen_vectors);
cv::eigen(src, false, eigen_values_2, eigen_vectors); cv::eigen(src, false, eigen_values_2, eigen_vectors);
if (!check_pair_count(src, eigen_values_2)) return false; if (!check_pair_count(src, eigen_values_2)) return false;
double diff_L1 = cv::norm(eigen_values_1, eigen_values_2, NORM_L1); for (size_t i = 0; i < COUNT_NORM_TYPES; ++i)
double diff_L2 = cv::norm(eigen_values_1, eigen_values_2, NORM_L2); {
double diff_INF = cv::norm(eigen_values_1, eigen_values_2, NORM_INF); double diff = cv::norm(eigen_values_1, eigen_values_2, NORM_TYPE[i]);
if (diff > eps_val)
if (diff_L1 > eps_val) { std::cout << "Checking accuracy of eigen values computing for matrix " << src << ": L1-criteria..." << endl; CV_Error(CORE_EIGEN_ERROR_DIFF, "Accuracy of eigen values computing less than required."); return false; } {
if (diff_L2 > eps_val) { std::cout << "Checking accuracy of eigen values computing for matrix " << src << ": L2-criteria..." << endl; CV_Error(CORE_EIGEN_ERROR_DIFF, "Accuracy of eigen vectors computing less than required."); return false; } std::cout << endl; std::cout << "Checking accuracy of eigen values computing for matrix " << src << ": ";
if (diff_INF > eps_val) { std::cout << "Checking accuracy of eigen values computing for matrix " << src << ": INF-criteria..." << endl; CV_Error(CORE_EIGEN_ERROR_DIFF, "Accuracy of eigen vectors computing less than required."); return false; } print_information(i, src, diff, eps_val);
CV_Error(CORE_EIGEN_ERROR_DIFF, MESSAGE_ERROR_DIFF_1);
return false;
}
}
return true; return true;
} }
bool Core_EigenTest::check_full(int type) bool Core_EigenTest::check_full(int type)
{ {
const int MATRIX_COUNT = 500; const int MATRIX_COUNT = 500;
const int MAX_DEGREE = 7; const int MAX_DEGREE = 7;
srand(time(0));
for (int i = 1; i <= MATRIX_COUNT; ++i)
{
size_t src_size = (int)(std::pow(2.0, (rand()%MAX_DEGREE+1)*1.0));
srand(time(0)); cv::Mat src(src_size, src_size, type);
for (size_t i = 1; i <= MATRIX_COUNT; ++i) for (int j = 0; j < src.rows; ++j)
{ for (int k = j; k < src.cols; ++k)
size_t src_size = (int)(std::pow(2.0, (rand()%MAX_DEGREE+1)*1.0)); if (type == CV_32FC1) src.at<float>(k, j) = src.at<float>(j, k) = cv::randu<float>();
else src.at<double>(k, j) = src.at<double>(j, k) = cv::randu<double>();
cv::Mat src(src_size, src_size, type);
for (int j = 0; j < src.rows; ++j) if (!test_values(src)) return false;
for (int k = j; k < src.cols; ++k)
if (type == CV_32FC1) src.at<float>(k, j) = src.at<float>(j, k) = cv::randu<float>();
else src.at<double>(k, j) = src.at<double>(j, k) = cv::randu<double>();
if (!test_values(src)) return false;
src.~Mat(); src.~Mat();
} }
return true; return true;
} }
// TEST(Core_Eigen_Scalar_32, single_complex) {Core_EigenTest_Scalar_32 test; test.safe_run(); } // TEST(Core_Eigen_Scalar_32, accuracy) {Core_EigenTest_Scalar_32 test; test.safe_run(); }
// TEST(Core_Eigen_Scalar_64, single_complex) {Core_EigenTest_Scalar_64 test; test.safe_run(); } // TEST(Core_Eigen_Scalar_64, accuracy) {Core_EigenTest_Scalar_64 test; test.safe_run(); }
TEST(Core_Eigen_32, complex) { Core_EigenTest_32 test; test.safe_run(); } TEST(Core_Eigen_32, accuracy) { Core_EigenTest_32 test; test.safe_run(); }
TEST(Core_Eigen_64, complex) { Core_EigenTest_64 test; test.safe_run(); } TEST(Core_Eigen_64, accuracy) { Core_EigenTest_64 test; test.safe_run(); }
\ No newline at end of file
#include "test_precomp.hpp" #include "test_precomp.hpp"
#include <time.h> #include <time.h>
#include <iostream>
#define IMGPROC_BOUNDINGRECT_ERROR_DIFF 1 #define IMGPROC_BOUNDINGRECT_ERROR_DIFF 1
...@@ -11,94 +10,93 @@ using namespace std; ...@@ -11,94 +10,93 @@ using namespace std;
class CV_BoundingRectTest: public cvtest::ArrayTest class CV_BoundingRectTest: public cvtest::ArrayTest
{ {
public: public:
CV_BoundingRectTest(); CV_BoundingRectTest();
~CV_BoundingRectTest(); ~CV_BoundingRectTest();
protected: protected:
void run (int); void run (int);
private: private:
template <class T> void generate_src_points(vector <Point_<T> >& src, int n); template <typename T> void generate_src_points(vector <Point_<T> >& src, int n);
template <class T> cv::Rect get_bounding_rect(const vector <Point_<T> > src); template <typename T> cv::Rect get_bounding_rect(const vector <Point_<T> > src);
template <class T> bool checking_function_work(vector <Point_<T> >& src, int type); template <typename T> bool checking_function_work(vector <Point_<T> >& src, int type);
}; };
CV_BoundingRectTest::CV_BoundingRectTest() {} CV_BoundingRectTest::CV_BoundingRectTest() {}
CV_BoundingRectTest::~CV_BoundingRectTest() {} CV_BoundingRectTest::~CV_BoundingRectTest() {}
template <class T> void CV_BoundingRectTest::generate_src_points(vector <Point_<T> >& src, int n) template <typename T> void CV_BoundingRectTest::generate_src_points(vector <Point_<T> >& src, int n)
{ {
src.clear(); src.clear();
for (size_t i = 0; i < n; ++i) for (int i = 0; i < n; ++i)
src.push_back(Point_<T>(cv::randu<T>(), cv::randu<T>())); src.push_back(Point_<T>(cv::randu<T>(), cv::randu<T>()));
} }
template <class T> cv::Rect CV_BoundingRectTest::get_bounding_rect(const vector <Point_<T> > src) template <typename T> cv::Rect CV_BoundingRectTest::get_bounding_rect(const vector <Point_<T> > src)
{ {
int n = src.size(); int n = src.size();
T min_w = std::numeric_limits<T>::max(), max_w = std::numeric_limits<T>::min(); T min_w = std::numeric_limits<T>::max(), max_w = std::numeric_limits<T>::min();
T min_h = min_w, max_h = max_w; T min_h = min_w, max_h = max_w;
for (size_t i = 0; i < n; ++i) for (int i = 0; i < n; ++i)
{ {
min_w = std::min<T>(src.at(i).x, min_w); min_w = std::min<T>(src.at(i).x, min_w);
max_w = std::max<T>(src.at(i).x, max_w); max_w = std::max<T>(src.at(i).x, max_w);
min_h = std::min<T>(src.at(i).y, min_h); min_h = std::min<T>(src.at(i).y, min_h);
max_h = std::max<T>(src.at(i).y, max_h); max_h = std::max<T>(src.at(i).y, max_h);
} }
return Rect((int)min_w, (int)min_h, (int)(floor(1.0*(max_w-min_w)) + 1), (int)(floor(1.0*(max_h-min_h)) + 1)); return Rect((int)min_w, (int)min_h, (int)(floor(1.0*(max_w-min_w)) + 1), (int)(floor(1.0*(max_h-min_h)) + 1));
} }
template <class T> bool CV_BoundingRectTest::checking_function_work(vector <Point_<T> >& src, int type) template <typename T> bool CV_BoundingRectTest::checking_function_work(vector <Point_<T> >& src, int type)
{ {
const int MAX_COUNT_OF_POINTS = 1000; const int MAX_COUNT_OF_POINTS = 1000;
const int N = 10000; const int N = 10000;
for (int k = 0; k < N; ++k) for (int k = 0; k < N; ++k)
{ {
RNG& rng = ts->get_rng(); RNG& rng = ts->get_rng();
int n = rng.next()%MAX_COUNT_OF_POINTS + 1; int n = rng.next()%MAX_COUNT_OF_POINTS + 1;
generate_src_points <T> (src, n); generate_src_points <T> (src, n);
cv::Rect right = get_bounding_rect <T> (src); cv::Rect right = get_bounding_rect <T> (src);
cv::Rect rect[2] = { boundingRect(src), boundingRect(Mat(src)) }; cv::Rect rect[2] = { boundingRect(src), boundingRect(Mat(src)) };
for (int i = 0; i < 2; ++i) if (rect[i] != right) for (int i = 0; i < 2; ++i) if (rect[i] != right)
{ {
cout << endl; cout << "Checking for the work of boundingRect function..." << endl; cout << endl; cout << "Checking for the work of boundingRect function..." << endl;
cout << "Type of src points: "; cout << "Type of src points: ";
switch (type) switch (type)
{ {
case 0: {cout << "INT"; break;} case 0: {cout << "INT"; break;}
case 1: {cout << "FLOAT"; break;} case 1: {cout << "FLOAT"; break;}
case 2: {cout << "DOUBLE"; break;} default: break;
default: break; }
} cout << endl;
cout << endl; cout << "Src points are stored as "; if (i == 0) cout << "VECTOR" << endl; else cout << "MAT" << endl;
cout << "Src points are stored as "; if (i == 0) cout << "VECTOR" << endl; else cout << "MAT" << endl; cout << "Number of points: " << n << endl;
cout << "Number of points: " << n << endl; cout << "Right rect (x, y, w, h): [" << right.x << ", " << right.y << ", " << right.width << ", " << right.height << "]" << endl;
cout << "Right rect (x, y, w, h): [" << right.x << ", " << right.y << ", " << right.width << ", " << right.height << "]" << endl; cout << "Result rect (x, y, w, h): [" << rect[i].x << ", " << rect[i].y << ", " << rect[i].width << ", " << rect[i].height << "]" << endl;
cout << "Result rect (x, y, w, h): [" << rect[i].x << ", " << rect[i].y << ", " << rect[i].width << ", " << rect[i].height << "]" << endl; cout << endl;
cout << endl; CV_Error(IMGPROC_BOUNDINGRECT_ERROR_DIFF, MESSAGE_ERROR_DIFF);
CV_Error(IMGPROC_BOUNDINGRECT_ERROR_DIFF, MESSAGE_ERROR_DIFF); return false;
return false; }
}
}
}
return true;
return true;
} }
void CV_BoundingRectTest::run(int) void CV_BoundingRectTest::run(int)
{ {
vector <Point> src_veci; if (!checking_function_work(src_veci, 0)) return; vector <Point> src_veci; if (!checking_function_work(src_veci, 0)) return;
vector <Point2f> src_vecf; checking_function_work(src_vecf, 1); vector <Point2f> src_vecf; checking_function_work(src_vecf, 1);
} }
TEST (Imgproc_BoundingRect, accuracy) { CV_BoundingRectTest test; test.safe_run(); } TEST (Imgproc_BoundingRect, accuracy) { CV_BoundingRectTest test; test.safe_run(); }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment