#2245 Fix BFMatcher::radiusMatchImpl witch Hamming distance (thanks to Jukka Holappa)

This commit is contained in:
Andrey Kamaev 2012-08-15 15:02:20 +04:00
parent 456890e9e4
commit 36fe62d7a5

View File

@ -270,7 +270,7 @@ void DescriptorMatcher::knnMatch( const Mat& queryDescriptors, vector<vector<DMa
return; return;
CV_Assert( knn > 0 ); CV_Assert( knn > 0 );
checkMasks( masks, queryDescriptors.rows ); checkMasks( masks, queryDescriptors.rows );
train(); train();
@ -285,7 +285,7 @@ void DescriptorMatcher::radiusMatch( const Mat& queryDescriptors, vector<vector<
return; return;
CV_Assert( maxDistance > std::numeric_limits<float>::epsilon() ); CV_Assert( maxDistance > std::numeric_limits<float>::epsilon() );
checkMasks( masks, queryDescriptors.rows ); checkMasks( masks, queryDescriptors.rows );
train(); train();
@ -315,9 +315,9 @@ bool DescriptorMatcher::isMaskedOut( const vector<Mat>& masks, int queryIdx )
return !masks.empty() && outCount == masks.size() ; return !masks.empty() && outCount == masks.size() ;
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////
BFMatcher::BFMatcher( int _normType, bool _crossCheck ) BFMatcher::BFMatcher( int _normType, bool _crossCheck )
{ {
normType = _normType; normType = _normType;
@ -342,24 +342,24 @@ void BFMatcher::knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch>
{ {
const int IMGIDX_SHIFT = 18; const int IMGIDX_SHIFT = 18;
const int IMGIDX_ONE = (1 << IMGIDX_SHIFT); const int IMGIDX_ONE = (1 << IMGIDX_SHIFT);
if( queryDescriptors.empty() || trainDescCollection.empty() ) if( queryDescriptors.empty() || trainDescCollection.empty() )
{ {
matches.clear(); matches.clear();
return; return;
} }
CV_Assert( queryDescriptors.type() == trainDescCollection[0].type() ); CV_Assert( queryDescriptors.type() == trainDescCollection[0].type() );
matches.reserve(queryDescriptors.rows); matches.reserve(queryDescriptors.rows);
Mat dist, nidx; Mat dist, nidx;
int iIdx, imgCount = (int)trainDescCollection.size(), update = 0; int iIdx, imgCount = (int)trainDescCollection.size(), update = 0;
int dtype = normType == NORM_HAMMING || normType == NORM_HAMMING2 || int dtype = normType == NORM_HAMMING || normType == NORM_HAMMING2 ||
(normType == NORM_L1 && queryDescriptors.type() == CV_8U) ? CV_32S : CV_32F; (normType == NORM_L1 && queryDescriptors.type() == CV_8U) ? CV_32S : CV_32F;
CV_Assert( (int64)imgCount*IMGIDX_ONE < INT_MAX ); CV_Assert( (int64)imgCount*IMGIDX_ONE < INT_MAX );
for( iIdx = 0; iIdx < imgCount; iIdx++ ) for( iIdx = 0; iIdx < imgCount; iIdx++ )
{ {
CV_Assert( trainDescCollection[iIdx].rows < IMGIDX_ONE ); CV_Assert( trainDescCollection[iIdx].rows < IMGIDX_ONE );
@ -367,23 +367,23 @@ void BFMatcher::knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch>
normType, knn, masks.empty() ? Mat() : masks[iIdx], update, crossCheck); normType, knn, masks.empty() ? Mat() : masks[iIdx], update, crossCheck);
update += IMGIDX_ONE; update += IMGIDX_ONE;
} }
if( dtype == CV_32S ) if( dtype == CV_32S )
{ {
Mat temp; Mat temp;
dist.convertTo(temp, CV_32F); dist.convertTo(temp, CV_32F);
dist = temp; dist = temp;
} }
for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ ) for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
{ {
const float* distptr = dist.ptr<float>(qIdx); const float* distptr = dist.ptr<float>(qIdx);
const int* nidxptr = nidx.ptr<int>(qIdx); const int* nidxptr = nidx.ptr<int>(qIdx);
matches.push_back( vector<DMatch>() ); matches.push_back( vector<DMatch>() );
vector<DMatch>& mq = matches.back(); vector<DMatch>& mq = matches.back();
mq.reserve(knn); mq.reserve(knn);
for( int k = 0; k < nidx.cols; k++ ) for( int k = 0; k < nidx.cols; k++ )
{ {
if( nidxptr[k] < 0 ) if( nidxptr[k] < 0 )
@ -391,13 +391,13 @@ void BFMatcher::knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch>
mq.push_back( DMatch(qIdx, nidxptr[k] & (IMGIDX_ONE - 1), mq.push_back( DMatch(qIdx, nidxptr[k] & (IMGIDX_ONE - 1),
nidxptr[k] >> IMGIDX_SHIFT, distptr[k]) ); nidxptr[k] >> IMGIDX_SHIFT, distptr[k]) );
} }
if( mq.empty() && compactResult ) if( mq.empty() && compactResult )
matches.pop_back(); matches.pop_back();
} }
} }
void BFMatcher::radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, void BFMatcher::radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches,
float maxDistance, const vector<Mat>& masks, bool compactResult ) float maxDistance, const vector<Mat>& masks, bool compactResult )
{ {
@ -407,14 +407,14 @@ void BFMatcher::radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMat
return; return;
} }
CV_Assert( queryDescriptors.type() == trainDescCollection[0].type() ); CV_Assert( queryDescriptors.type() == trainDescCollection[0].type() );
matches.resize(queryDescriptors.rows); matches.resize(queryDescriptors.rows);
Mat dist, distf; Mat dist, distf;
int iIdx, imgCount = (int)trainDescCollection.size(); int iIdx, imgCount = (int)trainDescCollection.size();
int dtype = normType == NORM_HAMMING || int dtype = normType == NORM_HAMMING ||
(normType == NORM_L1 && queryDescriptors.type() == CV_8U) ? CV_32S : CV_32F; (normType == NORM_L1 && queryDescriptors.type() == CV_8U) ? CV_32S : CV_32F;
for( iIdx = 0; iIdx < imgCount; iIdx++ ) for( iIdx = 0; iIdx < imgCount; iIdx++ )
{ {
batchDistance(queryDescriptors, trainDescCollection[iIdx], dist, dtype, noArray(), batchDistance(queryDescriptors, trainDescCollection[iIdx], dist, dtype, noArray(),
@ -423,36 +423,36 @@ void BFMatcher::radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMat
dist.convertTo(distf, CV_32F); dist.convertTo(distf, CV_32F);
else else
distf = dist; distf = dist;
for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ ) for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
{ {
const float* distptr = dist.ptr<float>(qIdx); const float* distptr = distf.ptr<float>(qIdx);
vector<DMatch>& mq = matches[qIdx]; vector<DMatch>& mq = matches[qIdx];
for( int k = 0; k < dist.cols; k++ ) for( int k = 0; k < distf.cols; k++ )
{ {
if( distptr[k] <= maxDistance ) if( distptr[k] <= maxDistance )
mq.push_back( DMatch(qIdx, k, iIdx, distptr[k]) ); mq.push_back( DMatch(qIdx, k, iIdx, distptr[k]) );
} }
} }
} }
int qIdx0 = 0; int qIdx0 = 0;
for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ ) for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
{ {
if( matches[qIdx].empty() && compactResult ) if( matches[qIdx].empty() && compactResult )
continue; continue;
if( qIdx0 < qIdx ) if( qIdx0 < qIdx )
std::swap(matches[qIdx], matches[qIdx0]); std::swap(matches[qIdx], matches[qIdx0]);
std::sort( matches[qIdx0].begin(), matches[qIdx0].end() ); std::sort( matches[qIdx0].begin(), matches[qIdx0].end() );
qIdx0++; qIdx0++;
} }
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////
/* /*
* Factory function for DescriptorMatcher creating * Factory function for DescriptorMatcher creating
*/ */
@ -1025,7 +1025,7 @@ void GenericDescriptorMatcher::knnMatch( const Mat& queryImage, vector<KeyPoint>
KeyPointsFilter::runByImageBorder( queryKeypoints, queryImage.size(), 0 ); KeyPointsFilter::runByImageBorder( queryKeypoints, queryImage.size(), 0 );
KeyPointsFilter::runByKeypointSize( queryKeypoints, std::numeric_limits<float>::epsilon() ); KeyPointsFilter::runByKeypointSize( queryKeypoints, std::numeric_limits<float>::epsilon() );
train(); train();
knnMatchImpl( queryImage, queryKeypoints, matches, knn, masks, compactResult ); knnMatchImpl( queryImage, queryKeypoints, matches, knn, masks, compactResult );
} }
@ -1041,7 +1041,7 @@ void GenericDescriptorMatcher::radiusMatch( const Mat& queryImage, vector<KeyPoi
KeyPointsFilter::runByImageBorder( queryKeypoints, queryImage.size(), 0 ); KeyPointsFilter::runByImageBorder( queryKeypoints, queryImage.size(), 0 );
KeyPointsFilter::runByKeypointSize( queryKeypoints, std::numeric_limits<float>::epsilon() ); KeyPointsFilter::runByKeypointSize( queryKeypoints, std::numeric_limits<float>::epsilon() );
train(); train();
radiusMatchImpl( queryImage, queryKeypoints, matches, maxDistance, masks, compactResult ); radiusMatchImpl( queryImage, queryKeypoints, matches, maxDistance, masks, compactResult );
} }
@ -1065,7 +1065,7 @@ Ptr<GenericDescriptorMatcher> GenericDescriptorMatcher::create( const string& ge
{ {
Ptr<GenericDescriptorMatcher> descriptorMatcher = Ptr<GenericDescriptorMatcher> descriptorMatcher =
Algorithm::create<GenericDescriptorMatcher>("DescriptorMatcher." + genericDescritptorMatcherType); Algorithm::create<GenericDescriptorMatcher>("DescriptorMatcher." + genericDescritptorMatcherType);
if( !paramsFilename.empty() && !descriptorMatcher.empty() ) if( !paramsFilename.empty() && !descriptorMatcher.empty() )
{ {
FileStorage fs = FileStorage( paramsFilename, FileStorage::READ ); FileStorage fs = FileStorage( paramsFilename, FileStorage::READ );