#2245 Fix BFMatcher::radiusMatchImpl witch Hamming distance (thanks to Jukka Holappa)
This commit is contained in:
parent
456890e9e4
commit
36fe62d7a5
@ -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 );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user