Added distance threshold-based matching
This commit is contained in:
parent
f4dba4686d
commit
276f3b8862
@ -1573,9 +1573,9 @@ public:
|
|||||||
* Find the best match for each descriptor from a query set
|
* Find the best match for each descriptor from a query set
|
||||||
*
|
*
|
||||||
* query The query set of descriptors
|
* query The query set of descriptors
|
||||||
* matchings Matchings of the closest matches from the training set
|
* matches DMatches of the closest matches from the training set
|
||||||
*/
|
*/
|
||||||
void match( const Mat& query, vector<DMatch>& matchings ) const;
|
void match( const Mat& query, vector<DMatch>& matches ) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the best matches between two descriptor sets, with constraints
|
* Find the best matches between two descriptor sets, with constraints
|
||||||
@ -1586,10 +1586,36 @@ public:
|
|||||||
*
|
*
|
||||||
* query The query set of descriptors
|
* query The query set of descriptors
|
||||||
* mask Mask specifying permissible matches.
|
* mask Mask specifying permissible matches.
|
||||||
* matchings Matchings of the closest matches from the training set
|
* matches DMatches of the closest matches from the training set
|
||||||
*/
|
*/
|
||||||
void match( const Mat& query, const Mat& mask,
|
void match( const Mat& query, const Mat& mask,
|
||||||
vector<DMatch>& matchings ) const;
|
vector<DMatch>& matches ) const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find many matches for each descriptor from a query set
|
||||||
|
*
|
||||||
|
* query The query set of descriptors
|
||||||
|
* matches DMatches of the closest matches from the training set
|
||||||
|
* threshold Distance threshold for descriptors matching
|
||||||
|
*/
|
||||||
|
void match( const Mat& query, vector<vector<DMatch> >& matches, float threshold ) const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find many matches for each descriptor from a query set, with constraints
|
||||||
|
* on which pairs of descriptors can be matched.
|
||||||
|
*
|
||||||
|
* The mask describes which descriptors can be matched. descriptors_1[i]
|
||||||
|
* can be matched with descriptors_2[j] only if mask.at<char>(i,j) is non-zero.
|
||||||
|
*
|
||||||
|
* query The query set of descriptors
|
||||||
|
* mask Mask specifying permissible matches.
|
||||||
|
* matches DMatches of the closest matches from the training set
|
||||||
|
* threshold Distance threshold for descriptors matching
|
||||||
|
*/
|
||||||
|
void match( const Mat& query, const Mat& mask,
|
||||||
|
vector<vector<DMatch> >& matches, float threshold ) const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the best keypoint matches for small view changes.
|
* Find the best keypoint matches for small view changes.
|
||||||
@ -1627,6 +1653,10 @@ protected:
|
|||||||
virtual void matchImpl( const Mat& descriptors_1, const Mat& descriptors_2,
|
virtual void matchImpl( const Mat& descriptors_1, const Mat& descriptors_2,
|
||||||
const Mat& mask, vector<DMatch>& matches ) const = 0;
|
const Mat& mask, vector<DMatch>& matches ) const = 0;
|
||||||
|
|
||||||
|
virtual void matchImpl( const Mat& descriptors_1, const Mat& descriptors_2,
|
||||||
|
const Mat& mask, vector<vector<DMatch> >& matches, float threshold ) const = 0;
|
||||||
|
|
||||||
|
|
||||||
static bool possibleMatch( const Mat& mask, int index_1, int index_2 )
|
static bool possibleMatch( const Mat& mask, int index_1, int index_2 )
|
||||||
{
|
{
|
||||||
return mask.empty() || mask.at<char>(index_1, index_2);
|
return mask.empty() || mask.at<char>(index_1, index_2);
|
||||||
@ -1674,6 +1704,18 @@ inline void DescriptorMatcher::match( const Mat& query, const Mat& mask,
|
|||||||
matchImpl( query, train, mask, matches );
|
matchImpl( query, train, mask, matches );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void DescriptorMatcher::match( const Mat& query, vector<vector<DMatch> >& matches, float threshold ) const
|
||||||
|
{
|
||||||
|
matchImpl( query, train, Mat(), matches, threshold );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void DescriptorMatcher::match( const Mat& query, const Mat& mask,
|
||||||
|
vector<vector<DMatch> >& matches, float threshold ) const
|
||||||
|
{
|
||||||
|
matchImpl( query, train, mask, matches, threshold );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void DescriptorMatcher::clear()
|
inline void DescriptorMatcher::clear()
|
||||||
{
|
{
|
||||||
train.release();
|
train.release();
|
||||||
@ -1701,6 +1743,9 @@ protected:
|
|||||||
virtual void matchImpl( const Mat& descriptors_1, const Mat& descriptors_2,
|
virtual void matchImpl( const Mat& descriptors_1, const Mat& descriptors_2,
|
||||||
const Mat& mask, vector<DMatch>& matches ) const;
|
const Mat& mask, vector<DMatch>& matches ) const;
|
||||||
|
|
||||||
|
virtual void matchImpl( const Mat& descriptors_1, const Mat& descriptors_2,
|
||||||
|
const Mat& mask, vector<vector<DMatch> >& matches, float threshold ) const;
|
||||||
|
|
||||||
Distance distance;
|
Distance distance;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1764,6 +1809,46 @@ void BruteForceMatcher<Distance>::matchImpl( const Mat& descriptors_1, const Mat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Distance>
|
||||||
|
void BruteForceMatcher<Distance>::matchImpl( const Mat& descriptors_1, const Mat& descriptors_2,
|
||||||
|
const Mat& mask, vector<vector<DMatch> >& matches, float threshold ) const
|
||||||
|
{
|
||||||
|
typedef typename Distance::ValueType ValueType;
|
||||||
|
typedef typename Distance::ResultType DistanceType;
|
||||||
|
|
||||||
|
assert( mask.empty() || (mask.rows == descriptors_1.rows && mask.cols == descriptors_2.rows) );
|
||||||
|
|
||||||
|
assert( descriptors_1.cols == descriptors_2.cols || descriptors_1.empty() || descriptors_2.empty() );
|
||||||
|
assert( DataType<ValueType>::type == descriptors_1.type() || descriptors_1.empty() );
|
||||||
|
assert( DataType<ValueType>::type == descriptors_2.type() || descriptors_2.empty() );
|
||||||
|
|
||||||
|
int dimension = descriptors_1.cols;
|
||||||
|
matches.resize( descriptors_1.rows );
|
||||||
|
|
||||||
|
for( int i = 0; i < descriptors_1.rows; i++ )
|
||||||
|
{
|
||||||
|
const ValueType* d1 = descriptors_1.ptr<ValueType>(i);
|
||||||
|
|
||||||
|
for( int j = 0; j < descriptors_2.rows; j++ )
|
||||||
|
{
|
||||||
|
if( possibleMatch(mask, i, j) )
|
||||||
|
{
|
||||||
|
const ValueType* d2 = descriptors_2.ptr<ValueType>(j);
|
||||||
|
DistanceType curDistance = distance(d1, d2, dimension);
|
||||||
|
if( curDistance < threshold )
|
||||||
|
{
|
||||||
|
DMatch match;
|
||||||
|
match.distance = curDistance;
|
||||||
|
match.indexQuery = i;
|
||||||
|
match.indexTrain = j;
|
||||||
|
matches[i].push_back( match );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DescriptorMatcher* createDescriptorMatcher( const string& descriptorMatcherType );
|
DescriptorMatcher* createDescriptorMatcher( const string& descriptorMatcherType );
|
||||||
|
|
||||||
/****************************************************************************************\
|
/****************************************************************************************\
|
||||||
@ -1835,6 +1920,8 @@ public:
|
|||||||
// matches A vector to be filled with keypoint matches
|
// matches A vector to be filled with keypoint matches
|
||||||
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 ) {};
|
||||||
|
|
||||||
// Clears keypoints storing in collection
|
// Clears keypoints storing in collection
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
@ -2041,6 +2128,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);
|
||||||
|
|
||||||
virtual void classify( const Mat& image, vector<KeyPoint>& keypoints );
|
virtual void classify( const Mat& image, vector<KeyPoint>& keypoints );
|
||||||
|
|
||||||
virtual void clear ();
|
virtual void clear ();
|
||||||
@ -2105,6 +2194,14 @@ public:
|
|||||||
matcher.match( descriptors, matches );
|
matcher.match( descriptors, matches );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void match( const Mat& image, vector<KeyPoint>& points, vector<vector<DMatch> >& matches, float threshold )
|
||||||
|
{
|
||||||
|
Mat descriptors;
|
||||||
|
extractor.compute( image, points, descriptors );
|
||||||
|
|
||||||
|
matcher.match( descriptors, matches, threshold );
|
||||||
|
}
|
||||||
|
|
||||||
virtual void clear()
|
virtual void clear()
|
||||||
{
|
{
|
||||||
GenericDescriptorMatch::clear();
|
GenericDescriptorMatch::clear();
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
|
|
||||||
#include "precomp.hpp"
|
#include "precomp.hpp"
|
||||||
|
|
||||||
|
//#define _KDTREE
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
@ -439,21 +441,22 @@ void OneWayDescriptorMatch::match( const Mat& image, vector<KeyPoint>& points, v
|
|||||||
match( image, points, matchings );
|
match( image, points, matchings );
|
||||||
|
|
||||||
for( size_t i = 0; i < points.size(); i++ )
|
for( size_t i = 0; i < points.size(); i++ )
|
||||||
indices[i] = matchings[i].index;
|
indices[i] = matchings[i].indexTrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OneWayDescriptorMatch::match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matchings )
|
void OneWayDescriptorMatch::match( const Mat& image, vector<KeyPoint>& points, vector<DMatch>& matches )
|
||||||
{
|
{
|
||||||
matchings.resize( points.size() );
|
matches.resize( points.size() );
|
||||||
IplImage _image = image;
|
IplImage _image = image;
|
||||||
for( size_t i = 0; i < points.size(); i++ )
|
for( size_t i = 0; i < points.size(); i++ )
|
||||||
{
|
{
|
||||||
int poseIdx = -1;
|
int poseIdx = -1;
|
||||||
|
|
||||||
DMatch matching;
|
DMatch match;
|
||||||
matching.index = -1;
|
match.indexQuery = i;
|
||||||
base->FindDescriptor( &_image, points[i].pt, matching.index, poseIdx, matching.distance );
|
match.indexTrain = -1;
|
||||||
matchings[i] = matching;
|
base->FindDescriptor( &_image, points[i].pt, match.indexTrain, poseIdx, match.distance );
|
||||||
|
matches[i] = match;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,18 +747,45 @@ void FernDescriptorMatch::match( const Mat& image, vector<KeyPoint>& keypoints,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FernDescriptorMatch::match( const Mat& image, vector<KeyPoint>& keypoints, vector<DMatch>& matchings )
|
void FernDescriptorMatch::match( const Mat& image, vector<KeyPoint>& keypoints, vector<DMatch>& matches )
|
||||||
{
|
{
|
||||||
trainFernClassifier();
|
trainFernClassifier();
|
||||||
|
|
||||||
matchings.resize( keypoints.size() );
|
matches.resize( keypoints.size() );
|
||||||
vector<float> signature( (size_t)classifier->getClassCount() );
|
vector<float> signature( (size_t)classifier->getClassCount() );
|
||||||
|
|
||||||
for( size_t pi = 0; pi < keypoints.size(); pi++ )
|
for( size_t pi = 0; pi < keypoints.size(); pi++ )
|
||||||
{
|
{
|
||||||
calcBestProbAndMatchIdx( image, keypoints[pi].pt, matchings[pi].distance, matchings[pi].index, signature );
|
matches[pi].indexQuery = pi;
|
||||||
|
calcBestProbAndMatchIdx( image, keypoints[pi].pt, matches[pi].distance, matches[pi].indexTrain, signature );
|
||||||
//matching[pi].distance is log of probability so we need to transform it
|
//matching[pi].distance is log of probability so we need to transform it
|
||||||
matchings[pi].distance = -matchings[pi].distance;
|
matches[pi].distance = -matches[pi].distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FernDescriptorMatch::match( const Mat& image, vector<KeyPoint>& keypoints, vector<vector<DMatch> >& matches, float threshold )
|
||||||
|
{
|
||||||
|
trainFernClassifier();
|
||||||
|
|
||||||
|
matches.resize( keypoints.size() );
|
||||||
|
vector<float> signature( (size_t)classifier->getClassCount() );
|
||||||
|
|
||||||
|
for( size_t pi = 0; pi < keypoints.size(); pi++ )
|
||||||
|
{
|
||||||
|
(*classifier)( image, keypoints[pi].pt, signature);
|
||||||
|
|
||||||
|
DMatch match;
|
||||||
|
match.indexQuery = pi;
|
||||||
|
|
||||||
|
for( size_t ci = 0; ci < (size_t)classifier->getClassCount(); ci++ )
|
||||||
|
{
|
||||||
|
if( -signature[ci] < threshold )
|
||||||
|
{
|
||||||
|
match.distance = -signature[ci];
|
||||||
|
match.indexTrain = ci;
|
||||||
|
matches[pi].push_back( match );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1447,12 +1447,19 @@ 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> matches1to2;
|
vector<vector<DMatch> > matches1to2;
|
||||||
descMatch->match( imgs[0], keypoints1, matches1to2 );
|
descMatch->match( imgs[0], keypoints1, matches1to2, std::numeric_limits<float>::max() );
|
||||||
vector<DMatchForEvaluation> matches ( matches1to2.size() );
|
vector<DMatchForEvaluation> matches;
|
||||||
for( size_t i=0;i<matches1to2.size();i++)
|
for( size_t i=0;i<matches1to2.size();i++)
|
||||||
{
|
{
|
||||||
matches[i].match = matches1to2[i];
|
//TODO: use copy
|
||||||
|
for( size_t j=0;j<matches1to2[i].size();j++ )
|
||||||
|
{
|
||||||
|
DMatchForEvaluation match;
|
||||||
|
match.match = matches1to2[i][j];
|
||||||
|
matches.push_back( match );
|
||||||
|
//std::copy( matches1to2[i].begin(), matches1to2[i].end(), std::back_inserter( matches ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO if( commRunParams[di].matchFilter )
|
// TODO if( commRunParams[di].matchFilter )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user