mirror of
https://github.com/opencv/opencv.git
synced 2025-06-11 20:09:23 +08:00
Fixed plot data generation for descriptors comparison
This commit is contained in:
parent
400eb37189
commit
673b4404a9
@ -1516,7 +1516,8 @@ struct CV_EXPORTS L2
|
|||||||
*/
|
*/
|
||||||
struct DMatch
|
struct DMatch
|
||||||
{
|
{
|
||||||
int index;
|
int indexTrain;
|
||||||
|
int indexQuery;
|
||||||
float distance;
|
float distance;
|
||||||
|
|
||||||
//less is better
|
//less is better
|
||||||
@ -1712,7 +1713,7 @@ void BruteForceMatcher<Distance>::matchImpl( const Mat& descriptors_1, const Mat
|
|||||||
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++)
|
||||||
{
|
{
|
||||||
matches[i] = matchings[i].index;
|
matches[i] = matchings[i].indexTrain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1754,10 +1755,11 @@ void BruteForceMatcher<Distance>::matchImpl( const Mat& descriptors_1, const Mat
|
|||||||
|
|
||||||
if( matchIndex != -1 )
|
if( matchIndex != -1 )
|
||||||
{
|
{
|
||||||
DMatch matching;
|
DMatch match;
|
||||||
matching.index = matchIndex;
|
match.indexTrain = matchIndex;
|
||||||
matching.distance = matchDistance;
|
match.indexQuery = i;
|
||||||
matches[i] = matching;
|
match.distance = matchDistance;
|
||||||
|
matches[i] = match;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1830,8 +1832,8 @@ public:
|
|||||||
// Matches test keypoints to the training set
|
// Matches test keypoints to the training set
|
||||||
// image The source image
|
// image The source image
|
||||||
// points Test keypoints from the source image
|
// points Test keypoints from the source image
|
||||||
// matchings A vector to be filled with keypoint matchings
|
// matches A vector to be filled with keypoint matches
|
||||||
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matchings ) {};
|
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matches ) {};
|
||||||
|
|
||||||
// Clears keypoints storing in collection
|
// Clears keypoints storing in collection
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
@ -1907,7 +1909,7 @@ public:
|
|||||||
// loaded with DescriptorOneWay::Initialize, kd tree is used for finding minimum distances.
|
// loaded with DescriptorOneWay::Initialize, kd tree is used for finding minimum distances.
|
||||||
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<int>& indices );
|
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<int>& indices );
|
||||||
|
|
||||||
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matchings );
|
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matches );
|
||||||
|
|
||||||
// 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 );
|
||||||
@ -2037,7 +2039,7 @@ public:
|
|||||||
|
|
||||||
virtual void match( const Mat& image, vector<KeyPoint>& keypoints, vector<int>& indices );
|
virtual void match( const Mat& image, vector<KeyPoint>& keypoints, vector<int>& indices );
|
||||||
|
|
||||||
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matchings );
|
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matches );
|
||||||
|
|
||||||
virtual void classify( const Mat& image, vector<KeyPoint>& keypoints );
|
virtual void classify( const Mat& image, vector<KeyPoint>& keypoints );
|
||||||
|
|
||||||
@ -2095,12 +2097,12 @@ public:
|
|||||||
matcher.match( descriptors, keypointIndices );
|
matcher.match( descriptors, keypointIndices );
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matchings )
|
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, matchings );
|
matcher.match( descriptors, matches );
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void clear()
|
virtual void clear()
|
||||||
|
@ -372,20 +372,21 @@ void calculateRepeatability( const vector<EllipticKeyPoint>& _keypoints1, const
|
|||||||
if( !size || overlaps.nzcount() == 0 )
|
if( !size || overlaps.nzcount() == 0 )
|
||||||
return;
|
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 )
|
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 = 0;
|
||||||
while( overlaps.nzcount() > 0 )
|
while( overlaps.nzcount() > 0 )
|
||||||
{
|
{
|
||||||
double maxOverlap = 0;
|
double maxOverlap = 0;
|
||||||
int maxIdx[2];
|
int maxIdx[2];
|
||||||
@ -400,7 +401,16 @@ void calculateRepeatability( const vector<EllipticKeyPoint>& _keypoints1, const
|
|||||||
}
|
}
|
||||||
else
|
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;
|
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<EllipticKeyPoint>& keypoints1, const vector<EllipticKeyPoint>& keypoints2,
|
void evaluateDescriptors( const vector<EllipticKeyPoint>& keypoints1, const vector<EllipticKeyPoint>& keypoints2,
|
||||||
vector< pair<DMatch, int> >& matches1to2,
|
vector<DMatchForEvaluation>& matches1to2,
|
||||||
const Mat& img1, const Mat& img2, const Mat& H1to2,
|
const Mat& img1, const Mat& img2, const Mat& H1to2,
|
||||||
int &correctMatchCount, int &falseMatchCount, vector<int> &matchStatuses, int& correspondenceCount )
|
int &correctMatchCount, int &falseMatchCount, int& correspondenceCount )
|
||||||
{
|
{
|
||||||
assert( !keypoints1.empty() && !keypoints2.empty() && !matches1to2.empty() );
|
assert( !keypoints1.empty() && !keypoints2.empty() && !matches1to2.empty() );
|
||||||
assert( keypoints1.size() == matches1to2.size() );
|
assert( keypoints1.size() == matches1to2.size() );
|
||||||
@ -441,26 +464,23 @@ void evaluateDescriptors( const vector<EllipticKeyPoint>& keypoints1, const vect
|
|||||||
&thresholdedOverlapMask );
|
&thresholdedOverlapMask );
|
||||||
correspondenceCount = thresholdedOverlapMask.nzcount();
|
correspondenceCount = thresholdedOverlapMask.nzcount();
|
||||||
|
|
||||||
matchStatuses.resize( matches1to2.size() );
|
|
||||||
correctMatchCount = 0;
|
correctMatchCount = 0;
|
||||||
falseMatchCount = 0;
|
falseMatchCount = 0;
|
||||||
|
|
||||||
//the nearest descriptors should be examined first
|
for( size_t i = 0; i < matches1to2.size(); i++ )
|
||||||
std::sort( matches1to2.begin(), matches1to2.end() );
|
|
||||||
|
|
||||||
for( size_t i1 = 0; i1 < matches1to2.size(); i1++ )
|
|
||||||
{
|
{
|
||||||
int i2 = matches1to2[i1].first.index;
|
if( matches1to2[i].match.indexTrain > 0 )
|
||||||
if( i2 > 0 )
|
|
||||||
{
|
{
|
||||||
matchStatuses[i2] = thresholdedOverlapMask(matches1to2[i1].second, i2);
|
matches1to2[i].isCorrect = thresholdedOverlapMask( matches1to2[i].match.indexQuery, matches1to2[i].match.indexTrain);
|
||||||
if( matchStatuses[i2] )
|
if( matches1to2[i].isCorrect )
|
||||||
correctMatchCount++;
|
correctMatchCount++;
|
||||||
else
|
else
|
||||||
falseMatchCount++;
|
falseMatchCount++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
matchStatuses[i2] = -1;
|
{
|
||||||
|
matches1to2[i].isCorrect = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1408,9 +1428,8 @@ void DescriptorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vecto
|
|||||||
transformToEllipticKeyPoints( keypoints1, ekeypoints1 );
|
transformToEllipticKeyPoints( keypoints1, ekeypoints1 );
|
||||||
|
|
||||||
int progressCount = DATASETS_COUNT*TEST_CASE_COUNT;
|
int progressCount = DATASETS_COUNT*TEST_CASE_COUNT;
|
||||||
vector< pair<DMatch, int> > allMatchings;
|
vector<DMatchForEvaluation> allMatches;
|
||||||
vector<int> allMatchStatuses;
|
|
||||||
size_t matchingIndex = 0;
|
|
||||||
int allCorrespCount = 0;
|
int allCorrespCount = 0;
|
||||||
for( int ci = 0; ci < TEST_CASE_COUNT; ci++ )
|
for( int ci = 0; ci < TEST_CASE_COUNT; ci++ )
|
||||||
{
|
{
|
||||||
@ -1428,43 +1447,38 @@ void DescriptorQualityTest::runDatasetTest (const vector<Mat> &imgs, const vecto
|
|||||||
readKeypoints( keypontsFS, keypoints2, ci+1 );
|
readKeypoints( keypontsFS, keypoints2, ci+1 );
|
||||||
transformToEllipticKeyPoints( keypoints2, ekeypoints2 );
|
transformToEllipticKeyPoints( keypoints2, ekeypoints2 );
|
||||||
descMatch->add( imgs[ci+1], keypoints2 );
|
descMatch->add( imgs[ci+1], keypoints2 );
|
||||||
vector<DMatch> matchings1to2;
|
vector<DMatch> matches1to2;
|
||||||
descMatch->match( imgs[0], keypoints1, matchings1to2 );
|
descMatch->match( imgs[0], keypoints1, matches1to2 );
|
||||||
vector< pair<DMatch, int> > matchings (matchings1to2.size());
|
vector<DMatchForEvaluation> matches ( matches1to2.size() );
|
||||||
for( size_t i=0;i<matchings1to2.size();i++ )
|
for( size_t i=0;i<matches1to2.size();i++)
|
||||||
matchings[i] = pair<DMatch, int>( matchings1to2[i], i);
|
{
|
||||||
|
matches[i].match = matches1to2[i];
|
||||||
|
}
|
||||||
|
|
||||||
// TODO if( commRunParams[di].matchFilter )
|
// TODO if( commRunParams[di].matchFilter )
|
||||||
int correspCount;
|
int correspCount;
|
||||||
int correctMatchCount = 0, falseMatchCount = 0;
|
int correctMatchCount = 0, falseMatchCount = 0;
|
||||||
vector<int> matchStatuses;
|
evaluateDescriptors( ekeypoints1, ekeypoints2, matches, imgs[0], imgs[ci+1], Hs[ci],
|
||||||
evaluateDescriptors( ekeypoints1, ekeypoints2, matchings, imgs[0], imgs[ci+1], Hs[ci],
|
correctMatchCount, falseMatchCount, correspCount );
|
||||||
correctMatchCount, falseMatchCount, matchStatuses, correspCount );
|
|
||||||
for( size_t i=0;i<matchings.size();i++ )
|
|
||||||
matchings[i].second += matchingIndex;
|
|
||||||
matchingIndex += matchings.size();
|
|
||||||
|
|
||||||
|
|
||||||
allCorrespCount += correspCount;
|
allCorrespCount += correspCount;
|
||||||
|
std::copy( matches.begin(), matches.end(), std::back_inserter( allMatches ) );
|
||||||
|
|
||||||
//TODO: use merge
|
//TODO: remove after testing
|
||||||
std::copy( matchings.begin(), matchings.end(), std::back_inserter( allMatchings ) );
|
//printf ("%d %d %d \n", correctMatchCount, falseMatchCount, correspCount );
|
||||||
std::copy( matchStatuses.begin(), matchStatuses.end(), std::back_inserter( allMatchStatuses ) );
|
|
||||||
|
|
||||||
printf ("%d %d %d \n", correctMatchCount, falseMatchCount, correspCount );
|
|
||||||
|
|
||||||
calcQuality[di][ci].recall = recall( correctMatchCount, correspCount );
|
calcQuality[di][ci].recall = recall( correctMatchCount, correspCount );
|
||||||
calcQuality[di][ci].precision = precision( correctMatchCount, falseMatchCount );
|
calcQuality[di][ci].precision = precision( correctMatchCount, falseMatchCount );
|
||||||
descMatch->clear ();
|
descMatch->clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
int correctMatchCount = 0, falseMatchCount = 0;
|
||||||
for( size_t i=0;i<allMatchings.size();i++)
|
for( size_t i=0;i<allMatches.size();i++)
|
||||||
{
|
{
|
||||||
if( allMatchStatuses[ allMatchings[i].second ] )
|
if( allMatches[i].isCorrect )
|
||||||
correctMatchCount++;
|
correctMatchCount++;
|
||||||
else
|
else
|
||||||
falseMatchCount++;
|
falseMatchCount++;
|
||||||
|
Loading…
Reference in New Issue
Block a user