diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp index 9b940d3783..175613c3d4 100644 --- a/modules/features2d/include/opencv2/features2d/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d/features2d.hpp @@ -1516,7 +1516,8 @@ struct CV_EXPORTS L2 */ struct DMatch { - int index; + int indexTrain; + int indexQuery; float distance; //less is better @@ -1712,7 +1713,7 @@ void BruteForceMatcher::matchImpl( const Mat& descriptors_1, const Mat matches.resize( matchings.size() ); for( size_t i=0;i::matchImpl( const Mat& descriptors_1, const Mat if( matchIndex != -1 ) { - DMatch matching; - matching.index = matchIndex; - matching.distance = matchDistance; - matches[i] = matching; + DMatch match; + match.indexTrain = matchIndex; + match.indexQuery = i; + match.distance = matchDistance; + matches[i] = match; } } } @@ -1830,8 +1832,8 @@ public: // Matches test keypoints to the training set // image The source image // points Test keypoints from the source image - // matchings A vector to be filled with keypoint matchings - virtual void match( const Mat& image, vector& points, vector& matchings ) {}; + // matches A vector to be filled with keypoint matches + virtual void match( const Mat& image, vector& points, vector& matches ) {}; // Clears keypoints storing in collection virtual void clear(); @@ -1907,7 +1909,7 @@ public: // loaded with DescriptorOneWay::Initialize, kd tree is used for finding minimum distances. virtual void match( const Mat& image, vector& points, vector& indices ); - virtual void match( const Mat& image, vector& points, vector& matchings ); + virtual void match( const Mat& image, vector& points, vector& matches ); // Classify a set of keypoints. The same as match, but returns point classes rather than indices virtual void classify( const Mat& image, vector& points ); @@ -2037,7 +2039,7 @@ public: virtual void match( const Mat& image, vector& keypoints, vector& indices ); - virtual void match( const Mat& image, vector& points, vector& matchings ); + virtual void match( const Mat& image, vector& points, vector& matches ); virtual void classify( const Mat& image, vector& keypoints ); @@ -2095,12 +2097,12 @@ public: matcher.match( descriptors, keypointIndices ); }; - virtual void match( const Mat& image, vector& points, vector& matchings ) + virtual void match( const Mat& image, vector& points, vector& matches ) { Mat descriptors; extractor.compute( image, points, descriptors ); - matcher.match( descriptors, matchings ); + matcher.match( descriptors, matches ); } virtual void clear() diff --git a/tests/cv/src/adetectordescriptor_evaluation.cpp b/tests/cv/src/adetectordescriptor_evaluation.cpp index 70276287a8..7a24ec69b8 100644 --- a/tests/cv/src/adetectordescriptor_evaluation.cpp +++ b/tests/cv/src/adetectordescriptor_evaluation.cpp @@ -372,20 +372,21 @@ void calculateRepeatability( const vector& _keypoints1, const if( !size || overlaps.nzcount() == 0 ) return; - // 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); - } - } 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 correspondencesCount = 0; - while( overlaps.nzcount() > 0 ) + while( overlaps.nzcount() > 0 ) { double maxOverlap = 0; int maxIdx[2]; @@ -400,7 +401,16 @@ void calculateRepeatability( const vector& _keypoints1, const } else { - overlaps.copyTo(*thresholdedOverlapMask); + thresholdedOverlapMask->create( 2, size ); + for( int y = 0; y < size[0]; y++ ) + { + for( int x = 0; x < size[1]; x++ ) + { + float val = overlaps(y,x); + if ( val >= overlapThreshold ) + thresholdedOverlapMask->ref(y,x) = val; + } + } } } @@ -424,10 +434,23 @@ inline float precision( int correctMatchCount, int falseMatchCount ) return correctMatchCount + falseMatchCount ? (float)correctMatchCount / (float)(correctMatchCount + falseMatchCount) : -1; } + +struct DMatchForEvaluation +{ + DMatch match; + int isCorrect; + + bool operator<( const DMatchForEvaluation &m) const + { + return match < m.match; + } +}; + + void evaluateDescriptors( const vector& keypoints1, const vector& keypoints2, - vector< pair >& matches1to2, + vector& matches1to2, const Mat& img1, const Mat& img2, const Mat& H1to2, - int &correctMatchCount, int &falseMatchCount, vector &matchStatuses, int& correspondenceCount ) + int &correctMatchCount, int &falseMatchCount, int& correspondenceCount ) { assert( !keypoints1.empty() && !keypoints2.empty() && !matches1to2.empty() ); assert( keypoints1.size() == matches1to2.size() ); @@ -441,26 +464,23 @@ void evaluateDescriptors( const vector& keypoints1, const vect &thresholdedOverlapMask ); correspondenceCount = thresholdedOverlapMask.nzcount(); - matchStatuses.resize( matches1to2.size() ); correctMatchCount = 0; falseMatchCount = 0; - //the nearest descriptors should be examined first - std::sort( matches1to2.begin(), matches1to2.end() ); - - for( size_t i1 = 0; i1 < matches1to2.size(); i1++ ) + for( size_t i = 0; i < matches1to2.size(); i++ ) { - int i2 = matches1to2[i1].first.index; - if( i2 > 0 ) + if( matches1to2[i].match.indexTrain > 0 ) { - matchStatuses[i2] = thresholdedOverlapMask(matches1to2[i1].second, i2); - if( matchStatuses[i2] ) + matches1to2[i].isCorrect = thresholdedOverlapMask( matches1to2[i].match.indexQuery, matches1to2[i].match.indexTrain); + if( matches1to2[i].isCorrect ) correctMatchCount++; else falseMatchCount++; } else - matchStatuses[i2] = -1; + { + matches1to2[i].isCorrect = -1; + } } } @@ -1408,9 +1428,8 @@ void DescriptorQualityTest::runDatasetTest (const vector &imgs, const vecto transformToEllipticKeyPoints( keypoints1, ekeypoints1 ); int progressCount = DATASETS_COUNT*TEST_CASE_COUNT; - vector< pair > allMatchings; - vector allMatchStatuses; - size_t matchingIndex = 0; + vector allMatches; + int allCorrespCount = 0; for( int ci = 0; ci < TEST_CASE_COUNT; ci++ ) { @@ -1428,43 +1447,38 @@ void DescriptorQualityTest::runDatasetTest (const vector &imgs, const vecto readKeypoints( keypontsFS, keypoints2, ci+1 ); transformToEllipticKeyPoints( keypoints2, ekeypoints2 ); descMatch->add( imgs[ci+1], keypoints2 ); - vector matchings1to2; - descMatch->match( imgs[0], keypoints1, matchings1to2 ); - vector< pair > matchings (matchings1to2.size()); - for( size_t i=0;i( matchings1to2[i], i); + vector matches1to2; + descMatch->match( imgs[0], keypoints1, matches1to2 ); + vector matches ( matches1to2.size() ); + for( size_t i=0;i matchStatuses; - evaluateDescriptors( ekeypoints1, ekeypoints2, matchings, imgs[0], imgs[ci+1], Hs[ci], - correctMatchCount, falseMatchCount, matchStatuses, correspCount ); - for( size_t i=0;iclear (); } - std::sort( allMatchings.begin(), allMatchings.end() ); + std::sort( allMatches.begin(), allMatches.end() ); - calcDatasetQuality[di].resize( allMatchings.size() ); + calcDatasetQuality[di].resize( allMatches.size() ); int correctMatchCount = 0, falseMatchCount = 0; - for( size_t i=0;i