merged regression tests for FeatureDetector, DescriptorExtractor from branch .features2d;

renamed createDetector to createFeatureDetector
This commit is contained in:
Maria Dimashova 2010-09-17 11:26:58 +00:00
parent eab003d06e
commit 8ab3fdbcca
6 changed files with 340 additions and 6 deletions

View File

@ -1354,7 +1354,7 @@ protected:
SURF surf;
};
CV_EXPORTS Ptr<FeatureDetector> createDetector( const string& detectorType );
CV_EXPORTS Ptr<FeatureDetector> createFeatureDetector( const string& detectorType );
/*
* Adapts a detector to partition the source image into a grid and detect

View File

@ -316,7 +316,7 @@ void SurfFeatureDetector::detectImpl( const Mat& image, const Mat& mask,
surf(image, mask, keypoints);
}
Ptr<FeatureDetector> createDetector( const string& detectorType )
Ptr<FeatureDetector> createFeatureDetector( const string& detectorType )
{
FeatureDetector* fd = 0;
if( !detectorType.compare( "FAST" ) )

View File

@ -651,7 +651,7 @@ int main(int argc, char** argv)
Size calibratedImageSize;
readCameraMatrix(intrinsicsFilename, cameraMatrix, distCoeffs, calibratedImageSize);
Ptr<FeatureDetector> detector = createDetector(detectorName);
Ptr<FeatureDetector> detector = createFeatureDetector(detectorName);
Ptr<DescriptorExtractor> descriptorExtractor = createDescriptorExtractor(descriptorExtractorName);
string modelIndexFilename = format("%s_segm/frame_index.yml", modelName);

View File

@ -143,7 +143,7 @@ int main(int argc, char** argv)
ransacReprojThreshold = atof(argv[5]);
cout << "< Creating detector, descriptor extractor and descriptor matcher ..." << endl;
Ptr<FeatureDetector> detector = createDetector( argv[1] );
Ptr<FeatureDetector> detector = createFeatureDetector( argv[1] );
Ptr<DescriptorExtractor> descriptorExtractor = createDescriptorExtractor( argv[2] );
Ptr<DescriptorMatcher> descriptorMatcher = createDescriptorMatcher( "BruteForce" );
cout << ">" << endl;

View File

@ -686,8 +686,8 @@ inline void readKeypoints( FileStorage& fs, vector<KeyPoint>& keypoints, int img
void DetectorQualityTest::readAlgorithm ()
{
defaultDetector = createDetector( algName );
specificDetector = createDetector( algName );
defaultDetector = createFeatureDetector( algName );
specificDetector = createFeatureDetector( algName );
if( defaultDetector == 0 )
{
ts->printf(CvTS::LOG, "Algorithm can not be read\n");

View File

@ -0,0 +1,334 @@
/*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 "cvtest.h"
#include "opencv2/core/core.hpp"
using namespace std;
using namespace cv;
const string FEATURES2D_DIR = "features2d";
const string DETECTOR_DIR = FEATURES2D_DIR + "/feature_detectors";
const string DESCRIPTOR_DIR = FEATURES2D_DIR + "/descriptor_extractors";
const string IMAGE_FILENAME = "tsukuba.png";
/****************************************************************************************\
* Regression tests for feature detectors comparing keypoints. *
\****************************************************************************************/
class CV_FeatureDetectorTest : public CvTest
{
public:
CV_FeatureDetectorTest( const char* testName, const Ptr<FeatureDetector>& _fdetector ) :
CvTest( testName, "cv::FeatureDetector::detect"), fdetector(_fdetector) {}
protected:
virtual void run( int start_from )
{
const float maxPtDif = 1.f;
const float maxSizeDif = 1.f;
const float maxAngleDif = 2.f;
const float maxResponseDif = 0.1f;
string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME;
string resFilename = string(ts->get_data_path()) + DETECTOR_DIR + "/" + string(name) + "_res.xml.gz";
if( fdetector.empty() )
{
ts->printf( CvTS::LOG, "Feature detector is empty" );
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
return;
}
Mat image = imread( imgFilename, 0 );
if( image.empty() )
{
ts->printf( CvTS::LOG, "image %s can not be read \n", imgFilename.c_str() );
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
return;
}
FileStorage fs( resFilename, FileStorage::READ );
vector<KeyPoint> calcKeypoints;
fdetector->detect( image, calcKeypoints );
if( fs.isOpened() ) // compare computed and valid keypoints
{
// TODO compare saved feature detector params with current ones
vector<KeyPoint> validKeypoints;
read( fs["keypoints"], validKeypoints );
if( validKeypoints.empty() )
{
ts->printf( CvTS::LOG, "Keypoints can nod be read\n" );
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
return;
}
int progress = 0, progressCount = validKeypoints.size() * calcKeypoints.size();
int badPointCount = 0, commonPointCount = max(validKeypoints.size(), calcKeypoints.size());
for( size_t v = 0; v < validKeypoints.size(); v++ )
{
int nearestIdx = -1;
float minDist = std::numeric_limits<float>::max();
for( size_t c = 0; c < calcKeypoints.size(); c++ )
{
progress = update_progress( progress, v*calcKeypoints.size() + c, progressCount, 0 );
float curDist = norm( calcKeypoints[c].pt - validKeypoints[v].pt );
if( curDist < minDist )
{
minDist = curDist;
nearestIdx = c;
}
}
if( minDist > maxPtDif ||
fabs(calcKeypoints[nearestIdx].size - validKeypoints[v].size) > maxSizeDif ||
abs(calcKeypoints[nearestIdx].angle - validKeypoints[v].angle) > maxAngleDif ||
abs(calcKeypoints[nearestIdx].response - validKeypoints[v].response) > maxResponseDif ||
calcKeypoints[nearestIdx].octave != validKeypoints[v].octave
// TODO !!!!!!!
/*||
calcKeypoints[nearestIdx].class_id != validKeypoints[v].class_id*/ )
{
badPointCount++;
}
}
ts->printf( CvTS::LOG, "badPointCount = %d; validPointCount = %d; calcPointCount = %d\n",
badPointCount, validKeypoints.size(), calcKeypoints.size() );
if( badPointCount > 0.9 * commonPointCount )
{
ts->printf( CvTS::LOG, "Bad accuracy!\n" );
ts->set_failed_test_info( CvTS::FAIL_BAD_ACCURACY );
return;
}
}
else // write
{
fs.open( resFilename, FileStorage::WRITE );
if( !fs.isOpened() )
{
ts->printf( CvTS::LOG, "file %s can not be opened to write\n", resFilename.c_str() );
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
return;
}
else
{
fs << "detector_params" << "{";
fdetector->write( fs );
fs << "}";
write( fs, "keypoints", calcKeypoints );
}
}
ts->set_failed_test_info( CvTS::OK );
}
Ptr<FeatureDetector> fdetector;
};
CV_FeatureDetectorTest fastTest( "detector_fast", createFeatureDetector("FAST") );
CV_FeatureDetectorTest gfttTest( "detector_gftt", createFeatureDetector("GFTT") );
CV_FeatureDetectorTest harrisTest( "detector_harris", createFeatureDetector("HARRIS") );
CV_FeatureDetectorTest mserTest( "detector_mser", createFeatureDetector("MSER") );
CV_FeatureDetectorTest siftTest( "detector_sift", createFeatureDetector("SIFT") );
CV_FeatureDetectorTest starTest( "detector_star", createFeatureDetector("STAR") );
CV_FeatureDetectorTest surfTest( "detector_surf", createFeatureDetector("SURF") );
/****************************************************************************************\
* Regression tests for descriptor extractors. *
\****************************************************************************************/
static void writeMatInBin( const Mat& mat, const string& filename )
{
FILE* f = fopen( filename.c_str(), "wb");
if( f )
{
int type = mat.type();
fwrite( (void*)&mat.rows, sizeof(int), 1, f );
fwrite( (void*)&mat.cols, sizeof(int), 1, f );
fwrite( (void*)&type, sizeof(int), 1, f );
fwrite( (void*)&mat.step, sizeof(int), 1, f );
fwrite( (void*)mat.data, 1, mat.step*mat.rows, f );
fclose(f);
}
}
static Mat readMatFromBin( const string& filename )
{
FILE* f = fopen( filename.c_str(), "rb" );
if( f )
{
int rows, cols, type, step;
fread( (void*)&rows, sizeof(int), 1, f );
fread( (void*)&cols, sizeof(int), 1, f );
fread( (void*)&type, sizeof(int), 1, f );
fread( (void*)&step, sizeof(int), 1, f );
uchar* data = (uchar*)cvAlloc(step*rows);
fread( (void*)data, 1, step*rows, f );
fclose(f);
return Mat( rows, cols, type, data );
}
return Mat();
}
class CV_DescriptorExtractorTest : public CvTest
{
public:
CV_DescriptorExtractorTest( const char* testName, float _normDif, const Ptr<DescriptorExtractor>& _dextractor, float _prevTime ) :
CvTest( testName, "cv::DescriptorExtractor::compute" ), normDif(_normDif), prevTime(_prevTime), dextractor(_dextractor) {}
protected:
virtual void createDescriptorExtractor() {}
void run(int)
{
createDescriptorExtractor();
if( dextractor.empty() )
{
ts->printf(CvTS::LOG, "Descriptor extractor is empty\n");
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
return;
}
string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME;
Mat img = imread( imgFilename, 0 );
if( img.empty() )
{
ts->printf( CvTS::LOG, "image %s can not be read\n", imgFilename.c_str() );
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
return;
}
vector<KeyPoint> keypoints;
FileStorage fs( string(ts->get_data_path()) + FEATURES2D_DIR + "/keypoints.xml.gz", FileStorage::READ );
if( fs.isOpened() )
read( fs.getFirstTopLevelNode(), keypoints );
else
{
ts->printf( CvTS::LOG, "Compute and write keypoints\n" );
fs.open( string(ts->get_data_path()) + FEATURES2D_DIR + "/keypoints.xml.gz", FileStorage::WRITE );
if( fs.isOpened() )
{
SurfFeatureDetector fd;
fd.detect(img, keypoints);
write( fs, "keypoints", keypoints );
}
else
{
ts->printf(CvTS::LOG, "File for writting keypoints can not be opened\n");
ts->set_failed_test_info( CvTS::FAIL_INVALID_TEST_DATA );
return;
}
}
Mat calcDescriptors;
double t = (double)getTickCount();
dextractor->compute( img, keypoints, calcDescriptors );
t = getTickCount() - t;
ts->printf(CvTS::LOG, "\nAverage time of computiting one descriptor = %g ms (previous time = %g ms)\n", t/((double)cvGetTickFrequency()*1000.)/calcDescriptors.rows, prevTime );
// TODO read and write descriptor extractor parameters and check them
Mat validDescriptors = readDescriptors();
if( !validDescriptors.empty() )
{
double normVal = norm( calcDescriptors, validDescriptors, NORM_INF );
ts->printf( CvTS::LOG, "nofm (inf) BTW valid and calculated float descriptors = %f\n", normVal );
if( normVal > normDif )
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()
{
Mat res = readMatFromBin( string(ts->get_data_path()) + DESCRIPTOR_DIR + "/" + string(name) );
return res;
}
virtual bool writeDescriptors( Mat& descs )
{
writeMatInBin( descs, string(ts->get_data_path()) + DESCRIPTOR_DIR + "/" + string(name) );
return true;
}
const float normDif;
const float prevTime;
Ptr<DescriptorExtractor> dextractor;
};
template<typename T>
class CV_CalonderDescriptorExtractorTest : public CV_DescriptorExtractorTest
{
public:
CV_CalonderDescriptorExtractorTest( const char* testName, float _normDif, float _prevTime ) :
CV_DescriptorExtractorTest( testName, _normDif, Ptr<DescriptorExtractor>(), _prevTime )
{}
virtual void createDescriptorExtractor()
{
dextractor = new CalonderDescriptorExtractor<T>( string(ts->get_data_path()) + FEATURES2D_DIR + "/calonder_classifier.rtc");
}
};
CV_DescriptorExtractorTest siftDescriptorTest( "descriptor_sift", std::numeric_limits<float>::epsilon(),
createDescriptorExtractor("SIFT"), 8.06652f );
CV_DescriptorExtractorTest surfDescriptorTest( "descriptor_surf", std::numeric_limits<float>::epsilon(),
createDescriptorExtractor("SURF"), 0.147372f );
#if CV_SSE2
CV_CalonderDescriptorExtractorTest<uchar> ucharCalonderTest( "descriptor_calonder_uchar",
std::numeric_limits<float>::epsilon() + 1,
0.0132175f );
CV_CalonderDescriptorExtractorTest<float> floatCalonderTest( "descriptor_calonder_float",
std::numeric_limits<float>::epsilon(),
0.0221308f );
#endif // CV_SSE2