template<class Distance> inline
void BruteForceMatcher<Distance>::matchImpl( const Mat& query, const Mat& mask, vector<int>& matches ) const
{
- vector<DMatch> matchings;
- matchImpl( query, mask, matchings);
+ vector<DMatch> fullMatches;
+ matchImpl( query, mask, fullMatches);
matches.clear();
- matches.resize( matchings.size() );
- for( size_t i=0;i<matchings.size();i++)
+ matches.resize( fullMatches.size() );
+ for( size_t i=0;i<fullMatches.size();i++)
{
- matches[i] = matchings[i].indexTrain;
+ matches[i] = fullMatches[i].indexTrain;
}
}
int dimension = query.cols;
matches.clear();
- matches.resize(query.rows);
+ matches.reserve(query.rows);
for( int i = 0; i < query.rows; i++ )
{
match.indexTrain = matchIndex;
match.indexQuery = i;
match.distance = matchDistance;
- matches[i] = match;
+ matches.push_back( match );
}
}
}
}
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 );
* BruteForceMatcher L2 specialization *
\****************************************************************************************/
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.reserve( query.rows );
#if (!defined HAVE_EIGEN2)
{
Mat distances = (-2)*query.row(i)*desc_2t;
distances += norms;
+ DMatch match;
+ match.indexTrain = -1;
+ double minVal;
Point minLoc;
- minMaxLoc ( distances, 0, 0, &minLoc );
- matches.push_back( minLoc.x );
+ if( mask.empty() )
+ {
+ 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
cv2eigen( query.t(), desc1t);
cv2eigen( train, desc2 );
- //Eigen::Matrix<float, Eigen::Dynamic, 1> norms = desc2.rowwise().squaredNorm();
Eigen::Matrix<float, Eigen::Dynamic, 1> norms = desc2.rowwise().squaredNorm() / 2;
- for( int i=0;i<query.rows;i++ )
- {
- //Eigen::Matrix<float, Eigen::Dynamic, 1> distances = (-2) * (desc2*desc1t.col(i));
- Eigen::Matrix<float, Eigen::Dynamic, 1> distances = desc2*desc1t.col(i);
- //distances += norms;
- distances -= norms;
+ if( mask.empty() )
+ {
+ for( int i=0;i<query.rows;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;
- int idx;
+ float maxCoeff = -std::numeric_limits<float>::max();
+ 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;
+ }
+ }
- //distances.minCoeff(&idx);
- distances.maxCoeff(&idx);
- matches.push_back( idx );
+ if( match.indexTrain != -1 )
+ {
+ match.indexQuery = i;
+ match.distance = sqrt( (-2)*maxCoeff + desc1t.col(i).squaredNorm() );
+ matches.push_back( match );
+ }
+ }
}
#endif
}
for( int i=0;i<descriptorsNumber;i++ )
permutation.at<int>( 0, i ) = i;
- RNG rng (cvGetTickCount());
+ //RNG rng = RNG( cvGetTickCount() );
+ RNG rng = RNG( *ts->get_rng() );
randShuffle( permutation, 1, &rng );
float boundary = 500.f;
}
}
- vector<int> specMatches, genericMatches;
+ vector<DMatch> specMatches, genericMatches;
BruteForceMatcher<L2<float> > specMatcher;
BruteForceMatcher<L2Fake > genericMatcher;
specMatcher.add( train );
ts->set_failed_test_info( CvTS::FAIL_INVALID_OUTPUT );
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 );
break;