Commit 276f3b88 authored by Ilya Lysenkov's avatar Ilya Lysenkov

Added distance threshold-based matching

parent f4dba468
...@@ -1573,9 +1573,9 @@ public: ...@@ -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: ...@@ -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: ...@@ -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, ...@@ -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: ...@@ -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 ...@@ -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: ...@@ -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();
...@@ -2039,7 +2126,9 @@ public: ...@@ -2039,7 +2126,9 @@ 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>& 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 );
...@@ -2105,6 +2194,14 @@ public: ...@@ -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 @@ ...@@ -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 ...@@ -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, ...@@ -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 ...@@ -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 )
......
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