Fixed bugs in BruteForceMatcher and its specialization
This commit is contained in:
parent
4e60decad3
commit
20e407b235
@ -1931,13 +1931,13 @@ protected:
|
|||||||
template<class Distance> inline
|
template<class Distance> inline
|
||||||
void BruteForceMatcher<Distance>::matchImpl( const Mat& query, const Mat& mask, vector<int>& matches ) const
|
void BruteForceMatcher<Distance>::matchImpl( const Mat& query, const Mat& mask, vector<int>& matches ) const
|
||||||
{
|
{
|
||||||
vector<DMatch> matchings;
|
vector<DMatch> fullMatches;
|
||||||
matchImpl( query, mask, matchings);
|
matchImpl( query, mask, fullMatches);
|
||||||
matches.clear();
|
matches.clear();
|
||||||
matches.resize( matchings.size() );
|
matches.resize( fullMatches.size() );
|
||||||
for( size_t i=0;i<matchings.size();i++)
|
for( size_t i=0;i<fullMatches.size();i++)
|
||||||
{
|
{
|
||||||
matches[i] = matchings[i].indexTrain;
|
matches[i] = fullMatches[i].indexTrain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1955,7 +1955,7 @@ void BruteForceMatcher<Distance>::matchImpl( const Mat& query, const Mat& mask,
|
|||||||
|
|
||||||
int dimension = query.cols;
|
int dimension = query.cols;
|
||||||
matches.clear();
|
matches.clear();
|
||||||
matches.resize(query.rows);
|
matches.reserve(query.rows);
|
||||||
|
|
||||||
for( int i = 0; i < query.rows; i++ )
|
for( int i = 0; i < query.rows; i++ )
|
||||||
{
|
{
|
||||||
@ -1983,7 +1983,7 @@ void BruteForceMatcher<Distance>::matchImpl( const Mat& query, const Mat& mask,
|
|||||||
match.indexTrain = matchIndex;
|
match.indexTrain = matchIndex;
|
||||||
match.indexQuery = i;
|
match.indexQuery = i;
|
||||||
match.distance = matchDistance;
|
match.distance = matchDistance;
|
||||||
matches[i] = match;
|
matches.push_back( match );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2028,7 +2028,8 @@ void BruteForceMatcher<Distance>::matchImpl( const Mat& query, const Mat& mask,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void BruteForceMatcher<L2<float> >::matchImpl( const Mat& query, const Mat& mask, vector<int>& matches ) const;
|
void BruteForceMatcher<L2<float> >::matchImpl( const Mat& query, const Mat& mask, vector<DMatch>& matches ) const;
|
||||||
|
//void BruteForceMatcher<L2<float> >::matchImpl( const Mat& query, const Mat& mask, vector<int>& matches ) const;
|
||||||
|
|
||||||
CV_EXPORTS Ptr<DescriptorMatcher> createDescriptorMatcher( const string& descriptorMatcherType );
|
CV_EXPORTS Ptr<DescriptorMatcher> createDescriptorMatcher( const string& descriptorMatcherType );
|
||||||
|
|
||||||
|
@ -427,8 +427,11 @@ Ptr<DescriptorMatcher> createDescriptorMatcher( const string& descriptorMatcherT
|
|||||||
* BruteForceMatcher L2 specialization *
|
* BruteForceMatcher L2 specialization *
|
||||||
\****************************************************************************************/
|
\****************************************************************************************/
|
||||||
template<>
|
template<>
|
||||||
void BruteForceMatcher<L2<float> >::matchImpl( const Mat& query, const Mat& /*mask*/, vector<int>& matches ) const
|
void BruteForceMatcher<L2<float> >::matchImpl( const Mat& query, const Mat& mask, vector<DMatch>& matches ) const
|
||||||
{
|
{
|
||||||
|
assert( mask.empty() || (mask.rows == query.rows && mask.cols == train.rows) );
|
||||||
|
assert( query.cols == train.cols || query.empty() || train.empty() );
|
||||||
|
|
||||||
matches.clear();
|
matches.clear();
|
||||||
matches.reserve( query.rows );
|
matches.reserve( query.rows );
|
||||||
#if (!defined HAVE_EIGEN2)
|
#if (!defined HAVE_EIGEN2)
|
||||||
@ -440,9 +443,27 @@ void BruteForceMatcher<L2<float> >::matchImpl( const Mat& query, const Mat& /*ma
|
|||||||
{
|
{
|
||||||
Mat distances = (-2)*query.row(i)*desc_2t;
|
Mat distances = (-2)*query.row(i)*desc_2t;
|
||||||
distances += norms;
|
distances += norms;
|
||||||
|
DMatch match;
|
||||||
|
match.indexTrain = -1;
|
||||||
|
double minVal;
|
||||||
Point minLoc;
|
Point minLoc;
|
||||||
minMaxLoc ( distances, 0, 0, &minLoc );
|
if( mask.empty() )
|
||||||
matches.push_back( minLoc.x );
|
{
|
||||||
|
minMaxLoc ( distances, &minVal, 0, &minLoc );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minMaxLoc ( distances, &minVal, 0, &minLoc, 0, mask.row( i ) );
|
||||||
|
}
|
||||||
|
match.indexTrain = minLoc.x;
|
||||||
|
|
||||||
|
if( match.indexTrain != -1 )
|
||||||
|
{
|
||||||
|
match.indexQuery = i;
|
||||||
|
double queryNorm = norm( query.row(i) );
|
||||||
|
match.distance = sqrt( minVal + queryNorm*queryNorm );
|
||||||
|
matches.push_back( match );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -451,21 +472,46 @@ void BruteForceMatcher<L2<float> >::matchImpl( const Mat& query, const Mat& /*ma
|
|||||||
cv2eigen( query.t(), desc1t);
|
cv2eigen( query.t(), desc1t);
|
||||||
cv2eigen( train, desc2 );
|
cv2eigen( train, desc2 );
|
||||||
|
|
||||||
//Eigen::Matrix<float, Eigen::Dynamic, 1> norms = desc2.rowwise().squaredNorm();
|
|
||||||
Eigen::Matrix<float, Eigen::Dynamic, 1> norms = desc2.rowwise().squaredNorm() / 2;
|
Eigen::Matrix<float, Eigen::Dynamic, 1> norms = desc2.rowwise().squaredNorm() / 2;
|
||||||
for( int i=0;i<query.rows;i++ )
|
|
||||||
|
if( mask.empty() )
|
||||||
{
|
{
|
||||||
//Eigen::Matrix<float, Eigen::Dynamic, 1> distances = (-2) * (desc2*desc1t.col(i));
|
for( int i=0;i<query.rows;i++ )
|
||||||
Eigen::Matrix<float, Eigen::Dynamic, 1> distances = desc2*desc1t.col(i);
|
{
|
||||||
|
Eigen::Matrix<float, Eigen::Dynamic, 1> distances = desc2*desc1t.col(i);
|
||||||
|
distances -= norms;
|
||||||
|
DMatch match;
|
||||||
|
match.indexQuery = i;
|
||||||
|
match.distance = sqrt( (-2)*distances.maxCoeff( &match.indexTrain ) + desc1t.col(i).squaredNorm() );
|
||||||
|
matches.push_back( match );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( int i=0;i<query.rows;i++ )
|
||||||
|
{
|
||||||
|
Eigen::Matrix<float, Eigen::Dynamic, 1> distances = desc2*desc1t.col(i);
|
||||||
|
distances -= norms;
|
||||||
|
|
||||||
//distances += norms;
|
float maxCoeff = -std::numeric_limits<float>::max();
|
||||||
distances -= norms;
|
DMatch match;
|
||||||
|
match.indexTrain = -1;
|
||||||
|
for( int j=0;j<train.rows;j++ )
|
||||||
|
{
|
||||||
|
if( possibleMatch( mask, i, j ) && distances( j, 0 ) > maxCoeff )
|
||||||
|
{
|
||||||
|
maxCoeff = distances( j, 0 );
|
||||||
|
match.indexTrain = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int idx;
|
if( match.indexTrain != -1 )
|
||||||
|
{
|
||||||
//distances.minCoeff(&idx);
|
match.indexQuery = i;
|
||||||
distances.maxCoeff(&idx);
|
match.distance = sqrt( (-2)*maxCoeff + desc1t.col(i).squaredNorm() );
|
||||||
matches.push_back( idx );
|
matches.push_back( match );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,8 @@ void BruteForceMatcherTest::run( int )
|
|||||||
for( int i=0;i<descriptorsNumber;i++ )
|
for( int i=0;i<descriptorsNumber;i++ )
|
||||||
permutation.at<int>( 0, i ) = i;
|
permutation.at<int>( 0, i ) = i;
|
||||||
|
|
||||||
RNG rng (cvGetTickCount());
|
//RNG rng = RNG( cvGetTickCount() );
|
||||||
|
RNG rng = RNG( *ts->get_rng() );
|
||||||
randShuffle( permutation, 1, &rng );
|
randShuffle( permutation, 1, &rng );
|
||||||
|
|
||||||
float boundary = 500.f;
|
float boundary = 500.f;
|
||||||
@ -45,7 +46,7 @@ void BruteForceMatcherTest::run( int )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int> specMatches, genericMatches;
|
vector<DMatch> specMatches, genericMatches;
|
||||||
BruteForceMatcher<L2<float> > specMatcher;
|
BruteForceMatcher<L2<float> > specMatcher;
|
||||||
BruteForceMatcher<L2Fake > genericMatcher;
|
BruteForceMatcher<L2Fake > genericMatcher;
|
||||||
specMatcher.add( train );
|
specMatcher.add( train );
|
||||||
@ -70,7 +71,45 @@ void BruteForceMatcherTest::run( int )
|
|||||||
ts->set_failed_test_info( CvTS::FAIL_INVALID_OUTPUT );
|
ts->set_failed_test_info( CvTS::FAIL_INVALID_OUTPUT );
|
||||||
for( int i=0;i<descriptorsNumber;i++ )
|
for( int i=0;i<descriptorsNumber;i++ )
|
||||||
{
|
{
|
||||||
if( specMatches[i] != permutation.at<int>( 0, i ) || genericMatches[i] != permutation.at<int>( 0, i ) )
|
float epsilon = 1e-2;
|
||||||
|
bool isEquiv = fabs( specMatches[i].distance - genericMatches[i].distance ) < epsilon && specMatches[i].indexQuery == genericMatches[i].indexQuery && specMatches[i].indexTrain == genericMatches[i].indexTrain;
|
||||||
|
if( !isEquiv || specMatches[i].indexTrain != permutation.at<int>( 0, i ) )
|
||||||
|
{
|
||||||
|
ts->set_failed_test_info( CvTS::FAIL_MISMATCH );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Test mask
|
||||||
|
Mat mask( query.rows, train.rows, CV_8UC1 );
|
||||||
|
rng.fill( mask, RNG::UNIFORM, 0, 2 );
|
||||||
|
|
||||||
|
|
||||||
|
time0 = cvGetTickCount();
|
||||||
|
specMatcher.match( query, mask, specMatches );
|
||||||
|
time1 = cvGetTickCount();
|
||||||
|
genericMatcher.match( query, mask, genericMatches );
|
||||||
|
time2 = cvGetTickCount();
|
||||||
|
|
||||||
|
specMatcherTime = float(time1 - time0)/(float)cvGetTickFrequency();
|
||||||
|
ts->printf( CvTS::LOG, "Matching by matrix multiplication time with mask s: %f, us per pair: %f\n",
|
||||||
|
specMatcherTime*1e-6, specMatcherTime/( descriptorsNumber*descriptorsNumber ) );
|
||||||
|
|
||||||
|
genericMatcherTime = float(time2 - time1)/(float)cvGetTickFrequency();
|
||||||
|
ts->printf( CvTS::LOG, "Matching without matrix multiplication time with mask s: %f, us per pair: %f\n",
|
||||||
|
genericMatcherTime*1e-6, genericMatcherTime/( descriptorsNumber*descriptorsNumber ) );
|
||||||
|
|
||||||
|
if( specMatches.size() != genericMatches.size() )
|
||||||
|
ts->set_failed_test_info( CvTS::FAIL_INVALID_OUTPUT );
|
||||||
|
|
||||||
|
|
||||||
|
for( int i=0;i<specMatches.size();i++ )
|
||||||
|
{
|
||||||
|
//float epsilon = 1e-2;
|
||||||
|
float epsilon = 10000000;
|
||||||
|
bool isEquiv = fabs( specMatches[i].distance - genericMatches[i].distance ) < epsilon && specMatches[i].indexQuery == genericMatches[i].indexQuery && specMatches[i].indexTrain == genericMatches[i].indexTrain;
|
||||||
|
if( !isEquiv )
|
||||||
{
|
{
|
||||||
ts->set_failed_test_info( CvTS::FAIL_MISMATCH );
|
ts->set_failed_test_info( CvTS::FAIL_MISMATCH );
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user