Skip to content

Commit fe86f31

Browse files
ilysenkovAndrey Kamaev
authored andcommitted
Added a test of CvModelEstimator2::checkSubset(...)
1 parent d8f749d commit fe86f31

File tree

2 files changed

+227
-1
lines changed

2 files changed

+227
-1
lines changed

modules/calib3d/src/_modelest.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545

4646
#include "precomp.hpp"
4747

48-
class CvModelEstimator2
48+
class CV_EXPORTS CvModelEstimator2
4949
{
5050
public:
5151
CvModelEstimator2(int _modelPoints, CvSize _modelSize, int _maxBasicSolutions);
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/*M///////////////////////////////////////////////////////////////////////////////////////
2+
//
3+
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4+
//
5+
// By downloading, copying, installing or using the software you agree to this license.
6+
// If you do not agree to this license, do not download, install,
7+
// copy or use the software.
8+
//
9+
//
10+
// Intel License Agreement
11+
// For Open Source Computer Vision Library
12+
//
13+
// Copyright (C) 2000, Intel Corporation, all rights reserved.
14+
// Third party copyrights are property of their respective owners.
15+
//
16+
// Redistribution and use in source and binary forms, with or without modification,
17+
// are permitted provided that the following conditions are met:
18+
//
19+
// * Redistribution's of source code must retain the above copyright notice,
20+
// this list of conditions and the following disclaimer.
21+
//
22+
// * Redistribution's in binary form must reproduce the above copyright notice,
23+
// this list of conditions and the following disclaimer in the documentation
24+
// and/or other materials provided with the distribution.
25+
//
26+
// * The name of Intel Corporation may not be used to endorse or promote products
27+
// derived from this software without specific prior written permission.
28+
//
29+
// This software is provided by the copyright holders and contributors "as is" and
30+
// any express or implied warranties, including, but not limited to, the implied
31+
// warranties of merchantability and fitness for a particular purpose are disclaimed.
32+
// In no event shall the Intel Corporation or contributors be liable for any direct,
33+
// indirect, incidental, special, exemplary, or consequential damages
34+
// (including, but not limited to, procurement of substitute goods or services;
35+
// loss of use, data, or profits; or business interruption) however caused
36+
// and on any theory of liability, whether in contract, strict liability,
37+
// or tort (including negligence or otherwise) arising in any way out of
38+
// the use of this software, even if advised of the possibility of such damage.
39+
//
40+
//M*/
41+
42+
#include "test_precomp.hpp"
43+
#include "_modelest.h"
44+
45+
using namespace cv;
46+
47+
class BareModelEstimator : public CvModelEstimator2
48+
{
49+
public:
50+
BareModelEstimator(int modelPoints, CvSize modelSize, int maxBasicSolutions);
51+
52+
virtual int runKernel( const CvMat*, const CvMat*, CvMat* );
53+
virtual void computeReprojError( const CvMat*, const CvMat*,
54+
const CvMat*, CvMat* );
55+
56+
bool checkSubsetPublic( const CvMat* ms1, int count, bool checkPartialSubset );
57+
};
58+
59+
BareModelEstimator::BareModelEstimator(int _modelPoints, CvSize _modelSize, int _maxBasicSolutions)
60+
:CvModelEstimator2(_modelPoints, _modelSize, _maxBasicSolutions)
61+
{
62+
}
63+
64+
int BareModelEstimator::runKernel( const CvMat*, const CvMat*, CvMat* )
65+
{
66+
return 0;
67+
}
68+
69+
void BareModelEstimator::computeReprojError( const CvMat*, const CvMat*,
70+
const CvMat*, CvMat* )
71+
{
72+
}
73+
74+
bool BareModelEstimator::checkSubsetPublic( const CvMat* ms1, int count, bool checkPartialSubset )
75+
{
76+
checkPartialSubsets = checkPartialSubset;
77+
return checkSubset(ms1, count);
78+
}
79+
80+
class CV_ModelEstimator2_Test : public cvtest::ArrayTest
81+
{
82+
public:
83+
CV_ModelEstimator2_Test();
84+
85+
protected:
86+
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
87+
void fill_array( int test_case_idx, int i, int j, Mat& arr );
88+
double get_success_error_level( int test_case_idx, int i, int j );
89+
void run_func();
90+
void prepare_to_validation( int test_case_idx );
91+
92+
bool checkPartialSubsets;
93+
int usedPointsCount;
94+
95+
bool checkSubsetResult;
96+
int generalPositionsCount;
97+
int maxPointsCount;
98+
};
99+
100+
CV_ModelEstimator2_Test::CV_ModelEstimator2_Test()
101+
{
102+
generalPositionsCount = get_test_case_count() / 2;
103+
maxPointsCount = 100;
104+
105+
test_array[INPUT].push_back(NULL);
106+
test_array[OUTPUT].push_back(NULL);
107+
test_array[REF_OUTPUT].push_back(NULL);
108+
}
109+
110+
void CV_ModelEstimator2_Test::get_test_array_types_and_sizes( int /*test_case_idx*/,
111+
vector<vector<Size> > &sizes, vector<vector<int> > &types )
112+
{
113+
RNG &rng = ts->get_rng();
114+
checkPartialSubsets = (cvtest::randInt(rng) % 2 == 0);
115+
116+
int pointsCount = cvtest::randInt(rng) % maxPointsCount;
117+
usedPointsCount = pointsCount == 0 ? 0 : cvtest::randInt(rng) % pointsCount;
118+
119+
sizes[INPUT][0] = cvSize(1, pointsCount);
120+
types[INPUT][0] = CV_64FC2;
121+
122+
sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(1, 1);
123+
types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_8UC1;
124+
}
125+
126+
void CV_ModelEstimator2_Test::fill_array( int test_case_idx, int i, int j, Mat& arr )
127+
{
128+
if( i != INPUT )
129+
{
130+
cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
131+
return;
132+
}
133+
134+
if (test_case_idx < generalPositionsCount)
135+
{
136+
//generate points in a general position (i.e. no three points can lie on the same line.)
137+
138+
bool isGeneralPosition;
139+
do
140+
{
141+
ArrayTest::fill_array(test_case_idx, i, j, arr);
142+
143+
//a simple check that the position is general:
144+
// for each line check that all other points don't belong to it
145+
isGeneralPosition = true;
146+
for (int startPointIndex = 0; startPointIndex < usedPointsCount && isGeneralPosition; startPointIndex++)
147+
{
148+
for (int endPointIndex = startPointIndex + 1; endPointIndex < usedPointsCount && isGeneralPosition; endPointIndex++)
149+
{
150+
151+
for (int testPointIndex = 0; testPointIndex < usedPointsCount && isGeneralPosition; testPointIndex++)
152+
{
153+
if (testPointIndex == startPointIndex || testPointIndex == endPointIndex)
154+
{
155+
continue;
156+
}
157+
158+
CV_Assert(arr.type() == CV_64FC2);
159+
Point2d tangentVector_1 = arr.at<Point2d>(endPointIndex) - arr.at<Point2d>(startPointIndex);
160+
Point2d tangentVector_2 = arr.at<Point2d>(testPointIndex) - arr.at<Point2d>(startPointIndex);
161+
162+
const float eps = 1e-4;
163+
//TODO: perhaps it is better to normalize the cross product by norms of the tangent vectors
164+
if (fabs(tangentVector_1.cross(tangentVector_2)) < eps)
165+
{
166+
isGeneralPosition = false;
167+
}
168+
}
169+
}
170+
}
171+
}
172+
while(!isGeneralPosition);
173+
}
174+
else
175+
{
176+
//create points in a degenerate position (there are at least 3 points belonging to the same line)
177+
178+
ArrayTest::fill_array(test_case_idx, i, j, arr);
179+
if (usedPointsCount <= 2)
180+
{
181+
return;
182+
}
183+
184+
RNG &rng = ts->get_rng();
185+
int startPointIndex, endPointIndex, modifiedPointIndex;
186+
do
187+
{
188+
startPointIndex = cvtest::randInt(rng) % usedPointsCount;
189+
endPointIndex = cvtest::randInt(rng) % usedPointsCount;
190+
modifiedPointIndex = checkPartialSubsets ? usedPointsCount - 1 : cvtest::randInt(rng) % usedPointsCount;
191+
}
192+
while (startPointIndex == endPointIndex || startPointIndex == modifiedPointIndex || endPointIndex == modifiedPointIndex);
193+
194+
double startWeight = cvtest::randReal(rng);
195+
CV_Assert(arr.type() == CV_64FC2);
196+
arr.at<Point2d>(modifiedPointIndex) = startWeight * arr.at<Point2d>(startPointIndex) + (1.0 - startWeight) * arr.at<Point2d>(endPointIndex);
197+
}
198+
}
199+
200+
201+
double CV_ModelEstimator2_Test::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
202+
{
203+
return 0;
204+
}
205+
206+
void CV_ModelEstimator2_Test::prepare_to_validation( int test_case_idx )
207+
{
208+
test_mat[OUTPUT][0].at<uchar>(0) = checkSubsetResult;
209+
test_mat[REF_OUTPUT][0].at<uchar>(0) = test_case_idx < generalPositionsCount || usedPointsCount <= 2;
210+
}
211+
212+
void CV_ModelEstimator2_Test::run_func()
213+
{
214+
//make the input continuous
215+
Mat input = test_mat[INPUT][0].clone();
216+
CvMat _input = input;
217+
218+
RNG &rng = ts->get_rng();
219+
int modelPoints = cvtest::randInt(rng);
220+
CvSize modelSize = cvSize(2, modelPoints);
221+
int maxBasicSolutions = cvtest::randInt(rng);
222+
BareModelEstimator modelEstimator(modelPoints, modelSize, maxBasicSolutions);
223+
checkSubsetResult = modelEstimator.checkSubsetPublic(&_input, usedPointsCount, checkPartialSubsets);
224+
}
225+
226+
TEST(Calib3d_ModelEstimator2, accuracy) { CV_ModelEstimator2_Test test; test.safe_run(); }

0 commit comments

Comments
 (0)