Commit 89935fc5 authored by Maria Dimashova's avatar Maria Dimashova

fixed FernDescriptorMatch; optimized keypoint regions matching in…

fixed FernDescriptorMatch; optimized keypoint regions matching in detector/descriptor evaluation; added CalonderDescriptorExtractor to evaluation tests
parent 51822f20
...@@ -2128,7 +2128,8 @@ protected: ...@@ -2128,7 +2128,8 @@ protected:
Params params; Params params;
}; };
CV_EXPORTS Ptr<GenericDescriptorMatch> createGenericDescriptorMatch( const string& genericDescritptorMatchType, const string &paramsFilename = string () ); CV_EXPORTS Ptr<GenericDescriptorMatch> createGenericDescriptorMatcher( const string& genericDescritptorMatcherType,
const string &paramsFilename = string () );
/****************************************************************************************\ /****************************************************************************************\
* VectorDescriptorMatch * * VectorDescriptorMatch *
......
...@@ -204,15 +204,75 @@ static void filterEllipticKeyPointsByImageSize( vector<EllipticKeyPoint>& keypoi ...@@ -204,15 +204,75 @@ static void filterEllipticKeyPointsByImageSize( vector<EllipticKeyPoint>& keypoi
} }
} }
static void overlap( const vector<EllipticKeyPoint>& keypoints1, const vector<EllipticKeyPoint>& keypoints2t, bool commonPart, struct IntersectAreaCounter
SparseMat_<float>& overlaps )
{ {
IntersectAreaCounter() : bua(0.f), bna(0.f) {}
IntersectAreaCounter( float _miny, float _maxy, float _dr, const Point2f& _diff,
const Scalar& _ellipse1, const Scalar& _ellipse2 ) : bua(0.f), bna(0.f),
miny(_miny), maxy(_maxy), dr(_dr), diff(_diff),
ellipse1(_ellipse1), ellipse2(_ellipse2) {}
void operator()( const BlockedRange& range )
{
float temp_bua = bua, temp_bna = bna;
for( float rx1 = range.begin(); rx1 <= range.end(); rx1 += dr )
{
float rx2 = rx1 - diff.x;
for( float ry1 = miny; ry1 <= maxy; ry1 += dr )
{
float ry2 = ry1 - diff.y;
//compute the distance from the ellipse center
float e1 = (float)(ellipse1[0]*rx1*rx1 + 2*ellipse1[1]*rx1*ry1 + ellipse1[2]*ry1*ry1);
float e2 = (float)(ellipse2[0]*rx2*rx2 + 2*ellipse2[1]*rx2*ry2 + ellipse2[2]*ry2*ry2);
//compute the area
if( e1<1 && e2<1 ) temp_bna++;
if( e1<1 || e2<1 ) temp_bua++;
}
}
bua = temp_bua;
bna = temp_bna;
}
void join( IntersectAreaCounter& ac )
{
bua += ac.bua;
bna += ac.bna;
}
float bua, bna;
float miny, maxy, dr;
Point2f diff;
Scalar ellipse1, ellipse2;
};
struct SIdx
{
SIdx() : S(-1), i1(-1), i2(-1) {}
SIdx(float _S, int _i1, int _i2) : S(_S), i1(_i1), i2(_i2) {}
float S;
int i1;
int i2;
bool operator<(const SIdx& v) const { return S > v.S; }
struct UsedFinder
{
UsedFinder(const SIdx& _used) : used(_used) {}
const SIdx& used;
bool operator()(const SIdx& v) const { return (v.i1 == used.i1 || v.i2 == used.i2); }
};
};
static void computeOneToOneMatchedOverlaps( const vector<EllipticKeyPoint>& keypoints1, const vector<EllipticKeyPoint>& keypoints2t,
bool commonPart, vector<SIdx>& overlaps, float minOverlap )
{
CV_Assert( minOverlap >= 0.f );
overlaps.clear(); overlaps.clear();
if( keypoints1.empty() || keypoints2t.empty() ) if( keypoints1.empty() || keypoints2t.empty() )
return; return;
int size[] = { keypoints1.size(), keypoints2t.size() }; overlaps.clear();
overlaps.create( 2, size ); overlaps.reserve(cvRound(keypoints1.size() * keypoints2t.size() * 0.01));
for( size_t i1 = 0; i1 < keypoints1.size(); i1++ ) for( size_t i1 = 0; i1 < keypoints1.size(); i1++ )
{ {
...@@ -246,34 +306,40 @@ static void overlap( const vector<EllipticKeyPoint>& keypoints1, const vector<El ...@@ -246,34 +306,40 @@ static void overlap( const vector<EllipticKeyPoint>& keypoints1, const vector<El
float miny = floor((-keypoint1a.boundingBox.height < (diff.y-keypoint2a.boundingBox.height)) ? float miny = floor((-keypoint1a.boundingBox.height < (diff.y-keypoint2a.boundingBox.height)) ?
-keypoint1a.boundingBox.height : (diff.y-keypoint2a.boundingBox.height)); -keypoint1a.boundingBox.height : (diff.y-keypoint2a.boundingBox.height));
float mina = (maxx-minx) < (maxy-miny) ? (maxx-minx) : (maxy-miny) ; float mina = (maxx-minx) < (maxy-miny) ? (maxx-minx) : (maxy-miny) ;
float dr = mina/50.f;
float bua = 0.f, bna = 0.f;
//compute the area //compute the area
for( float rx1 = minx; rx1 <= maxx; rx1+=dr ) float dr = mina/50.f;
IntersectAreaCounter ac( miny, maxy, dr, diff, keypoint1a.ellipse, keypoint2a.ellipse );
parallel_reduce( BlockedRange(minx, maxx), ac );
if( ac.bna > 0 )
{ {
float rx2 = rx1-diff.x; float ov = ac.bna / ac.bua;
for( float ry1=miny; ry1<=maxy; ry1+=dr ) if( ov >= minOverlap )
{ overlaps.push_back(SIdx(ov, i1, i2));
float ry2=ry1-diff.y;
//compute the distance from the ellipse center
float e1 = (float)(keypoint1a.ellipse[0]*rx1*rx1+2*keypoint1a.ellipse[1]*rx1*ry1+keypoint1a.ellipse[2]*ry1*ry1);
float e2 = (float)(keypoint2a.ellipse[0]*rx2*rx2+2*keypoint2a.ellipse[1]*rx2*ry2+keypoint2a.ellipse[2]*ry2*ry2);
//compute the area
if( e1<1 && e2<1 ) bna++;
if( e1<1 || e2<1 ) bua++;
}
} }
if( bna > 0)
overlaps.ref(i1,i2) = bna/bua;
} }
} }
} }
sort( overlaps.begin(), overlaps.end() );
typedef vector<SIdx>::iterator It;
It pos = overlaps.begin();
It end = overlaps.end();
while(pos != end)
{
It prev = pos++;
end = std::remove_if(pos, end, SIdx::UsedFinder(*prev));
}
overlaps.erase(pos, overlaps.end());
} }
static void calculateRepeatability( const Mat& img1, const Mat& img2, const Mat& H1to2, static void calculateRepeatability( const Mat& img1, const Mat& img2, const Mat& H1to2,
const vector<KeyPoint>& _keypoints1, const vector<KeyPoint>& _keypoints2, const vector<KeyPoint>& _keypoints1, const vector<KeyPoint>& _keypoints2,
float& repeatability, int& correspondencesCount, float& repeatability, int& correspondencesCount,
SparseMat_<uchar>* thresholdedOverlapMask=0 ) Mat* thresholdedOverlapMask=0 )
{ {
vector<EllipticKeyPoint> keypoints1, keypoints2, keypoints1t, keypoints2t; vector<EllipticKeyPoint> keypoints1, keypoints2, keypoints1t, keypoints2t;
EllipticKeyPoint::convert( _keypoints1, keypoints1 ); EllipticKeyPoint::convert( _keypoints1, keypoints1 );
...@@ -284,8 +350,8 @@ static void calculateRepeatability( const Mat& img1, const Mat& img2, const Mat& ...@@ -284,8 +350,8 @@ static void calculateRepeatability( const Mat& img1, const Mat& img2, const Mat&
Mat H2to1; invert(H1to2, H2to1); Mat H2to1; invert(H1to2, H2to1);
EllipticKeyPoint::calcProjection( keypoints2, H2to1, keypoints2t ); EllipticKeyPoint::calcProjection( keypoints2, H2to1, keypoints2t );
bool ifEvaluateDetectors = !thresholdedOverlapMask; // == commonPart
float overlapThreshold; float overlapThreshold;
bool ifEvaluateDetectors = thresholdedOverlapMask == 0;
if( ifEvaluateDetectors ) if( ifEvaluateDetectors )
{ {
overlapThreshold = 1.f - 0.4f; overlapThreshold = 1.f - 0.4f;
...@@ -300,57 +366,34 @@ static void calculateRepeatability( const Mat& img1, const Mat& img2, const Mat& ...@@ -300,57 +366,34 @@ static void calculateRepeatability( const Mat& img1, const Mat& img2, const Mat&
else else
{ {
overlapThreshold = 1.f - 0.5f; overlapThreshold = 1.f - 0.5f;
thresholdedOverlapMask->create( keypoints1.size(), keypoints2t.size(), CV_8UC1 );
thresholdedOverlapMask->setTo( Scalar::all(0) );
} }
int minCount = min( keypoints1.size(), keypoints2t.size() ); int minCount = min( keypoints1.size(), keypoints2t.size() );
// calculate overlap errors // calculate overlap errors
SparseMat_<float> overlaps; vector<SIdx> overlaps;
overlap( keypoints1, keypoints2t, ifEvaluateDetectors, overlaps ); computeOneToOneMatchedOverlaps( keypoints1, keypoints2t, ifEvaluateDetectors, overlaps, overlapThreshold/*min overlap*/ );
correspondencesCount = -1; correspondencesCount = -1;
repeatability = -1.f; repeatability = -1.f;
const int* size = overlaps.size(); if( overlaps.empty() )
if( !size || overlaps.nzcount() == 0 )
return; return;
if( ifEvaluateDetectors ) if( ifEvaluateDetectors )
{ {
// threshold the overlaps
for( int y = 0; y < size[0]; y++ )
{
for( int x = 0; x < size[1]; x++ )
{
if ( overlaps(y,x) < overlapThreshold )
overlaps.erase(y,x);
}
}
// regions one-to-one matching // regions one-to-one matching
correspondencesCount = 0; correspondencesCount = overlaps.size();
while( overlaps.nzcount() > 0 ) repeatability = minCount ? (float)correspondencesCount / minCount : -1;
{
double maxOverlap = 0;
int maxIdx[2];
minMaxLoc( overlaps, 0, &maxOverlap, 0, maxIdx );
for( size_t i1 = 0; i1 < keypoints1.size(); i1++ )
overlaps.erase(i1, maxIdx[1]);
for( size_t i2 = 0; i2 < keypoints2t.size(); i2++ )
overlaps.erase(maxIdx[0], i2);
correspondencesCount++;
}
repeatability = minCount ? (float)correspondencesCount/minCount : -1;
} }
else else
{ {
thresholdedOverlapMask->create( 2, size ); for( size_t i = 0; i < overlaps.size(); i++ )
for( int y = 0; y < size[0]; y++ )
{ {
for( int x = 0; x < size[1]; x++ ) int y = overlaps[i].i1;
{ int x = overlaps[i].i2;
float val = overlaps(y,x); thresholdedOverlapMask->at<uchar>(y,x) = 1;
if ( val >= overlapThreshold )
thresholdedOverlapMask->ref(y,x) = 1;
}
} }
} }
} }
...@@ -462,8 +505,9 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con ...@@ -462,8 +505,9 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con
dmatch->clear(); dmatch->clear();
vector<vector<DMatch> > *matches1to2, buf1; vector<vector<DMatch> > *matches1to2, buf1;
vector<vector<uchar> > *correctMatches1to2Mask, buf2;
matches1to2 = _matches1to2 != 0 ? _matches1to2 : &buf1; matches1to2 = _matches1to2 != 0 ? _matches1to2 : &buf1;
vector<vector<uchar> > *correctMatches1to2Mask, buf2;
correctMatches1to2Mask = _correctMatches1to2Mask != 0 ? _correctMatches1to2Mask : &buf2; correctMatches1to2Mask = _correctMatches1to2Mask != 0 ? _correctMatches1to2Mask : &buf2;
if( keypoints1.empty() ) if( keypoints1.empty() )
...@@ -488,14 +532,10 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con ...@@ -488,14 +532,10 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con
} }
float repeatability; float repeatability;
int correspCount; int correspCount;
SparseMat_<uchar> thresholdedOverlapMask; // thresholded allOverlapErrors Mat thresholdedOverlapMask; // thresholded allOverlapErrors
calculateRepeatability( img1, img2, H1to2, calculateRepeatability( img1, img2, H1to2, keypoints1, keypoints2, repeatability, correspCount, &thresholdedOverlapMask );
keypoints1, keypoints2,
repeatability, correspCount,
&thresholdedOverlapMask );
correctMatches1to2Mask->resize(matches1to2->size()); correctMatches1to2Mask->resize(matches1to2->size());
int ddd = 0;
for( size_t i = 0; i < matches1to2->size(); i++ ) for( size_t i = 0; i < matches1to2->size(); i++ )
{ {
(*correctMatches1to2Mask)[i].resize((*matches1to2)[i].size()); (*correctMatches1to2Mask)[i].resize((*matches1to2)[i].size());
...@@ -503,8 +543,7 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con ...@@ -503,8 +543,7 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con
{ {
int indexQuery = (*matches1to2)[i][j].indexQuery; int indexQuery = (*matches1to2)[i][j].indexQuery;
int indexTrain = (*matches1to2)[i][j].indexTrain; int indexTrain = (*matches1to2)[i][j].indexTrain;
(*correctMatches1to2Mask)[i][j] = thresholdedOverlapMask( indexQuery, indexTrain ); (*correctMatches1to2Mask)[i][j] = thresholdedOverlapMask.at<uchar>( indexQuery, indexTrain );
ddd += thresholdedOverlapMask( indexQuery, indexTrain ) != 0 ? 1 : 0;
} }
} }
......
...@@ -569,7 +569,7 @@ void FernDescriptorMatch::trainFernClassifier() ...@@ -569,7 +569,7 @@ void FernDescriptorMatch::trainFernClassifier()
{ {
assert( params.filename.empty() ); assert( params.filename.empty() );
vector<vector<Point2f> > points; vector<vector<Point2f> > points(collection.images.size());
for( size_t imgIdx = 0; imgIdx < collection.images.size(); imgIdx++ ) for( size_t imgIdx = 0; imgIdx < collection.images.size(); imgIdx++ )
KeyPoint::convert( collection.points[imgIdx], points[imgIdx] ); KeyPoint::convert( collection.points[imgIdx], points[imgIdx] );
...@@ -757,34 +757,34 @@ void VectorDescriptorMatch::write (FileStorage& fs) const ...@@ -757,34 +757,34 @@ void VectorDescriptorMatch::write (FileStorage& fs) const
/****************************************************************************************\ /****************************************************************************************\
* Factory function for GenericDescriptorMatch creating * * Factory function for GenericDescriptorMatch creating *
\****************************************************************************************/ \****************************************************************************************/
Ptr<GenericDescriptorMatch> createGenericDescriptorMatch( const string& genericDescritptorMatchType, Ptr<GenericDescriptorMatch> createGenericDescriptorMatcher( const string& genericDescritptorMatcherType,
const string &paramsFilename ) const string &paramsFilename )
{ {
GenericDescriptorMatch *descriptorMatch = 0; GenericDescriptorMatch *descriptorMatcher = 0;
if( ! genericDescritptorMatchType.compare("ONEWAY") ) if( ! genericDescritptorMatcherType.compare("ONEWAY") )
{ {
descriptorMatch = new OneWayDescriptorMatch(); descriptorMatcher = new OneWayDescriptorMatch();
} }
else if( ! genericDescritptorMatchType.compare("FERN") ) else if( ! genericDescritptorMatcherType.compare("FERN") )
{ {
descriptorMatch = new FernDescriptorMatch(); descriptorMatcher = new FernDescriptorMatch();
} }
else if( ! genericDescritptorMatchType.compare ("CALONDER") ) else if( ! genericDescritptorMatcherType.compare ("CALONDER") )
{ {
//descriptorMatch = new CalonderDescriptorMatch (); //descriptorMatch = new CalonderDescriptorMatch ();
} }
if( !paramsFilename.empty() && descriptorMatch != 0 ) if( !paramsFilename.empty() && descriptorMatcher != 0 )
{ {
FileStorage fs = FileStorage( paramsFilename, FileStorage::READ ); FileStorage fs = FileStorage( paramsFilename, FileStorage::READ );
if( fs.isOpened() ) if( fs.isOpened() )
{ {
descriptorMatch->read( fs.root() ); descriptorMatcher->read( fs.root() );
fs.release(); fs.release();
} }
} }
return descriptorMatch; return descriptorMatcher;
} }
} }
...@@ -24,8 +24,8 @@ int main(int argc, char** argv) ...@@ -24,8 +24,8 @@ int main(int argc, char** argv)
std::string alg_name = std::string(argv[3]); std::string alg_name = std::string(argv[3]);
std::string params_filename = std::string(argv[4]); std::string params_filename = std::string(argv[4]);
GenericDescriptorMatch *descriptorMatch = createGenericDescriptorMatch(alg_name, params_filename); GenericDescriptorMatch *descriptorMatcher = createGenericDescriptorMatcher(alg_name, params_filename);
if( descriptorMatch == 0 ) if( descriptorMatcher == 0 )
{ {
printf ("Cannot create descriptor\n"); printf ("Cannot create descriptor\n");
return 0; return 0;
...@@ -50,10 +50,10 @@ int main(int argc, char** argv) ...@@ -50,10 +50,10 @@ int main(int argc, char** argv)
printf("Finding nearest neighbors... \n"); printf("Finding nearest neighbors... \n");
// find NN for each of keypoints2 in keypoints1 // find NN for each of keypoints2 in keypoints1
descriptorMatch->add( img1, keypoints1 ); descriptorMatcher->add( img1, keypoints1 );
vector<int> matches2to1; vector<int> matches2to1;
matches2to1.resize(keypoints2.size()); matches2to1.resize(keypoints2.size());
descriptorMatch->match( img2, keypoints2, matches2to1 ); descriptorMatcher->match( img2, keypoints2, matches2to1 );
printf("Done\n"); printf("Done\n");
IplImage* img_corr = DrawCorrespondences(img1, keypoints1, img2, keypoints2, matches2to1); IplImage* img_corr = DrawCorrespondences(img1, keypoints1, img2, keypoints2, matches2to1);
...@@ -65,7 +65,7 @@ int main(int argc, char** argv) ...@@ -65,7 +65,7 @@ int main(int argc, char** argv)
cvReleaseImage(&img1); cvReleaseImage(&img1);
cvReleaseImage(&img2); cvReleaseImage(&img2);
cvReleaseImage(&img_corr); cvReleaseImage(&img_corr);
delete descriptorMatch; delete descriptorMatcher;
} }
IplImage* DrawCorrespondences(IplImage* img1, const vector<KeyPoint>& features1, IplImage* img2, IplImage* DrawCorrespondences(IplImage* img1, const vector<KeyPoint>& features1, IplImage* img2,
......
...@@ -716,7 +716,7 @@ void DetectorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vector< ...@@ -716,7 +716,7 @@ void DetectorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vector<
evaluateFeatureDetector( imgs[0], imgs[ci+1], Hs[ci], &keypoints1, &keypoints2, evaluateFeatureDetector( imgs[0], imgs[ci+1], Hs[ci], &keypoints1, &keypoints2,
rep, calcQuality[di][ci].correspondenceCount, rep, calcQuality[di][ci].correspondenceCount,
detector ); detector );
calcQuality[di][ci].repeatability = 100.f*rep; calcQuality[di][ci].repeatability = rep == -1 ? rep : 100.f*rep;
writeKeypoints( keypontsFS, keypoints2, ci+1); writeKeypoints( keypontsFS, keypoints2, ci+1);
} }
} }
...@@ -732,32 +732,25 @@ void testLog( CvTS* ts, bool isBadAccuracy ) ...@@ -732,32 +732,25 @@ void testLog( CvTS* ts, bool isBadAccuracy )
int DetectorQualityTest::processResults( int datasetIdx, int caseIdx ) int DetectorQualityTest::processResults( int datasetIdx, int caseIdx )
{ {
int res = CvTS::OK; int res = CvTS::OK;
bool isBadAccuracy;
Quality valid = validQuality[datasetIdx][caseIdx], calc = calcQuality[datasetIdx][caseIdx]; Quality valid = validQuality[datasetIdx][caseIdx], calc = calcQuality[datasetIdx][caseIdx];
bool isBadAccuracy; const int countEps = 1 + cvRound( 0.005f*(float)valid.correspondenceCount );
int countEps = 1; const float rltvEps = 0.5f;
const float rltvEps = 0.001;
ts->printf(CvTS::LOG, "%s: calc=%f, valid=%f", REPEAT.c_str(), calc.repeatability, valid.repeatability ); ts->printf(CvTS::LOG, "%s: calc=%f, valid=%f", REPEAT.c_str(), calc.repeatability, valid.repeatability );
isBadAccuracy = valid.repeatability - calc.repeatability > rltvEps; isBadAccuracy = (valid.repeatability - calc.repeatability) > rltvEps;
testLog( ts, isBadAccuracy ); testLog( ts, isBadAccuracy );
res = isBadAccuracy ? CvTS::FAIL_BAD_ACCURACY : res; res = isBadAccuracy ? CvTS::FAIL_BAD_ACCURACY : res;
ts->printf(CvTS::LOG, "%s: calc=%d, valid=%d", CORRESP_COUNT.c_str(), calc.correspondenceCount, valid.correspondenceCount ); ts->printf(CvTS::LOG, "%s: calc=%d, valid=%d", CORRESP_COUNT.c_str(), calc.correspondenceCount, valid.correspondenceCount );
isBadAccuracy = valid.correspondenceCount - calc.correspondenceCount > countEps; isBadAccuracy = (valid.correspondenceCount - calc.correspondenceCount) > countEps;
testLog( ts, isBadAccuracy ); testLog( ts, isBadAccuracy );
res = isBadAccuracy ? CvTS::FAIL_BAD_ACCURACY : res; res = isBadAccuracy ? CvTS::FAIL_BAD_ACCURACY : res;
return res; return res;
} }
DetectorQualityTest fastDetectorQuality = DetectorQualityTest( "FAST", "quality-detector-fast" );
DetectorQualityTest gfttDetectorQuality = DetectorQualityTest( "GFTT", "quality-detector-gftt" );
DetectorQualityTest harrisDetectorQuality = DetectorQualityTest( "HARRIS", "quality-detector-harris" );
DetectorQualityTest mserDetectorQuality = DetectorQualityTest( "MSER", "quality-detector-mser" );
DetectorQualityTest starDetectorQuality = DetectorQualityTest( "STAR", "quality-detector-star" );
DetectorQualityTest siftDetectorQuality = DetectorQualityTest( "SIFT", "quality-detector-sift" );
DetectorQualityTest surfDetectorQuality = DetectorQualityTest( "SURF", "quality-detector-surf" );
/****************************************************************************************\ /****************************************************************************************\
* Descriptors evaluation * * Descriptors evaluation *
\****************************************************************************************/ \****************************************************************************************/
...@@ -844,8 +837,8 @@ protected: ...@@ -844,8 +837,8 @@ protected:
}; };
vector<CommonRunParams> commRunParams; vector<CommonRunParams> commRunParams;
Ptr<GenericDescriptorMatch> specificDescMatch; Ptr<GenericDescriptorMatch> specificDescMatcher;
Ptr<GenericDescriptorMatch> defaultDescMatch; Ptr<GenericDescriptorMatch> defaultDescMatcher;
CommonRunParams commRunParamsDefault; CommonRunParams commRunParamsDefault;
string matcherName; string matcherName;
...@@ -909,7 +902,7 @@ void DescriptorQualityTest::readDefaultRunParams (FileNode &fn) ...@@ -909,7 +902,7 @@ void DescriptorQualityTest::readDefaultRunParams (FileNode &fn)
{ {
commRunParamsDefault.projectKeypointsFrom1Image = (int)fn[PROJECT_KEYPOINTS_FROM_1IMAGE] != 0; commRunParamsDefault.projectKeypointsFrom1Image = (int)fn[PROJECT_KEYPOINTS_FROM_1IMAGE] != 0;
commRunParamsDefault.matchFilter = (int)fn[MATCH_FILTER]; commRunParamsDefault.matchFilter = (int)fn[MATCH_FILTER];
defaultDescMatch->read (fn); defaultDescMatcher->read (fn);
} }
} }
...@@ -917,7 +910,7 @@ void DescriptorQualityTest::writeDefaultRunParams (FileStorage &fs) const ...@@ -917,7 +910,7 @@ void DescriptorQualityTest::writeDefaultRunParams (FileStorage &fs) const
{ {
fs << PROJECT_KEYPOINTS_FROM_1IMAGE << commRunParamsDefault.projectKeypointsFrom1Image; fs << PROJECT_KEYPOINTS_FROM_1IMAGE << commRunParamsDefault.projectKeypointsFrom1Image;
fs << MATCH_FILTER << commRunParamsDefault.matchFilter; fs << MATCH_FILTER << commRunParamsDefault.matchFilter;
defaultDescMatch->write (fs); defaultDescMatcher->write (fs);
} }
void DescriptorQualityTest::readDatasetRunParams( FileNode& fn, int datasetIdx ) void DescriptorQualityTest::readDatasetRunParams( FileNode& fn, int datasetIdx )
...@@ -928,7 +921,7 @@ void DescriptorQualityTest::readDatasetRunParams( FileNode& fn, int datasetIdx ) ...@@ -928,7 +921,7 @@ void DescriptorQualityTest::readDatasetRunParams( FileNode& fn, int datasetIdx )
commRunParams[datasetIdx].keypontsFilename = (string)fn[KEYPOINTS_FILENAME]; commRunParams[datasetIdx].keypontsFilename = (string)fn[KEYPOINTS_FILENAME];
commRunParams[datasetIdx].projectKeypointsFrom1Image = (int)fn[PROJECT_KEYPOINTS_FROM_1IMAGE] != 0; commRunParams[datasetIdx].projectKeypointsFrom1Image = (int)fn[PROJECT_KEYPOINTS_FROM_1IMAGE] != 0;
commRunParams[datasetIdx].matchFilter = (int)fn[MATCH_FILTER]; commRunParams[datasetIdx].matchFilter = (int)fn[MATCH_FILTER];
specificDescMatch->read (fn); specificDescMatcher->read (fn);
} }
else else
{ {
...@@ -943,13 +936,13 @@ void DescriptorQualityTest::writeDatasetRunParams( FileStorage& fs, int datasetI ...@@ -943,13 +936,13 @@ void DescriptorQualityTest::writeDatasetRunParams( FileStorage& fs, int datasetI
fs << PROJECT_KEYPOINTS_FROM_1IMAGE << commRunParams[datasetIdx].projectKeypointsFrom1Image; fs << PROJECT_KEYPOINTS_FROM_1IMAGE << commRunParams[datasetIdx].projectKeypointsFrom1Image;
fs << MATCH_FILTER << commRunParams[datasetIdx].matchFilter; fs << MATCH_FILTER << commRunParams[datasetIdx].matchFilter;
defaultDescMatch->write (fs); defaultDescMatcher->write (fs);
} }
void DescriptorQualityTest::setDefaultDatasetRunParams( int datasetIdx ) void DescriptorQualityTest::setDefaultDatasetRunParams( int datasetIdx )
{ {
commRunParams[datasetIdx] = commRunParamsDefault; commRunParams[datasetIdx] = commRunParamsDefault;
commRunParams[datasetIdx].keypontsFilename = "surf_" + DATASET_NAMES[datasetIdx] + ".xml.gz"; commRunParams[datasetIdx].keypontsFilename = "SURF_" + DATASET_NAMES[datasetIdx] + ".xml.gz";
} }
void DescriptorQualityTest::writePlotData( int di ) const void DescriptorQualityTest::writePlotData( int di ) const
...@@ -967,15 +960,15 @@ void DescriptorQualityTest::writePlotData( int di ) const ...@@ -967,15 +960,15 @@ void DescriptorQualityTest::writePlotData( int di ) const
void DescriptorQualityTest::readAlgorithm( ) void DescriptorQualityTest::readAlgorithm( )
{ {
defaultDescMatch = createGenericDescriptorMatch( algName ); defaultDescMatcher = createGenericDescriptorMatcher( algName );
specificDescMatch = createGenericDescriptorMatch( algName ); specificDescMatcher = createGenericDescriptorMatcher( algName );
if( defaultDescMatch == 0 ) if( defaultDescMatcher == 0 )
{ {
Ptr<DescriptorExtractor> extractor = createDescriptorExtractor( algName ); Ptr<DescriptorExtractor> extractor = createDescriptorExtractor( algName );
Ptr<DescriptorMatcher> matcher = createDescriptorMatcher( matcherName ); Ptr<DescriptorMatcher> matcher = createDescriptorMatcher( matcherName );
defaultDescMatch = new VectorDescriptorMatch( extractor, matcher ); defaultDescMatcher = new VectorDescriptorMatch( extractor, matcher );
specificDescMatch = new VectorDescriptorMatch( extractor, matcher ); specificDescMatcher = new VectorDescriptorMatch( extractor, matcher );
if( extractor == 0 || matcher == 0 ) if( extractor == 0 || matcher == 0 )
{ {
...@@ -1035,7 +1028,7 @@ void DescriptorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vecto ...@@ -1035,7 +1028,7 @@ void DescriptorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vecto
return; return;
} }
Ptr<GenericDescriptorMatch> descMatch = commRunParams[di].isActiveParams ? specificDescMatch : defaultDescMatch; Ptr<GenericDescriptorMatch> descMatch = commRunParams[di].isActiveParams ? specificDescMatcher : defaultDescMatcher;
calcQuality[di].resize(TEST_CASE_COUNT); calcQuality[di].resize(TEST_CASE_COUNT);
vector<KeyPoint> keypoints1; vector<KeyPoint> keypoints1;
...@@ -1076,28 +1069,40 @@ void DescriptorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vecto ...@@ -1076,28 +1069,40 @@ void DescriptorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vecto
int DescriptorQualityTest::processResults( int datasetIdx, int caseIdx ) int DescriptorQualityTest::processResults( int datasetIdx, int caseIdx )
{ {
const float rltvEps = 0.001f;
int res = CvTS::OK; int res = CvTS::OK;
bool isBadAccuracy;
Quality valid = validQuality[datasetIdx][caseIdx], calc = calcQuality[datasetIdx][caseIdx]; Quality valid = validQuality[datasetIdx][caseIdx], calc = calcQuality[datasetIdx][caseIdx];
bool isBadAccuracy;
const float rltvEps = 0.001f;
ts->printf(CvTS::LOG, "%s: calc=%f, valid=%f", RECALL.c_str(), calc.recall, valid.recall ); ts->printf(CvTS::LOG, "%s: calc=%f, valid=%f", RECALL.c_str(), calc.recall, valid.recall );
isBadAccuracy = valid.recall - calc.recall > rltvEps; isBadAccuracy = (valid.recall - calc.recall) > rltvEps;
testLog( ts, isBadAccuracy ); testLog( ts, isBadAccuracy );
res = isBadAccuracy ? CvTS::FAIL_BAD_ACCURACY : res; res = isBadAccuracy ? CvTS::FAIL_BAD_ACCURACY : res;
ts->printf(CvTS::LOG, "%s: calc=%f, valid=%f", PRECISION.c_str(), calc.precision, valid.precision ); ts->printf(CvTS::LOG, "%s: calc=%f, valid=%f", PRECISION.c_str(), calc.precision, valid.precision );
isBadAccuracy = valid.precision - calc.precision > rltvEps; isBadAccuracy = (valid.precision - calc.precision) > rltvEps;
testLog( ts, isBadAccuracy ); testLog( ts, isBadAccuracy );
res = isBadAccuracy ? CvTS::FAIL_BAD_ACCURACY : res; res = isBadAccuracy ? CvTS::FAIL_BAD_ACCURACY : res;
return res; return res;
} }
//DescriptorQualityTest siftDescriptorQuality = DescriptorQualityTest( "SIFT", "quality-descriptor-sift", "BruteForce" ); //--------------------------------- Calonder descriptor test --------------------------------------------
//DescriptorQualityTest surfDescriptorQuality = DescriptorQualityTest( "SURF", "quality-descriptor-surf", "BruteForce" ); class CalonderDescriptorQualityTest : public DescriptorQualityTest
//DescriptorQualityTest siftL1DescriptorQuality = DescriptorQualityTest( "SIFT", "quality-descriptor-sift-L1", "BruteForce-L1" ); {
//DescriptorQualityTest surfL1DescriptorQuality = DescriptorQualityTest( "SURF", "quality-descriptor-surf-L1", "BruteForce-L1" ); public:
CalonderDescriptorQualityTest() :
DescriptorQualityTest( "Calonder", "quality-descriptor-calonder") {}
virtual void readAlgorithm( )
{
string classifierFile = string(ts->get_data_path()) + "/features2d/calonder_classifier.rtc";
defaultDescMatcher = new VectorDescriptorMatch( new CalonderDescriptorExtractor<float>( classifierFile ),
new BruteForceMatcher<L2<float> > );
specificDescMatcher = defaultDescMatcher;
}
};
//--------------------------------- One Way descriptor test -------------------------------------------- //--------------------------------- One Way descriptor test --------------------------------------------
class OneWayDescriptorQualityTest : public DescriptorQualityTest class OneWayDescriptorQualityTest : public DescriptorQualityTest
...@@ -1139,7 +1144,7 @@ void OneWayDescriptorQualityTest::processRunParamsFile () ...@@ -1139,7 +1144,7 @@ void OneWayDescriptorQualityTest::processRunParamsFile ()
OneWayDescriptorMatch *match = new OneWayDescriptorMatch (); OneWayDescriptorMatch *match = new OneWayDescriptorMatch ();
match->initialize( OneWayDescriptorMatch::Params (), base ); match->initialize( OneWayDescriptorMatch::Params (), base );
defaultDescMatch = match; defaultDescMatcher = match;
writeAllDatasetsRunParams(); writeAllDatasetsRunParams();
} }
...@@ -1151,7 +1156,30 @@ void OneWayDescriptorQualityTest::writeDatasetRunParams( FileStorage& fs, int da ...@@ -1151,7 +1156,30 @@ void OneWayDescriptorQualityTest::writeDatasetRunParams( FileStorage& fs, int da
fs << MATCH_FILTER << commRunParams[datasetIdx].matchFilter; fs << MATCH_FILTER << commRunParams[datasetIdx].matchFilter;
} }
// Detectors
//DetectorQualityTest fastDetectorQuality = DetectorQualityTest( "FAST", "quality-detector-fast" );
//DetectorQualityTest gfttDetectorQuality = DetectorQualityTest( "GFTT", "quality-detector-gftt" );
//DetectorQualityTest harrisDetectorQuality = DetectorQualityTest( "HARRIS", "quality-detector-harris" );
//DetectorQualityTest mserDetectorQuality = DetectorQualityTest( "MSER", "quality-detector-mser" );
//DetectorQualityTest starDetectorQuality = DetectorQualityTest( "STAR", "quality-detector-star" );
//DetectorQualityTest siftDetectorQuality = DetectorQualityTest( "SIFT", "quality-detector-sift" );
//DetectorQualityTest surfDetectorQuality = DetectorQualityTest( "SURF", "quality-detector-surf" );
//OneWayDescriptorQualityTest oneWayDescriptorQuality; // Detectors
//DescriptorQualityTest siftDescriptorQuality = DescriptorQualityTest( "SIFT", "quality-descriptor-sift", "BruteForce" );
//DescriptorQualityTest surfDescriptorQuality = DescriptorQualityTest( "SURF", "quality-descriptor-surf", "BruteForce" );
//DescriptorQualityTest fernDescriptorQualityTest( "FERN", "quality-descriptor-fern"); //DescriptorQualityTest fernDescriptorQualityTest( "FERN", "quality-descriptor-fern");
//DescriptorQualityTest calonderDescriptorQualityTest( "CALONDER", "quality-descriptor-calonder"); //CalonderDescriptorQualityTest calonderDescriptorQualityTest;
// Don't run them because of bug in OneWayDescriptorBase many to many matching. TODO: fix this bug.
//OneWayDescriptorQualityTest oneWayDescriptorQuality;
// Don't run them (will validate and save results as "quality-descriptor-sift" and "quality-descriptor-surf" test data).
// TODO: differ result filenames.
//DescriptorQualityTest siftL1DescriptorQuality = DescriptorQualityTest( "SIFT", "quality-descriptor-sift-L1", "BruteForce-L1" );
//DescriptorQualityTest surfL1DescriptorQuality = DescriptorQualityTest( "SURF", "quality-descriptor-surf-L1", "BruteForce-L1" );
//DescriptorQualityTest oppSiftL1DescriptorQuality = DescriptorQualityTest( "SIFT", "quality-descriptor-opponent-sift-L1", "BruteForce-L1" );
//DescriptorQualityTest oppSurfL1DescriptorQuality = DescriptorQualityTest( "SURF", "quality-descriptor-opponent-surf-L1", "BruteForce-L1" );
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment