added to DetectorExtractor test the check of compute() on empty data. Added test for BRIEF.
This commit is contained in:
parent
43716f31b9
commit
0a2881adcd
@ -2109,8 +2109,7 @@ inline void BruteForceMatcher<Distance>::commonKnnMatchImpl( BruteForceMatcher<D
|
|||||||
size_t imgCount = matcher.trainDescCollection.size();
|
size_t imgCount = matcher.trainDescCollection.size();
|
||||||
vector<Mat> allDists( imgCount ); // distances between one query descriptor and all train descriptors
|
vector<Mat> allDists( imgCount ); // distances between one query descriptor and all train descriptors
|
||||||
for( size_t i = 0; i < imgCount; i++ )
|
for( size_t i = 0; i < imgCount; i++ )
|
||||||
if( matcher.trainDescCollection[i].rows )
|
allDists[i] = Mat( 1, matcher.trainDescCollection[i].rows, DataType<DistanceType>::type );
|
||||||
allDists[i] = Mat( 1, matcher.trainDescCollection[i].rows, DataType<DistanceType>::type );
|
|
||||||
|
|
||||||
for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
|
for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
|
||||||
{
|
{
|
||||||
|
@ -358,7 +358,7 @@ Ptr<DescriptorExtractor> createDescriptorExtractor(const string& descriptorExtra
|
|||||||
}
|
}
|
||||||
else if (!descriptorExtractorType.compare("BRIEF"))
|
else if (!descriptorExtractorType.compare("BRIEF"))
|
||||||
{
|
{
|
||||||
de = new BriefDescriptorExtractor(32);
|
de = new BriefDescriptorExtractor();
|
||||||
}
|
}
|
||||||
return de;
|
return de;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ void CV_FeatureDetectorTest::emptyDataTest()
|
|||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
ts->printf( CvTS::LOG, "emptyDataTest: Detect() on empty image must not generate exeption\n" );
|
ts->printf( CvTS::LOG, "emptyDataTest: Detect() on empty image must not generate exception\n" );
|
||||||
ts->set_failed_test_info( CvTS::FAIL_INVALID_OUTPUT );
|
ts->set_failed_test_info( CvTS::FAIL_INVALID_OUTPUT );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -267,25 +267,86 @@ static Mat readMatFromBin( const string& filename )
|
|||||||
return Mat();
|
return Mat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Distance>
|
||||||
class CV_DescriptorExtractorTest : public CvTest
|
class CV_DescriptorExtractorTest : public CvTest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CV_DescriptorExtractorTest( const char* testName, float _maxNormDif, const Ptr<DescriptorExtractor>& _dextractor, float _prevTime ) :
|
typedef typename Distance::ValueType ValueType;
|
||||||
CvTest( testName, "cv::DescriptorExtractor::compute" ), maxNormDif(_maxNormDif), prevTime(_prevTime), dextractor(_dextractor) {}
|
typedef typename Distance::ResultType DistanceType;
|
||||||
|
|
||||||
|
CV_DescriptorExtractorTest( const char* testName, DistanceType _maxDistDif, const Ptr<DescriptorExtractor>& _dextractor, float _prevTime,
|
||||||
|
Distance d = Distance() ):
|
||||||
|
CvTest( testName, "cv::DescriptorExtractor::compute" ),
|
||||||
|
maxDistDif(_maxDistDif), prevTime(_prevTime), dextractor(_dextractor), distance(d) {}
|
||||||
protected:
|
protected:
|
||||||
virtual void createDescriptorExtractor() {}
|
virtual void createDescriptorExtractor() {}
|
||||||
|
|
||||||
void run(int)
|
void compareDescriptors( const Mat& validDescriptors, const Mat& calcDescriptors )
|
||||||
{
|
{
|
||||||
createDescriptorExtractor();
|
if( validDescriptors.size != calcDescriptors.size || validDescriptors.type() != calcDescriptors.type() )
|
||||||
|
|
||||||
if( dextractor.empty() )
|
|
||||||
{
|
{
|
||||||
ts->printf(CvTS::LOG, "Descriptor extractor is empty\n");
|
ts->printf(CvTS::LOG, "Valid and computed descriptors matrices must have the same size and type\n");
|
||||||
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
|
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CV_Assert( DataType<ValueType>::type == validDescriptors.type() );
|
||||||
|
|
||||||
|
int dimension = validDescriptors.cols;
|
||||||
|
DistanceType maxDist = std::numeric_limits<DistanceType>::min();
|
||||||
|
for( int y = 0; y < validDescriptors.rows; y++ )
|
||||||
|
{
|
||||||
|
DistanceType dist = distance( validDescriptors.ptr<ValueType>(y), calcDescriptors.ptr<ValueType>(y), dimension );
|
||||||
|
if( dist > maxDistDif)
|
||||||
|
{
|
||||||
|
stringstream ss;
|
||||||
|
ss << "Discance between valid and computed " << y << "-descriptors > " << maxDistDif << endl;
|
||||||
|
ts->printf(CvTS::LOG, ss.str().c_str() );
|
||||||
|
ts->set_failed_test_info( CvTS::FAIL_BAD_ACCURACY );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( dist > maxDist )
|
||||||
|
maxDist = dist;
|
||||||
|
}
|
||||||
|
stringstream ss;
|
||||||
|
ss << "regressionTest: Max discance between valid and computed descriptors " << maxDist << endl;
|
||||||
|
ts->printf(CvTS::LOG, ss.str().c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void emptyDataTest()
|
||||||
|
{
|
||||||
|
assert( !dextractor.empty() );
|
||||||
|
Mat image;
|
||||||
|
vector<KeyPoint> keypoints;
|
||||||
|
Mat descriptors;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dextractor->compute( image, keypoints, descriptors );
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
ts->printf( CvTS::LOG, "emptyDataTest: compute() on empty image and empty keypoints must not generate exception\n");
|
||||||
|
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
|
||||||
|
}
|
||||||
|
|
||||||
|
image.create( 50, 50, CV_8UC3 );
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dextractor->compute( image, keypoints, descriptors );
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
ts->printf( CvTS::LOG, "emptyDataTest: compute() on nonempty image and empty keypoints must not generate exception\n");
|
||||||
|
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void regressionTest()
|
||||||
|
{
|
||||||
|
assert( !dextractor.empty() );
|
||||||
|
|
||||||
|
// Read the test image.
|
||||||
string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME;
|
string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME;
|
||||||
Mat img = imread( imgFilename, 0 );
|
Mat img = imread( imgFilename, 0 );
|
||||||
if( img.empty() )
|
if( img.empty() )
|
||||||
@ -298,7 +359,43 @@ protected:
|
|||||||
vector<KeyPoint> keypoints;
|
vector<KeyPoint> keypoints;
|
||||||
FileStorage fs( string(ts->get_data_path()) + FEATURES2D_DIR + "/keypoints.xml.gz", FileStorage::READ );
|
FileStorage fs( string(ts->get_data_path()) + FEATURES2D_DIR + "/keypoints.xml.gz", FileStorage::READ );
|
||||||
if( fs.isOpened() )
|
if( fs.isOpened() )
|
||||||
|
{
|
||||||
read( fs.getFirstTopLevelNode(), keypoints );
|
read( fs.getFirstTopLevelNode(), keypoints );
|
||||||
|
|
||||||
|
Mat calcDescriptors;
|
||||||
|
double t = (double)getTickCount();
|
||||||
|
dextractor->compute( img, keypoints, calcDescriptors );
|
||||||
|
t = getTickCount() - t;
|
||||||
|
ts->printf(CvTS::LOG, "\nregressionTest: Average time of computiting one descriptor = %g ms (previous time = %g ms)\n", t/((double)cvGetTickFrequency()*1000.)/calcDescriptors.rows, prevTime );
|
||||||
|
|
||||||
|
if( calcDescriptors.rows != (int)keypoints.size() )
|
||||||
|
{
|
||||||
|
ts->printf( CvTS::LOG, "Count of computed descriptors and keypoints count must be equal\n" );
|
||||||
|
ts->set_failed_test_info( CvTS::FAIL_INVALID_OUTPUT );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( calcDescriptors.cols != dextractor->descriptorSize() || calcDescriptors.type() != dextractor->descriptorType() )
|
||||||
|
{
|
||||||
|
ts->printf( CvTS::LOG, "Incorrect descriptor size or descriptor type\n" );
|
||||||
|
ts->set_failed_test_info( CvTS::FAIL_INVALID_OUTPUT );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO read and write descriptor extractor parameters and check them
|
||||||
|
Mat validDescriptors = readDescriptors();
|
||||||
|
if( !validDescriptors.empty() )
|
||||||
|
compareDescriptors( validDescriptors, calcDescriptors );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( !writeDescriptors( calcDescriptors ) )
|
||||||
|
{
|
||||||
|
ts->printf( CvTS::LOG, "Descriptors can not be written\n" );
|
||||||
|
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ts->printf( CvTS::LOG, "Compute and write keypoints\n" );
|
ts->printf( CvTS::LOG, "Compute and write keypoints\n" );
|
||||||
@ -316,31 +413,22 @@ protected:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Mat calcDescriptors;
|
void run(int)
|
||||||
double t = (double)getTickCount();
|
{
|
||||||
dextractor->compute( img, keypoints, calcDescriptors );
|
createDescriptorExtractor();
|
||||||
t = getTickCount() - t;
|
if( dextractor.empty() )
|
||||||
ts->printf(CvTS::LOG, "\nAverage time of computiting one descriptor = %g ms (previous time = %g ms)\n", t/((double)cvGetTickFrequency()*1000.)/calcDescriptors.rows, prevTime );
|
{
|
||||||
|
ts->printf(CvTS::LOG, "Descriptor extractor is empty\n");
|
||||||
|
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO read and write descriptor extractor parameters and check them
|
emptyDataTest();
|
||||||
Mat validDescriptors = readDescriptors();
|
regressionTest();
|
||||||
if( !validDescriptors.empty() )
|
|
||||||
{
|
ts->set_failed_test_info( CvTS::OK );
|
||||||
double normValue = norm( calcDescriptors, validDescriptors, NORM_INF );
|
|
||||||
ts->printf( CvTS::LOG, "nofm (inf) BTW valid and calculated float descriptors = %f\n", normValue );
|
|
||||||
if( normValue > maxNormDif )
|
|
||||||
ts->set_failed_test_info( CvTS::FAIL_BAD_ACCURACY );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( !writeDescriptors( calcDescriptors ) )
|
|
||||||
{
|
|
||||||
ts->printf( CvTS::LOG, "Descriptors can not be written\n" );
|
|
||||||
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Mat readDescriptors()
|
virtual Mat readDescriptors()
|
||||||
@ -355,23 +443,27 @@ protected:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float maxNormDif;
|
const DistanceType maxDistDif;
|
||||||
const float prevTime;
|
const float prevTime;
|
||||||
|
|
||||||
Ptr<DescriptorExtractor> dextractor;
|
Ptr<DescriptorExtractor> dextractor;
|
||||||
|
Distance distance;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, typename Distance>
|
||||||
class CV_CalonderDescriptorExtractorTest : public CV_DescriptorExtractorTest
|
class CV_CalonderDescriptorExtractorTest : public CV_DescriptorExtractorTest<Distance>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CV_CalonderDescriptorExtractorTest( const char* testName, float _normDif, float _prevTime ) :
|
CV_CalonderDescriptorExtractorTest( const char* testName, float _normDif, float _prevTime ) :
|
||||||
CV_DescriptorExtractorTest( testName, _normDif, Ptr<DescriptorExtractor>(), _prevTime )
|
CV_DescriptorExtractorTest<Distance>( testName, _normDif, Ptr<DescriptorExtractor>(), _prevTime )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
protected:
|
||||||
virtual void createDescriptorExtractor()
|
virtual void createDescriptorExtractor()
|
||||||
{
|
{
|
||||||
dextractor = new CalonderDescriptorExtractor<T>( string(ts->get_data_path()) + FEATURES2D_DIR + "/calonder_classifier.rtc");
|
CV_DescriptorExtractorTest<Distance>::dextractor =
|
||||||
|
new CalonderDescriptorExtractor<T>( string(CV_DescriptorExtractorTest<Distance>::ts->get_data_path()) +
|
||||||
|
FEATURES2D_DIR + "/calonder_classifier.rtc");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -782,21 +874,25 @@ CV_FeatureDetectorTest surfTest( "detector-surf", createFeatureDetector("SURF")
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Descriptors
|
* Descriptors
|
||||||
|
* "descriptor-sift, descriptor-surf, descriptor-calonder-uchar, descriptor-calonder-float, descriptor-brief"
|
||||||
*/
|
*/
|
||||||
CV_DescriptorExtractorTest siftDescriptorTest( "descriptor-sift", 0.03f,
|
CV_DescriptorExtractorTest<L2<float> > siftDescriptorTest( "descriptor-sift", 0.03f,
|
||||||
createDescriptorExtractor("SIFT"), 8.06652f );
|
createDescriptorExtractor("SIFT"), 8.06652f );
|
||||||
CV_DescriptorExtractorTest surfDescriptorTest( "descriptor-surf", 0.035f,
|
CV_DescriptorExtractorTest<L2<float> > surfDescriptorTest( "descriptor-surf", 0.035f,
|
||||||
createDescriptorExtractor("SURF"), 0.147372f );
|
createDescriptorExtractor("SURF"), 0.147372f );
|
||||||
|
CV_DescriptorExtractorTest<Hamming> briefDescriptorTest( "descriptor-brief", 1,
|
||||||
|
createDescriptorExtractor("BRIEF"), 0.00527548 );
|
||||||
|
|
||||||
//CV_DescriptorExtractorTest oppSiftDescriptorTest( "descriptor-opponent-sift", 0.008f,
|
//CV_DescriptorExtractorTest oppSiftDescriptorTest( "descriptor-opponent-sift", 0.008f,
|
||||||
// createDescriptorExtractor("OpponentSIFT"), 8.06652f );
|
// createDescriptorExtractor("OpponentSIFT"), 8.06652f );
|
||||||
//CV_DescriptorExtractorTest oppurfDescriptorTest( "descriptor-opponent-surf", 0.02f,
|
//CV_DescriptorExtractorTest oppurfDescriptorTest( "descriptor-opponent-surf", 0.02f,
|
||||||
// createDescriptorExtractor("OpponentSURF"), 0.147372f );
|
// createDescriptorExtractor("OpponentSURF"), 0.147372f );
|
||||||
|
|
||||||
#if CV_SSE2
|
#if CV_SSE2
|
||||||
CV_CalonderDescriptorExtractorTest<uchar> ucharCalonderTest( "descriptor-calonder-uchar",
|
CV_CalonderDescriptorExtractorTest<uchar, L2<uchar> > ucharCalonderTest( "descriptor-calonder-uchar",
|
||||||
std::numeric_limits<float>::epsilon() + 1,
|
std::numeric_limits<float>::epsilon() + 1,
|
||||||
0.0132175f );
|
0.0132175f );
|
||||||
CV_CalonderDescriptorExtractorTest<float> floatCalonderTest( "descriptor-calonder-float",
|
CV_CalonderDescriptorExtractorTest<float, L2<float> > floatCalonderTest( "descriptor-calonder-float",
|
||||||
std::numeric_limits<float>::epsilon(),
|
std::numeric_limits<float>::epsilon(),
|
||||||
0.0221308f );
|
0.0221308f );
|
||||||
#endif // CV_SSE2
|
#endif // CV_SSE2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user