mirror of
https://github.com/opencv/opencv.git
synced 2026-09-25 04:09:57 +03:00
Merge pull request #29753 from Prasadayus:test_cleanup_geometry
Geometry:Test cleanup - #29753 **co-authored by: @varun-jaiswal17** ### geometry test cleanup ### Removed (dead or unbuildable) - `test_modelest.cpp` (231 lines, removed entirely): includes `_modelest.h` and subclasses `CvModelEstimator2`, both of which are gone from the tree, so it cannot compile. - `test_cameras.cpp:11-207` (197 lines removed): a `#if 0` block, never compiled, holding an older `cvtest::ArrayTest`-based `CV_ProjectPointsTest` built on the removed C API (`CvMat`, `cvProjectPoints2`). A live class of the same name derived from `cvtest::BaseTest` follows it and covers strictly more: `Rodrigues` plus five jacobians against the dead block's two. ### Given real assertions - `Calib3d_FindFundamentalMat.correctMatches` (`test_fundam.cpp:410`): reverting the solvePoly fix gives -nan / 1.79e+308 and it still passed. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -8,203 +8,6 @@
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
#if 0
|
||||
class CV_ProjectPointsTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_ProjectPointsTest();
|
||||
|
||||
protected:
|
||||
int read_params( const cv::FileStorage& fs );
|
||||
void fill_array( int test_case_idx, int i, int j, Mat& arr );
|
||||
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 );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
void run_func();
|
||||
void prepare_to_validation( int );
|
||||
|
||||
bool calc_jacobians;
|
||||
};
|
||||
|
||||
|
||||
CV_ProjectPointsTest::CV_ProjectPointsTest()
|
||||
: cvtest::ArrayTest( "3d-ProjectPoints", "cvProjectPoints2", "" )
|
||||
{
|
||||
test_array[INPUT].push_back(NULL); // rotation vector
|
||||
test_array[OUTPUT].push_back(NULL); // rotation matrix
|
||||
test_array[OUTPUT].push_back(NULL); // jacobian (J)
|
||||
test_array[OUTPUT].push_back(NULL); // rotation vector (backward transform result)
|
||||
test_array[OUTPUT].push_back(NULL); // inverse transform jacobian (J1)
|
||||
test_array[OUTPUT].push_back(NULL); // J*J1 (or J1*J) == I(3x3)
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
|
||||
element_wise_relative_error = false;
|
||||
calc_jacobians = false;
|
||||
}
|
||||
|
||||
|
||||
int CV_ProjectPointsTest::read_params( const cv::FileStorage& fs )
|
||||
{
|
||||
int code = cvtest::ArrayTest::read_params( fs );
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
void CV_ProjectPointsTest::get_test_array_types_and_sizes(
|
||||
int /*test_case_idx*/, vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
int depth = cvtest::randInt(rng) % 2 == 0 ? CV_32F : CV_64F;
|
||||
int i, code;
|
||||
|
||||
code = cvtest::randInt(rng) % 3;
|
||||
types[INPUT][0] = CV_MAKETYPE(depth, 1);
|
||||
|
||||
if( code == 0 )
|
||||
{
|
||||
sizes[INPUT][0] = cvSize(1,1);
|
||||
types[INPUT][0] = CV_MAKETYPE(depth, 3);
|
||||
}
|
||||
else if( code == 1 )
|
||||
sizes[INPUT][0] = cvSize(3,1);
|
||||
else
|
||||
sizes[INPUT][0] = cvSize(1,3);
|
||||
|
||||
sizes[OUTPUT][0] = cvSize(3, 3);
|
||||
types[OUTPUT][0] = CV_MAKETYPE(depth, 1);
|
||||
|
||||
types[OUTPUT][1] = CV_MAKETYPE(depth, 1);
|
||||
|
||||
if( cvtest::randInt(rng) % 2 )
|
||||
sizes[OUTPUT][1] = cvSize(3,9);
|
||||
else
|
||||
sizes[OUTPUT][1] = cvSize(9,3);
|
||||
|
||||
types[OUTPUT][2] = types[INPUT][0];
|
||||
sizes[OUTPUT][2] = sizes[INPUT][0];
|
||||
|
||||
types[OUTPUT][3] = types[OUTPUT][1];
|
||||
sizes[OUTPUT][3] = cvSize(sizes[OUTPUT][1].height, sizes[OUTPUT][1].width);
|
||||
|
||||
types[OUTPUT][4] = types[OUTPUT][1];
|
||||
sizes[OUTPUT][4] = cvSize(3,3);
|
||||
|
||||
calc_jacobians = 1;//cvtest::randInt(rng) % 3 != 0;
|
||||
if( !calc_jacobians )
|
||||
sizes[OUTPUT][1] = sizes[OUTPUT][3] = sizes[OUTPUT][4] = cvSize(0,0);
|
||||
|
||||
for( i = 0; i < 5; i++ )
|
||||
{
|
||||
types[REF_OUTPUT][i] = types[OUTPUT][i];
|
||||
sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double CV_ProjectPointsTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int j )
|
||||
{
|
||||
return j == 4 ? 1e-2 : 1e-2;
|
||||
}
|
||||
|
||||
|
||||
void CV_ProjectPointsTest::fill_array( int /*test_case_idx*/, int /*i*/, int /*j*/, CvMat* arr )
|
||||
{
|
||||
double r[3], theta0, theta1, f;
|
||||
CvMat _r = cvMat( arr->rows, arr->cols, CV_MAKETYPE(CV_64F,CV_MAT_CN(arr->type)), r );
|
||||
RNG& rng = ts->get_rng();
|
||||
|
||||
r[0] = cvtest::randReal(rng)*CV_PI*2;
|
||||
r[1] = cvtest::randReal(rng)*CV_PI*2;
|
||||
r[2] = cvtest::randReal(rng)*CV_PI*2;
|
||||
|
||||
theta0 = sqrt(r[0]*r[0] + r[1]*r[1] + r[2]*r[2]);
|
||||
theta1 = fmod(theta0, CV_PI*2);
|
||||
|
||||
if( theta1 > CV_PI )
|
||||
theta1 = -(CV_PI*2 - theta1);
|
||||
|
||||
f = theta1/(theta0 ? theta0 : 1);
|
||||
r[0] *= f;
|
||||
r[1] *= f;
|
||||
r[2] *= f;
|
||||
|
||||
cvTsConvert( &_r, arr );
|
||||
}
|
||||
|
||||
|
||||
int CV_ProjectPointsTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
void CV_ProjectPointsTest::run_func()
|
||||
{
|
||||
CvMat *v2m_jac = 0, *m2v_jac = 0;
|
||||
if( calc_jacobians )
|
||||
{
|
||||
v2m_jac = &test_mat[OUTPUT][1];
|
||||
m2v_jac = &test_mat[OUTPUT][3];
|
||||
}
|
||||
|
||||
cvProjectPoints2( &test_mat[INPUT][0], &test_mat[OUTPUT][0], v2m_jac );
|
||||
cvProjectPoints2( &test_mat[OUTPUT][0], &test_mat[OUTPUT][2], m2v_jac );
|
||||
}
|
||||
|
||||
|
||||
void CV_ProjectPointsTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
{
|
||||
const CvMat* vec = &test_mat[INPUT][0];
|
||||
CvMat* m = &test_mat[REF_OUTPUT][0];
|
||||
CvMat* vec2 = &test_mat[REF_OUTPUT][2];
|
||||
CvMat* v2m_jac = 0, *m2v_jac = 0;
|
||||
double theta0, theta1;
|
||||
|
||||
if( calc_jacobians )
|
||||
{
|
||||
v2m_jac = &test_mat[REF_OUTPUT][1];
|
||||
m2v_jac = &test_mat[REF_OUTPUT][3];
|
||||
}
|
||||
|
||||
|
||||
cvTsProjectPoints( vec, m, v2m_jac );
|
||||
cvTsProjectPoints( m, vec2, m2v_jac );
|
||||
cvTsCopy( vec, vec2 );
|
||||
|
||||
theta0 = cvtest::norm( cvarrtomat(vec2), 0, NORM_L2 );
|
||||
theta1 = fmod( theta0, CV_PI*2 );
|
||||
|
||||
if( theta1 > CV_PI )
|
||||
theta1 = -(CV_PI*2 - theta1);
|
||||
cvScale( vec2, vec2, theta1/(theta0 ? theta0 : 1) );
|
||||
|
||||
if( calc_jacobians )
|
||||
{
|
||||
//cvInvert( v2m_jac, m2v_jac, CV_SVD );
|
||||
if( cvtest::norm(cvarrtomat(&test_mat[OUTPUT][3]), 0, NORM_INF) < 1000 )
|
||||
{
|
||||
cvTsGEMM( &test_mat[OUTPUT][1], &test_mat[OUTPUT][3],
|
||||
1, 0, 0, &test_mat[OUTPUT][4],
|
||||
v2m_jac->rows == 3 ? 0 : CV_GEMM_A_T + CV_GEMM_B_T );
|
||||
}
|
||||
else
|
||||
{
|
||||
cvTsSetIdentity( &test_mat[OUTPUT][4], cvScalarAll(1.) );
|
||||
cvTsCopy( &test_mat[REF_OUTPUT][2], &test_mat[OUTPUT][2] );
|
||||
}
|
||||
cvTsSetIdentity( &test_mat[REF_OUTPUT][4], cvScalarAll(1.) );
|
||||
}
|
||||
}
|
||||
|
||||
CV_ProjectPointsTest ProjectPoints_test;
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------- CV_ProjectPointsTest --------------------------------
|
||||
void calcdfdx( const vector<vector<Point2f> >& leftF, const vector<vector<Point2f> >& rightF, double eps, Mat& dfdx )
|
||||
{
|
||||
|
||||
@@ -403,6 +403,9 @@ void CV_ComputeEpilinesTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
TEST(Calib3d_ConvertHomogeneoous, accuracy) { CV_ConvertHomogeneousTest test; test.safe_run(); }
|
||||
TEST(Calib3d_ComputeEpilines, accuracy) { CV_ComputeEpilinesTest test; test.safe_run(); }
|
||||
|
||||
// Regression test for https://github.com/opencv/opencv/issues/4330, fixed by 85149f8686. Both
|
||||
// epipoles at infinity collapses the 6th-degree polynomial correctMatches() solves; cv::solvePoly()
|
||||
// used to return garbage roots for it, giving NaN / DBL_MAX. These checks keep that closed.
|
||||
TEST(Calib3d_FindFundamentalMat, correctMatches)
|
||||
{
|
||||
double fdata[] = {0, 0, 0, 0, 0, -1, 0, 1, 0};
|
||||
@@ -416,8 +419,19 @@ TEST(Calib3d_FindFundamentalMat, correctMatches)
|
||||
|
||||
correctMatches(F, p1, p2, np1, np2);
|
||||
|
||||
cout << np1 << endl;
|
||||
cout << np2 << endl;
|
||||
ASSERT_EQ(p1.size(), np1.size());
|
||||
ASSERT_EQ(p1.type(), np1.type());
|
||||
ASSERT_EQ(p2.size(), np2.size());
|
||||
ASSERT_EQ(p2.type(), np2.type());
|
||||
|
||||
// rejects NaN and DBL_MAX, the pre-fix output
|
||||
EXPECT_TRUE(cv::checkRange(np1)) << "np1 = " << np1;
|
||||
EXPECT_TRUE(cv::checkRange(np2)) << "np2 = " << np2;
|
||||
|
||||
// The input pair already satisfies p2^T * F * p1 == 0 exactly, so the
|
||||
// optimal correction is zero and both points must come back unchanged.
|
||||
EXPECT_LE(cv::norm(np1, p1, NORM_INF), 1e-9) << "np1 = " << np1;
|
||||
EXPECT_LE(cv::norm(np2, p2, NORM_INF), 1e-9) << "np2 = " << np2;
|
||||
}
|
||||
|
||||
TEST(Calib3d_FindFundamentalMat, Crash)
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#if 0
|
||||
#include "_modelest.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
class BareModelEstimator : public CvModelEstimator2
|
||||
{
|
||||
public:
|
||||
BareModelEstimator(int modelPoints, CvSize modelSize, int maxBasicSolutions);
|
||||
|
||||
virtual int runKernel( const CvMat*, const CvMat*, CvMat* );
|
||||
virtual void computeReprojError( const CvMat*, const CvMat*,
|
||||
const CvMat*, CvMat* );
|
||||
|
||||
bool checkSubsetPublic( const CvMat* ms1, int count, bool checkPartialSubset );
|
||||
};
|
||||
|
||||
BareModelEstimator::BareModelEstimator(int _modelPoints, CvSize _modelSize, int _maxBasicSolutions)
|
||||
:CvModelEstimator2(_modelPoints, _modelSize, _maxBasicSolutions)
|
||||
{
|
||||
}
|
||||
|
||||
int BareModelEstimator::runKernel( const CvMat*, const CvMat*, CvMat* )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BareModelEstimator::computeReprojError( const CvMat*, const CvMat*,
|
||||
const CvMat*, CvMat* )
|
||||
{
|
||||
}
|
||||
|
||||
bool BareModelEstimator::checkSubsetPublic( const CvMat* ms1, int count, bool checkPartialSubset )
|
||||
{
|
||||
checkPartialSubsets = checkPartialSubset;
|
||||
return checkSubset(ms1, count);
|
||||
}
|
||||
|
||||
class CV_ModelEstimator2_Test : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_ModelEstimator2_Test();
|
||||
|
||||
protected:
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
void fill_array( int test_case_idx, int i, int j, Mat& arr );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
void run_func();
|
||||
void prepare_to_validation( int test_case_idx );
|
||||
|
||||
bool checkPartialSubsets;
|
||||
int usedPointsCount;
|
||||
|
||||
bool checkSubsetResult;
|
||||
int generalPositionsCount;
|
||||
int maxPointsCount;
|
||||
};
|
||||
|
||||
CV_ModelEstimator2_Test::CV_ModelEstimator2_Test()
|
||||
{
|
||||
generalPositionsCount = get_test_case_count() / 2;
|
||||
maxPointsCount = 100;
|
||||
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
}
|
||||
|
||||
void CV_ModelEstimator2_Test::get_test_array_types_and_sizes( int /*test_case_idx*/,
|
||||
vector<vector<Size> > &sizes, vector<vector<int> > &types )
|
||||
{
|
||||
RNG &rng = ts->get_rng();
|
||||
checkPartialSubsets = (cvtest::randInt(rng) % 2 == 0);
|
||||
|
||||
int pointsCount = cvtest::randInt(rng) % maxPointsCount;
|
||||
usedPointsCount = pointsCount == 0 ? 0 : cvtest::randInt(rng) % pointsCount;
|
||||
|
||||
sizes[INPUT][0] = cvSize(1, pointsCount);
|
||||
types[INPUT][0] = CV_64FC2;
|
||||
|
||||
sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(1, 1);
|
||||
types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_8UC1;
|
||||
}
|
||||
|
||||
void CV_ModelEstimator2_Test::fill_array( int test_case_idx, int i, int j, Mat& arr )
|
||||
{
|
||||
if( i != INPUT )
|
||||
{
|
||||
cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_case_idx < generalPositionsCount)
|
||||
{
|
||||
//generate points in a general position (i.e. no three points can lie on the same line.)
|
||||
|
||||
bool isGeneralPosition;
|
||||
do
|
||||
{
|
||||
ArrayTest::fill_array(test_case_idx, i, j, arr);
|
||||
|
||||
//a simple check that the position is general:
|
||||
// for each line check that all other points don't belong to it
|
||||
isGeneralPosition = true;
|
||||
for (int startPointIndex = 0; startPointIndex < usedPointsCount && isGeneralPosition; startPointIndex++)
|
||||
{
|
||||
for (int endPointIndex = startPointIndex + 1; endPointIndex < usedPointsCount && isGeneralPosition; endPointIndex++)
|
||||
{
|
||||
|
||||
for (int testPointIndex = 0; testPointIndex < usedPointsCount && isGeneralPosition; testPointIndex++)
|
||||
{
|
||||
if (testPointIndex == startPointIndex || testPointIndex == endPointIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CV_Assert(arr.type() == CV_64FC2);
|
||||
Point2d tangentVector_1 = arr.at<Point2d>(endPointIndex) - arr.at<Point2d>(startPointIndex);
|
||||
Point2d tangentVector_2 = arr.at<Point2d>(testPointIndex) - arr.at<Point2d>(startPointIndex);
|
||||
|
||||
const float eps = 1e-4f;
|
||||
//TODO: perhaps it is better to normalize the cross product by norms of the tangent vectors
|
||||
if (fabs(tangentVector_1.cross(tangentVector_2)) < eps)
|
||||
{
|
||||
isGeneralPosition = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while(!isGeneralPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
//create points in a degenerate position (there are at least 3 points belonging to the same line)
|
||||
|
||||
ArrayTest::fill_array(test_case_idx, i, j, arr);
|
||||
if (usedPointsCount <= 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RNG &rng = ts->get_rng();
|
||||
int startPointIndex, endPointIndex, modifiedPointIndex;
|
||||
do
|
||||
{
|
||||
startPointIndex = cvtest::randInt(rng) % usedPointsCount;
|
||||
endPointIndex = cvtest::randInt(rng) % usedPointsCount;
|
||||
modifiedPointIndex = checkPartialSubsets ? usedPointsCount - 1 : cvtest::randInt(rng) % usedPointsCount;
|
||||
}
|
||||
while (startPointIndex == endPointIndex || startPointIndex == modifiedPointIndex || endPointIndex == modifiedPointIndex);
|
||||
|
||||
double startWeight = cvtest::randReal(rng);
|
||||
CV_Assert(arr.type() == CV_64FC2);
|
||||
arr.at<Point2d>(modifiedPointIndex) = startWeight * arr.at<Point2d>(startPointIndex) + (1.0 - startWeight) * arr.at<Point2d>(endPointIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double CV_ModelEstimator2_Test::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CV_ModelEstimator2_Test::prepare_to_validation( int test_case_idx )
|
||||
{
|
||||
test_mat[OUTPUT][0].at<uchar>(0) = checkSubsetResult;
|
||||
test_mat[REF_OUTPUT][0].at<uchar>(0) = test_case_idx < generalPositionsCount || usedPointsCount <= 2;
|
||||
}
|
||||
|
||||
void CV_ModelEstimator2_Test::run_func()
|
||||
{
|
||||
//make the input continuous
|
||||
Mat input = test_mat[INPUT][0].clone();
|
||||
CvMat _input = input;
|
||||
|
||||
RNG &rng = ts->get_rng();
|
||||
int modelPoints = cvtest::randInt(rng);
|
||||
CvSize modelSize = cvSize(2, modelPoints);
|
||||
int maxBasicSolutions = cvtest::randInt(rng);
|
||||
BareModelEstimator modelEstimator(modelPoints, modelSize, maxBasicSolutions);
|
||||
checkSubsetResult = modelEstimator.checkSubsetPublic(&_input, usedPointsCount, checkPartialSubsets);
|
||||
}
|
||||
|
||||
TEST(Calib3d_ModelEstimator2, accuracy) { CV_ModelEstimator2_Test test; test.safe_run(); }
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user