Added L1 distance code and used factory functions in evaluation framework
This commit is contained in:
parent
4bcd81f85f
commit
add94f9bd6
@ -1507,6 +1507,27 @@ struct CV_EXPORTS L2
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Manhattan distance (city block distance) functor
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
struct CV_EXPORTS L1
|
||||||
|
{
|
||||||
|
typedef T ValueType;
|
||||||
|
typedef typename Accumulator<T>::Type ResultType;
|
||||||
|
|
||||||
|
ResultType operator()( const T* a, const T* b, int size ) const
|
||||||
|
{
|
||||||
|
ResultType result = ResultType();
|
||||||
|
for( int i = 0; i < size; i++ )
|
||||||
|
{
|
||||||
|
ResultType diff = a[i] - b[i];
|
||||||
|
result += fabs( diff );
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************************\
|
/****************************************************************************************\
|
||||||
* DMatch *
|
* DMatch *
|
||||||
@ -1755,6 +1776,7 @@ void BruteForceMatcher<Distance>::matchImpl( const Mat& descriptors_1, const Mat
|
|||||||
{
|
{
|
||||||
vector<DMatch> matchings;
|
vector<DMatch> matchings;
|
||||||
matchImpl( descriptors_1, descriptors_2, mask, matchings);
|
matchImpl( descriptors_1, descriptors_2, mask, matchings);
|
||||||
|
matches.clear();
|
||||||
matches.resize( matchings.size() );
|
matches.resize( matchings.size() );
|
||||||
for( size_t i=0;i<matchings.size();i++)
|
for( size_t i=0;i<matchings.size();i++)
|
||||||
{
|
{
|
||||||
@ -1776,6 +1798,7 @@ void BruteForceMatcher<Distance>::matchImpl( const Mat& descriptors_1, const Mat
|
|||||||
assert( DataType<ValueType>::type == descriptors_2.type() || descriptors_2.empty() );
|
assert( DataType<ValueType>::type == descriptors_2.type() || descriptors_2.empty() );
|
||||||
|
|
||||||
int dimension = descriptors_1.cols;
|
int dimension = descriptors_1.cols;
|
||||||
|
matches.clear();
|
||||||
matches.resize(descriptors_1.rows);
|
matches.resize(descriptors_1.rows);
|
||||||
|
|
||||||
for( int i = 0; i < descriptors_1.rows; i++ )
|
for( int i = 0; i < descriptors_1.rows; i++ )
|
||||||
@ -1823,6 +1846,7 @@ void BruteForceMatcher<Distance>::matchImpl( const Mat& descriptors_1, const Mat
|
|||||||
assert( DataType<ValueType>::type == descriptors_2.type() || descriptors_2.empty() );
|
assert( DataType<ValueType>::type == descriptors_2.type() || descriptors_2.empty() );
|
||||||
|
|
||||||
int dimension = descriptors_1.cols;
|
int dimension = descriptors_1.cols;
|
||||||
|
matches.clear();
|
||||||
matches.resize( descriptors_1.rows );
|
matches.resize( descriptors_1.rows );
|
||||||
|
|
||||||
for( int i = 0; i < descriptors_1.rows; i++ )
|
for( int i = 0; i < descriptors_1.rows; i++ )
|
||||||
@ -1931,8 +1955,6 @@ public:
|
|||||||
// Writes match object to a file storage
|
// Writes match object to a file storage
|
||||||
virtual void write( FileStorage& fs ) const {};
|
virtual void write( FileStorage& fs ) const {};
|
||||||
|
|
||||||
static GenericDescriptorMatch* CreateDescriptorMatch( const string &alg_name, const string ¶ms_filename = string () );
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
KeyPointCollection collection;
|
KeyPointCollection collection;
|
||||||
};
|
};
|
||||||
@ -1998,6 +2020,8 @@ public:
|
|||||||
|
|
||||||
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matches );
|
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matches );
|
||||||
|
|
||||||
|
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<vector<DMatch> >& matches, float threshold);
|
||||||
|
|
||||||
// Classify a set of keypoints. The same as match, but returns point classes rather than indices
|
// Classify a set of keypoints. The same as match, but returns point classes rather than indices
|
||||||
virtual void classify( const Mat& image, vector<KeyPoint>& points );
|
virtual void classify( const Mat& image, vector<KeyPoint>& points );
|
||||||
|
|
||||||
@ -2146,6 +2170,7 @@ protected:
|
|||||||
Params params;
|
Params params;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GenericDescriptorMatch* createDescriptorMatch( const string& genericDescritptorMatchType, const string ¶msFilename = string () );
|
||||||
/****************************************************************************************\
|
/****************************************************************************************\
|
||||||
* VectorDescriptorMatch *
|
* VectorDescriptorMatch *
|
||||||
\****************************************************************************************/
|
\****************************************************************************************/
|
||||||
@ -2159,7 +2184,7 @@ class CV_EXPORTS VectorDescriptorMatch : public GenericDescriptorMatch
|
|||||||
public:
|
public:
|
||||||
using GenericDescriptorMatch::add;
|
using GenericDescriptorMatch::add;
|
||||||
|
|
||||||
VectorDescriptorMatch( const Extractor& _extractor = Extractor(), const Matcher& _matcher = Matcher() ) :
|
VectorDescriptorMatch( Extractor *_extractor = 0, Matcher * _matcher = 0 ) :
|
||||||
extractor(_extractor), matcher(_matcher) {}
|
extractor(_extractor), matcher(_matcher) {}
|
||||||
|
|
||||||
~VectorDescriptorMatch() {}
|
~VectorDescriptorMatch() {}
|
||||||
@ -2171,8 +2196,8 @@ public:
|
|||||||
virtual void add( const Mat& image, vector<KeyPoint>& keypoints )
|
virtual void add( const Mat& image, vector<KeyPoint>& keypoints )
|
||||||
{
|
{
|
||||||
Mat descriptors;
|
Mat descriptors;
|
||||||
extractor.compute( image, keypoints, descriptors );
|
extractor->compute( image, keypoints, descriptors );
|
||||||
matcher.add( descriptors );
|
matcher->add( descriptors );
|
||||||
|
|
||||||
collection.add( Mat(), keypoints );
|
collection.add( Mat(), keypoints );
|
||||||
};
|
};
|
||||||
@ -2181,47 +2206,47 @@ public:
|
|||||||
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<int>& keypointIndices )
|
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<int>& keypointIndices )
|
||||||
{
|
{
|
||||||
Mat descriptors;
|
Mat descriptors;
|
||||||
extractor.compute( image, points, descriptors );
|
extractor->compute( image, points, descriptors );
|
||||||
|
|
||||||
matcher.match( descriptors, keypointIndices );
|
matcher->match( descriptors, keypointIndices );
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matches )
|
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matches )
|
||||||
{
|
{
|
||||||
Mat descriptors;
|
Mat descriptors;
|
||||||
extractor.compute( image, points, descriptors );
|
extractor->compute( image, points, descriptors );
|
||||||
|
|
||||||
matcher.match( descriptors, matches );
|
matcher->match( descriptors, matches );
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<vector<DMatch> >& matches, float threshold )
|
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<vector<DMatch> >& matches, float threshold )
|
||||||
{
|
{
|
||||||
Mat descriptors;
|
Mat descriptors;
|
||||||
extractor.compute( image, points, descriptors );
|
extractor->compute( image, points, descriptors );
|
||||||
|
|
||||||
matcher.match( descriptors, matches, threshold );
|
matcher->match( descriptors, matches, threshold );
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void clear()
|
virtual void clear()
|
||||||
{
|
{
|
||||||
GenericDescriptorMatch::clear();
|
GenericDescriptorMatch::clear();
|
||||||
matcher.clear();
|
matcher->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void read (const FileNode& fn)
|
virtual void read (const FileNode& fn)
|
||||||
{
|
{
|
||||||
GenericDescriptorMatch::read(fn);
|
GenericDescriptorMatch::read(fn);
|
||||||
extractor.read (fn);
|
extractor->read (fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void write (FileStorage& fs) const
|
virtual void write (FileStorage& fs) const
|
||||||
{
|
{
|
||||||
GenericDescriptorMatch::write(fs);
|
GenericDescriptorMatch::write(fs);
|
||||||
extractor.write (fs);
|
extractor->write (fs);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
Extractor extractor;
|
Ptr<Extractor> extractor;
|
||||||
Matcher matcher;
|
Ptr<Matcher> matcher;
|
||||||
//vector<int> classIds;
|
//vector<int> classIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
//M*/
|
//M*/
|
||||||
|
|
||||||
#include "precomp.hpp"
|
#include "precomp.hpp"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
//#define _KDTREE
|
//#define _KDTREE
|
||||||
|
|
||||||
@ -254,6 +255,10 @@ DescriptorMatcher* createDescriptorMatcher( const string& descriptorMatcherType
|
|||||||
{
|
{
|
||||||
dm = new BruteForceMatcher<L2<float> >();
|
dm = new BruteForceMatcher<L2<float> >();
|
||||||
}
|
}
|
||||||
|
else if ( !descriptorMatcherType.compare( "BruteForce-L1" ) )
|
||||||
|
{
|
||||||
|
dm = new BruteForceMatcher<L1<float> >();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//CV_Error( CV_StsBadArg, "unsupported descriptor matcher type");
|
//CV_Error( CV_StsBadArg, "unsupported descriptor matcher type");
|
||||||
@ -330,27 +335,27 @@ void GenericDescriptorMatch::clear()
|
|||||||
collection.clear();
|
collection.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericDescriptorMatch* GenericDescriptorMatch::CreateDescriptorMatch( const string &alg_name, const string ¶ms_filename )
|
GenericDescriptorMatch* createDescriptorMatch( const string& genericDescritptorMatchType, const string ¶msFilename )
|
||||||
{
|
{
|
||||||
GenericDescriptorMatch *descriptorMatch = 0;
|
GenericDescriptorMatch *descriptorMatch = 0;
|
||||||
if( ! alg_name.compare ("one_way") )
|
if( ! genericDescritptorMatchType.compare ("ONEWAY") )
|
||||||
{
|
{
|
||||||
descriptorMatch = new OneWayDescriptorMatch ();
|
descriptorMatch = new OneWayDescriptorMatch ();
|
||||||
}
|
}
|
||||||
else if( ! alg_name.compare ("fern") )
|
else if( ! genericDescritptorMatchType.compare ("FERN") )
|
||||||
{
|
{
|
||||||
FernDescriptorMatch::Params params;
|
FernDescriptorMatch::Params params;
|
||||||
params.signatureSize = INT_MAX;
|
params.signatureSize = numeric_limits<int>::max();
|
||||||
descriptorMatch = new FernDescriptorMatch (params);
|
descriptorMatch = new FernDescriptorMatch (params);
|
||||||
}
|
}
|
||||||
else if( ! alg_name.compare ("calonder") )
|
else if( ! genericDescritptorMatchType.compare ("CALONDER") )
|
||||||
{
|
{
|
||||||
descriptorMatch = new CalonderDescriptorMatch ();
|
descriptorMatch = new CalonderDescriptorMatch ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !params_filename.empty() && descriptorMatch != 0 )
|
if( !paramsFilename.empty() && descriptorMatch != 0 )
|
||||||
{
|
{
|
||||||
FileStorage fs = FileStorage( params_filename, FileStorage::READ );
|
FileStorage fs = FileStorage( paramsFilename, FileStorage::READ );
|
||||||
if( fs.isOpened() )
|
if( fs.isOpened() )
|
||||||
{
|
{
|
||||||
descriptorMatch->read( fs.root() );
|
descriptorMatch->read( fs.root() );
|
||||||
@ -460,6 +465,76 @@ void OneWayDescriptorMatch::match( const Mat& image, vector<KeyPoint>& points, v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OneWayDescriptorMatch::match( const Mat& image, vector<KeyPoint>& points, vector<vector<DMatch> >& matches, float threshold )
|
||||||
|
{
|
||||||
|
matches.clear();
|
||||||
|
matches.resize( points.size() );
|
||||||
|
IplImage _image = image;
|
||||||
|
|
||||||
|
|
||||||
|
vector<DMatch> dmatches;
|
||||||
|
match( image, points, dmatches );
|
||||||
|
for( size_t i=0;i<matches.size();i++ )
|
||||||
|
{
|
||||||
|
matches[i].push_back( dmatches[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
printf("Start matching %d points\n", points.size());
|
||||||
|
//std::cout << "Start matching " << points.size() << "points\n";
|
||||||
|
assert(collection.images.size() == 1);
|
||||||
|
int n = collection.points[0].size();
|
||||||
|
|
||||||
|
printf("n = %d\n", n);
|
||||||
|
for( size_t i = 0; i < points.size(); i++ )
|
||||||
|
{
|
||||||
|
//printf("Matching %d\n", i);
|
||||||
|
//int poseIdx = -1;
|
||||||
|
|
||||||
|
DMatch match;
|
||||||
|
match.indexQuery = i;
|
||||||
|
match.indexTrain = -1;
|
||||||
|
|
||||||
|
|
||||||
|
CvPoint pt = points[i].pt;
|
||||||
|
CvRect roi = cvRect(cvRound(pt.x - 24/4),
|
||||||
|
cvRound(pt.y - 24/4),
|
||||||
|
24/2, 24/2);
|
||||||
|
cvSetImageROI(&_image, roi);
|
||||||
|
|
||||||
|
std::vector<int> desc_idxs;
|
||||||
|
std::vector<int> pose_idxs;
|
||||||
|
std::vector<float> distances;
|
||||||
|
std::vector<float> _scales;
|
||||||
|
|
||||||
|
|
||||||
|
base->FindDescriptor(&_image, n, desc_idxs, pose_idxs, distances, _scales);
|
||||||
|
cvResetImageROI(&_image);
|
||||||
|
|
||||||
|
for( int j=0;j<n;j++ )
|
||||||
|
{
|
||||||
|
match.indexTrain = desc_idxs[j];
|
||||||
|
match.distance = distances[j];
|
||||||
|
matches[i].push_back( match );
|
||||||
|
}
|
||||||
|
|
||||||
|
//sort( matches[i].begin(), matches[i].end(), compareIndexTrain );
|
||||||
|
//for( int j=0;j<n;j++ )
|
||||||
|
//{
|
||||||
|
//printf( "%d %f; ",matches[i][j].indexTrain, matches[i][j].distance);
|
||||||
|
//}
|
||||||
|
//printf("\n\n\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//base->FindDescriptor( &_image, 100, points[i].pt, match.indexTrain, poseIdx, match.distance );
|
||||||
|
//matches[i].push_back( match );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void OneWayDescriptorMatch::read( const FileNode &fn )
|
void OneWayDescriptorMatch::read( const FileNode &fn )
|
||||||
{
|
{
|
||||||
base = new OneWayDescriptorObject( params.patchSize, params.poseCount, string (), string (), string (),
|
base = new OneWayDescriptorObject( params.patchSize, params.poseCount, string (), string (), string (),
|
||||||
|
@ -344,6 +344,11 @@ FeatureDetector* createDetector( const string& detectorType )
|
|||||||
5/*edge_blur_size*/ );
|
5/*edge_blur_size*/ );
|
||||||
}
|
}
|
||||||
else if( !detectorType.compare( "GFTT" ) )
|
else if( !detectorType.compare( "GFTT" ) )
|
||||||
|
{
|
||||||
|
fd = new GoodFeaturesToTrackDetector( 1000/*maxCorners*/, 0.01/*qualityLevel*/, 1./*minDistance*/,
|
||||||
|
3/*int _blockSize*/, false/*useHarrisDetector*/, 0.04/*k*/ );
|
||||||
|
}
|
||||||
|
else if( !detectorType.compare( "HARRIS" ) )
|
||||||
{
|
{
|
||||||
fd = new GoodFeaturesToTrackDetector( 1000/*maxCorners*/, 0.01/*qualityLevel*/, 1./*minDistance*/,
|
fd = new GoodFeaturesToTrackDetector( 1000/*maxCorners*/, 0.01/*qualityLevel*/, 1./*minDistance*/,
|
||||||
3/*int _blockSize*/, true/*useHarrisDetector*/, 0.04/*k*/ );
|
3/*int _blockSize*/, true/*useHarrisDetector*/, 0.04/*k*/ );
|
||||||
|
@ -1042,58 +1042,14 @@ inline void readKeypoints( FileStorage& fs, vector<KeyPoint>& keypoints, int img
|
|||||||
|
|
||||||
void DetectorQualityTest::readAlgorithm ()
|
void DetectorQualityTest::readAlgorithm ()
|
||||||
{
|
{
|
||||||
//TODO: use Factory Register when it will be implemented
|
defaultDetector = createDetector( algName );
|
||||||
if (! algName.compare ("fast"))
|
specificDetector = createDetector( algName );
|
||||||
{
|
if( defaultDetector == 0 )
|
||||||
defaultDetector = new FastFeatureDetector(50, true);
|
|
||||||
specificDetector = new FastFeatureDetector();
|
|
||||||
}
|
|
||||||
else if (! algName.compare ("mser"))
|
|
||||||
{
|
|
||||||
defaultDetector = new MserFeatureDetector();
|
|
||||||
specificDetector = new MserFeatureDetector();
|
|
||||||
}
|
|
||||||
else if (! algName.compare ("star"))
|
|
||||||
{
|
|
||||||
defaultDetector = new StarFeatureDetector();
|
|
||||||
specificDetector = new StarFeatureDetector();
|
|
||||||
}
|
|
||||||
else if (! algName.compare ("sift"))
|
|
||||||
{
|
|
||||||
defaultDetector = new SiftFeatureDetector(SIFT::DetectorParams::GET_DEFAULT_THRESHOLD(), 3);
|
|
||||||
specificDetector = new SiftFeatureDetector();
|
|
||||||
}
|
|
||||||
else if (! algName.compare ("surf"))
|
|
||||||
{
|
|
||||||
defaultDetector = new SurfFeatureDetector(1500);
|
|
||||||
specificDetector = new SurfFeatureDetector();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int maxCorners = 1500;
|
|
||||||
double qualityLevel = 0.01;
|
|
||||||
double minDistance = 2.0;
|
|
||||||
int blockSize=3;
|
|
||||||
|
|
||||||
if (! algName.compare ("gftt"))
|
|
||||||
{
|
|
||||||
bool useHarrisDetector = false;
|
|
||||||
defaultDetector = new GoodFeaturesToTrackDetector (maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector);
|
|
||||||
specificDetector = new GoodFeaturesToTrackDetector (maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector);
|
|
||||||
}
|
|
||||||
else if (! algName.compare ("harris"))
|
|
||||||
{
|
|
||||||
bool useHarrisDetector = true;
|
|
||||||
defaultDetector = new GoodFeaturesToTrackDetector (maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector);
|
|
||||||
specificDetector = new GoodFeaturesToTrackDetector (maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
ts->printf(CvTS::LOG, "Algorithm can not be read\n");
|
ts->printf(CvTS::LOG, "Algorithm can not be read\n");
|
||||||
ts->set_failed_test_info( CvTS::FAIL_GENERIC);
|
ts->set_failed_test_info( CvTS::FAIL_GENERIC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void DetectorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vector<Mat> &Hs, int di, int &progress)
|
void DetectorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vector<Mat> &Hs, int di, int &progress)
|
||||||
{
|
{
|
||||||
@ -1152,13 +1108,13 @@ int DetectorQualityTest::processResults( int datasetIdx, int caseIdx )
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
DetectorQualityTest fastDetectorQuality = DetectorQualityTest( "fast", "quality-detector-fast" );
|
//DetectorQualityTest fastDetectorQuality = DetectorQualityTest( "FAST", "quality-detector-fast" );
|
||||||
DetectorQualityTest gfttDetectorQuality = DetectorQualityTest( "gftt", "quality-detector-gftt" );
|
//DetectorQualityTest gfttDetectorQuality = DetectorQualityTest( "GFTT", "quality-detector-gftt" );
|
||||||
DetectorQualityTest harrisDetectorQuality = DetectorQualityTest( "harris", "quality-detector-harris" );
|
//DetectorQualityTest harrisDetectorQuality = DetectorQualityTest( "HARRIS", "quality-detector-harris" );
|
||||||
DetectorQualityTest mserDetectorQuality = DetectorQualityTest( "mser", "quality-detector-mser" );
|
//DetectorQualityTest mserDetectorQuality = DetectorQualityTest( "MSER", "quality-detector-mser" );
|
||||||
DetectorQualityTest starDetectorQuality = DetectorQualityTest( "star", "quality-detector-star" );
|
//DetectorQualityTest starDetectorQuality = DetectorQualityTest( "STAR", "quality-detector-star" );
|
||||||
DetectorQualityTest siftDetectorQuality = DetectorQualityTest( "sift", "quality-detector-sift" );
|
//DetectorQualityTest siftDetectorQuality = DetectorQualityTest( "SIFT", "quality-detector-sift" );
|
||||||
DetectorQualityTest surfDetectorQuality = DetectorQualityTest( "surf", "quality-detector-surf" );
|
//DetectorQualityTest surfDetectorQuality = DetectorQualityTest( "SURF", "quality-detector-surf" );
|
||||||
|
|
||||||
/****************************************************************************************\
|
/****************************************************************************************\
|
||||||
* Descriptors evaluation *
|
* Descriptors evaluation *
|
||||||
@ -1179,7 +1135,7 @@ class DescriptorQualityTest : public BaseQualityTest
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum{ NO_MATCH_FILTER = 0 };
|
enum{ NO_MATCH_FILTER = 0 };
|
||||||
DescriptorQualityTest( const char* _descriptorName, const char* _testName ) :
|
DescriptorQualityTest( const char* _descriptorName, const char* _testName, const char* _matcherName = 0 ) :
|
||||||
BaseQualityTest( _descriptorName, _testName, "quality-of-descriptor" )
|
BaseQualityTest( _descriptorName, _testName, "quality-of-descriptor" )
|
||||||
{
|
{
|
||||||
validQuality.resize(DATASETS_COUNT);
|
validQuality.resize(DATASETS_COUNT);
|
||||||
@ -1190,6 +1146,9 @@ public:
|
|||||||
commRunParamsDefault.projectKeypointsFrom1Image = true;
|
commRunParamsDefault.projectKeypointsFrom1Image = true;
|
||||||
commRunParamsDefault.matchFilter = NO_MATCH_FILTER;
|
commRunParamsDefault.matchFilter = NO_MATCH_FILTER;
|
||||||
commRunParamsDefault.isActiveParams = false;
|
commRunParamsDefault.isActiveParams = false;
|
||||||
|
|
||||||
|
if( _matcherName )
|
||||||
|
matcherName = _matcherName;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -1223,6 +1182,7 @@ protected:
|
|||||||
virtual int processResults( int datasetIdx, int caseIdx );
|
virtual int processResults( int datasetIdx, int caseIdx );
|
||||||
|
|
||||||
virtual void writePlotData( int di ) const;
|
virtual void writePlotData( int di ) const;
|
||||||
|
void calculatePlotData( vector<DMatchForEvaluation> &allMatches, int allCorrespCount, int di );
|
||||||
|
|
||||||
struct Quality
|
struct Quality
|
||||||
{
|
{
|
||||||
@ -1246,6 +1206,7 @@ protected:
|
|||||||
Ptr<GenericDescriptorMatch> defaultDescMatch;
|
Ptr<GenericDescriptorMatch> defaultDescMatch;
|
||||||
|
|
||||||
CommonRunParams commRunParamsDefault;
|
CommonRunParams commRunParamsDefault;
|
||||||
|
string matcherName;
|
||||||
};
|
};
|
||||||
|
|
||||||
string DescriptorQualityTest::getRunParamsFilename() const
|
string DescriptorQualityTest::getRunParamsFilename() const
|
||||||
@ -1364,53 +1325,70 @@ void DescriptorQualityTest::writePlotData( int di ) const
|
|||||||
|
|
||||||
void DescriptorQualityTest::readAlgorithm( )
|
void DescriptorQualityTest::readAlgorithm( )
|
||||||
{
|
{
|
||||||
//TODO: use Factory Register when it will be implemented
|
defaultDescMatch = createDescriptorMatch( algName );
|
||||||
if (! algName.compare ("sift"))
|
specificDescMatch = createDescriptorMatch( algName );
|
||||||
{
|
|
||||||
SiftDescriptorExtractor extractor;
|
|
||||||
BruteForceMatcher<L2<float> > matcher;
|
|
||||||
defaultDescMatch = new VectorDescriptorMatch<SiftDescriptorExtractor, BruteForceMatcher<L2<float> > >(extractor, matcher);
|
|
||||||
specificDescMatch = new VectorDescriptorMatch<SiftDescriptorExtractor, BruteForceMatcher<L2<float> > >(extractor, matcher);
|
|
||||||
}
|
|
||||||
else if (! algName.compare ("surf"))
|
|
||||||
{
|
|
||||||
SurfDescriptorExtractor extractor;
|
|
||||||
BruteForceMatcher<L2<float> > matcher;
|
|
||||||
defaultDescMatch = new VectorDescriptorMatch<SurfDescriptorExtractor, BruteForceMatcher<L2<float> > >(extractor, matcher);
|
|
||||||
specificDescMatch = new VectorDescriptorMatch<SurfDescriptorExtractor, BruteForceMatcher<L2<float> > >(extractor, matcher);
|
|
||||||
}
|
|
||||||
else if (! algName.compare ("one_way"))
|
|
||||||
{
|
|
||||||
defaultDescMatch = new OneWayDescriptorMatch ();
|
|
||||||
specificDescMatch = new OneWayDescriptorMatch ();
|
|
||||||
}
|
|
||||||
else if (! algName.compare ("fern"))
|
|
||||||
{
|
|
||||||
FernDescriptorMatch::Params params;
|
|
||||||
params.nviews = 100;
|
|
||||||
params.signatureSize = INT_MAX;
|
|
||||||
params.nstructs = 50;
|
|
||||||
defaultDescMatch = new FernDescriptorMatch (params);
|
|
||||||
specificDescMatch = new FernDescriptorMatch ();
|
|
||||||
}
|
|
||||||
else if (! algName.compare ("calonder"))
|
|
||||||
{
|
|
||||||
CalonderDescriptorMatch::Params params;
|
|
||||||
params.numTrees = 20;
|
|
||||||
params.depth = 7;
|
|
||||||
params.views = 100;
|
|
||||||
params.reducedNumDim = 100;
|
|
||||||
params.patchSize = 20;
|
|
||||||
|
|
||||||
defaultDescMatch = new CalonderDescriptorMatch (params);
|
if( defaultDescMatch == 0 )
|
||||||
specificDescMatch = new CalonderDescriptorMatch ();
|
{
|
||||||
}
|
DescriptorExtractor *extractor = createDescriptorExtractor( algName );
|
||||||
else
|
DescriptorMatcher *matcher = createDescriptorMatcher( matcherName );
|
||||||
|
defaultDescMatch = new VectorDescriptorMatch<DescriptorExtractor, DescriptorMatcher >( extractor, matcher );
|
||||||
|
specificDescMatch = new VectorDescriptorMatch<DescriptorExtractor, DescriptorMatcher >( extractor, matcher );
|
||||||
|
|
||||||
|
if( extractor == 0 || matcher == 0 )
|
||||||
{
|
{
|
||||||
ts->printf(CvTS::LOG, "Algorithm can not be read\n");
|
ts->printf(CvTS::LOG, "Algorithm can not be read\n");
|
||||||
ts->set_failed_test_info( CvTS::FAIL_GENERIC);
|
ts->set_failed_test_info( CvTS::FAIL_GENERIC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptorQualityTest::calculatePlotData( vector<DMatchForEvaluation> &allMatches, int allCorrespCount, int di )
|
||||||
|
{
|
||||||
|
std::sort( allMatches.begin(), allMatches.end() );
|
||||||
|
|
||||||
|
//calcDatasetQuality[di].resize( allMatches.size() );
|
||||||
|
calcDatasetQuality[di].clear();
|
||||||
|
int correctMatchCount = 0, falseMatchCount = 0;
|
||||||
|
const float sparsePlotBound = 0.1;
|
||||||
|
const int npoints = 10000;
|
||||||
|
int step = 1 + allMatches.size() / npoints;
|
||||||
|
const float resultPrecision = 0.5;
|
||||||
|
bool isResultCalculated = false;
|
||||||
|
for( size_t i=0;i<allMatches.size();i++)
|
||||||
|
{
|
||||||
|
if( allMatches[i].isCorrect )
|
||||||
|
correctMatchCount++;
|
||||||
|
else
|
||||||
|
falseMatchCount++;
|
||||||
|
|
||||||
|
if( precision( correctMatchCount, falseMatchCount ) >= sparsePlotBound || (i % step == 0) )
|
||||||
|
{
|
||||||
|
Quality quality;
|
||||||
|
quality.recall = recall( correctMatchCount, allCorrespCount );
|
||||||
|
quality.precision = precision( correctMatchCount, falseMatchCount );
|
||||||
|
|
||||||
|
calcDatasetQuality[di].push_back( quality );
|
||||||
|
|
||||||
|
if( !isResultCalculated && quality.precision < resultPrecision)
|
||||||
|
{
|
||||||
|
for(int ci=0;ci<TEST_CASE_COUNT;ci++)
|
||||||
|
{
|
||||||
|
calcQuality[di][ci].recall = quality.recall;
|
||||||
|
calcQuality[di][ci].precision = quality.precision;
|
||||||
|
}
|
||||||
|
isResultCalculated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Quality quality;
|
||||||
|
quality.recall = recall( correctMatchCount, allCorrespCount );
|
||||||
|
quality.precision = precision( correctMatchCount, falseMatchCount );
|
||||||
|
|
||||||
|
calcDatasetQuality[di].push_back( quality );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void DescriptorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vector<Mat> &Hs, int di, int &progress)
|
void DescriptorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vector<Mat> &Hs, int di, int &progress)
|
||||||
{
|
{
|
||||||
@ -1465,48 +1443,7 @@ void DescriptorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vecto
|
|||||||
descMatch->clear ();
|
descMatch->clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort( allMatches.begin(), allMatches.end() );
|
calculatePlotData( allMatches, allCorrespCount, di );
|
||||||
|
|
||||||
//calcDatasetQuality[di].resize( allMatches.size() );
|
|
||||||
calcDatasetQuality[di].clear();
|
|
||||||
int correctMatchCount = 0, falseMatchCount = 0;
|
|
||||||
const float sparsePlotBound = 0.1;
|
|
||||||
const int npoints = 10000;
|
|
||||||
int step = allMatches.size() / npoints;
|
|
||||||
const float resultPrecision = 0.5;
|
|
||||||
bool isResultCalculated = false;
|
|
||||||
for( size_t i=0;i<allMatches.size();i++)
|
|
||||||
{
|
|
||||||
if( allMatches[i].isCorrect )
|
|
||||||
correctMatchCount++;
|
|
||||||
else
|
|
||||||
falseMatchCount++;
|
|
||||||
|
|
||||||
if( precision( correctMatchCount, falseMatchCount ) >= sparsePlotBound || (i % step == 0) )
|
|
||||||
{
|
|
||||||
Quality quality;
|
|
||||||
quality.recall = recall( correctMatchCount, allCorrespCount );
|
|
||||||
quality.precision = precision( correctMatchCount, falseMatchCount );
|
|
||||||
|
|
||||||
calcDatasetQuality[di].push_back( quality );
|
|
||||||
|
|
||||||
if( !isResultCalculated && quality.precision < resultPrecision)
|
|
||||||
{
|
|
||||||
for(int ci=0;ci<TEST_CASE_COUNT;ci++)
|
|
||||||
{
|
|
||||||
calcQuality[di][ci].recall = quality.recall;
|
|
||||||
calcQuality[di][ci].precision = quality.precision;
|
|
||||||
}
|
|
||||||
isResultCalculated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Quality quality;
|
|
||||||
quality.recall = recall( correctMatchCount, allCorrespCount );
|
|
||||||
quality.precision = precision( correctMatchCount, falseMatchCount );
|
|
||||||
|
|
||||||
calcDatasetQuality[di].push_back( quality );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int DescriptorQualityTest::processResults( int datasetIdx, int caseIdx )
|
int DescriptorQualityTest::processResults( int datasetIdx, int caseIdx )
|
||||||
@ -1529,15 +1466,17 @@ int DescriptorQualityTest::processResults( int datasetIdx, int caseIdx )
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
DescriptorQualityTest siftDescriptorQuality = DescriptorQualityTest( "sift", "quality-descriptor-sift" );
|
//DescriptorQualityTest siftDescriptorQuality = DescriptorQualityTest( "SIFT", "quality-descriptor-sift", "BruteForce" );
|
||||||
DescriptorQualityTest surfDescriptorQuality = DescriptorQualityTest( "surf", "quality-descriptor-surf" );
|
//DescriptorQualityTest surfDescriptorQuality = DescriptorQualityTest( "SURF", "quality-descriptor-surf", "BruteForce" );
|
||||||
|
//DescriptorQualityTest siftL1DescriptorQuality = DescriptorQualityTest( "SIFT", "quality-descriptor-sift-L1", "BruteForce-L1" );
|
||||||
|
//DescriptorQualityTest surfL1DescriptorQuality = DescriptorQualityTest( "SURF", "quality-descriptor-surf-L1", "BruteForce-L1" );
|
||||||
|
|
||||||
//--------------------------------- One Way descriptor test --------------------------------------------
|
//--------------------------------- One Way descriptor test --------------------------------------------
|
||||||
class OneWayDescriptorQualityTest : public DescriptorQualityTest
|
class OneWayDescriptorQualityTest : public DescriptorQualityTest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OneWayDescriptorQualityTest() :
|
OneWayDescriptorQualityTest() :
|
||||||
DescriptorQualityTest("one_way", "quality-descriptor-one-way")
|
DescriptorQualityTest("ONEWAY", "quality-descriptor-one-way")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
@ -1587,7 +1526,6 @@ void OneWayDescriptorQualityTest::writeDatasetRunParams( FileStorage& fs, int da
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
OneWayDescriptorQualityTest oneWayDescriptorQuality;
|
//OneWayDescriptorQualityTest oneWayDescriptorQuality;
|
||||||
|
//DescriptorQualityTest fernDescriptorQualityTest( "FERN", "quality-descriptor-fern");
|
||||||
DescriptorQualityTest fernDescriptorQualityTest( "fern", "quality-descriptor-fern");
|
//DescriptorQualityTest calonderDescriptorQualityTest( "CALONDER", "quality-descriptor-calonder");
|
||||||
DescriptorQualityTest calonderDescriptorQualityTest( "calonder", "quality-descriptor-calonder");
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user