mirror of
https://github.com/opencv/opencv.git
synced 2024-11-28 05:06:29 +08:00
added the filtering of keypoints having zero size (#877)
This commit is contained in:
parent
d3aa228073
commit
b9662e099c
@ -263,6 +263,26 @@ CV_EXPORTS void write(FileStorage& fs, const string& name, const vector<KeyPoint
|
||||
//! reads vector of keypoints from the specified file storage node
|
||||
CV_EXPORTS void read(const FileNode& node, CV_OUT vector<KeyPoint>& keypoints);
|
||||
|
||||
/*
|
||||
* A class filters a vector of keypoints.
|
||||
* Because now it is difficult to provide a convenient interface for all usage scenarios of the keypoints filter class,
|
||||
* it has only 2 needed by now static methods.
|
||||
*/
|
||||
class CV_EXPORTS KeyPointsFilter
|
||||
{
|
||||
public:
|
||||
KeyPointsFilter(){}
|
||||
|
||||
/*
|
||||
* Remove keypoints within borderPixels of an image edge.
|
||||
*/
|
||||
static void runByImageBorder( vector<KeyPoint>& keypoints, Size imageSize, int borderSize );
|
||||
/*
|
||||
* Remove keypoints of sizes out of range.
|
||||
*/
|
||||
static void runByKeypointSize( vector<KeyPoint>& keypoints, float minSize, float maxSize=std::numeric_limits<float>::max() );
|
||||
};
|
||||
|
||||
/*!
|
||||
SIFT implementation.
|
||||
|
||||
@ -1624,13 +1644,7 @@ public:
|
||||
static Ptr<DescriptorExtractor> create( const string& descriptorExtractorType );
|
||||
|
||||
protected:
|
||||
virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const = 0;
|
||||
|
||||
/*
|
||||
* Remove keypoints within borderPixels of an image edge.
|
||||
*/
|
||||
static void removeBorderKeypoints( vector<KeyPoint>& keypoints,
|
||||
Size imageSize, int borderSize );
|
||||
virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1715,7 +1729,7 @@ void CalonderDescriptorExtractor<T>::computeImpl( const cv::Mat& image,
|
||||
cv::Mat& descriptors) const
|
||||
{
|
||||
// Cannot compute descriptors for keypoints on the image border.
|
||||
removeBorderKeypoints(keypoints, image.size(), BORDER_SIZE);
|
||||
KeyPointsFilter::runByImageBorder(keypoints, image.size(), BORDER_SIZE);
|
||||
|
||||
/// @todo Check 16-byte aligned
|
||||
descriptors.create(keypoints.size(), classifier_.classes(), cv::DataType<T>::type);
|
||||
|
@ -208,7 +208,7 @@ void BriefDescriptorExtractor::computeImpl(const Mat& image, std::vector<KeyPoin
|
||||
integral( grayImage, sum, CV_32S);
|
||||
|
||||
//Remove keypoints very close to the border
|
||||
removeBorderKeypoints(keypoints, image.size(), PATCH_SIZE/2 + KERNEL_SIZE/2);
|
||||
KeyPointsFilter::runByImageBorder(keypoints, image.size(), PATCH_SIZE/2 + KERNEL_SIZE/2);
|
||||
|
||||
descriptors = Mat::zeros((int)keypoints.size(), bytes_, CV_8U);
|
||||
test_fn_(sum, keypoints, descriptors);
|
||||
|
@ -52,30 +52,20 @@ namespace cv
|
||||
/*
|
||||
* DescriptorExtractor
|
||||
*/
|
||||
struct RoiPredicate
|
||||
{
|
||||
RoiPredicate( const Rect& _r ) : r(_r)
|
||||
{}
|
||||
|
||||
bool operator()( const KeyPoint& keyPt ) const
|
||||
{
|
||||
return !r.contains( keyPt.pt );
|
||||
}
|
||||
|
||||
Rect r;
|
||||
};
|
||||
|
||||
DescriptorExtractor::~DescriptorExtractor()
|
||||
{}
|
||||
|
||||
void DescriptorExtractor::compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const
|
||||
{
|
||||
{
|
||||
if( image.empty() || keypoints.empty() )
|
||||
return;
|
||||
{
|
||||
descriptors.release();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check keypoints are in image. Do filter bad points here?
|
||||
//for( size_t i = 0; i < keypoints.size(); i++ )
|
||||
// CV_Assert( Rect(0,0, image.cols, image.rows).contains(keypoints[i].pt) );
|
||||
|
||||
KeyPointsFilter::runByImageBorder( keypoints, image.size(), 0 );
|
||||
KeyPointsFilter::runByKeypointSize( keypoints, std::numeric_limits<float>::epsilon() );
|
||||
|
||||
computeImpl( image, keypoints, descriptors );
|
||||
}
|
||||
@ -99,18 +89,6 @@ bool DescriptorExtractor::empty() const
|
||||
return false;
|
||||
}
|
||||
|
||||
void DescriptorExtractor::removeBorderKeypoints( vector<KeyPoint>& keypoints,
|
||||
Size imageSize, int borderSize )
|
||||
{
|
||||
if( borderSize > 0)
|
||||
{
|
||||
keypoints.erase( remove_if(keypoints.begin(), keypoints.end(),
|
||||
RoiPredicate(Rect(Point(borderSize, borderSize),
|
||||
Point(imageSize.width - borderSize, imageSize.height - borderSize)))),
|
||||
keypoints.end() );
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<DescriptorExtractor> DescriptorExtractor::create(const string& descriptorExtractorType)
|
||||
{
|
||||
DescriptorExtractor* de = 0;
|
||||
|
@ -65,14 +65,14 @@ FeatureDetector::~FeatureDetector()
|
||||
|
||||
void FeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
|
||||
{
|
||||
keypoints.clear();
|
||||
keypoints.clear();
|
||||
|
||||
if( image.empty() )
|
||||
return;
|
||||
if( image.empty() )
|
||||
return;
|
||||
|
||||
CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) );
|
||||
CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) );
|
||||
|
||||
detectImpl( image, keypoints, mask );
|
||||
detectImpl( image, keypoints, mask );
|
||||
}
|
||||
|
||||
void FeatureDetector::detect(const vector<Mat>& imageCollection, vector<vector<KeyPoint> >& pointCollection, const vector<Mat>& masks ) const
|
||||
|
@ -152,4 +152,52 @@ float KeyPoint::overlap( const KeyPoint& kp1, const KeyPoint& kp2 )
|
||||
return ovrl;
|
||||
}
|
||||
|
||||
struct RoiPredicate
|
||||
{
|
||||
RoiPredicate( const Rect& _r ) : r(_r)
|
||||
{}
|
||||
|
||||
bool operator()( const KeyPoint& keyPt ) const
|
||||
{
|
||||
return !r.contains( keyPt.pt );
|
||||
}
|
||||
|
||||
Rect r;
|
||||
};
|
||||
|
||||
void KeyPointsFilter::runByImageBorder( vector<KeyPoint>& keypoints, Size imageSize, int borderSize )
|
||||
{
|
||||
if( borderSize > 0)
|
||||
{
|
||||
keypoints.erase( remove_if(keypoints.begin(), keypoints.end(),
|
||||
RoiPredicate(Rect(Point(borderSize, borderSize),
|
||||
Point(imageSize.width - borderSize, imageSize.height - borderSize)))),
|
||||
keypoints.end() );
|
||||
}
|
||||
}
|
||||
|
||||
struct SizePredicate
|
||||
{
|
||||
SizePredicate( float _minSize, float _maxSize ) : minSize(_minSize), maxSize(_maxSize)
|
||||
{}
|
||||
|
||||
bool operator()( const KeyPoint& keyPt ) const
|
||||
{
|
||||
float size = keyPt.size;
|
||||
return (size < minSize) || (size > maxSize);
|
||||
}
|
||||
|
||||
float minSize, maxSize;
|
||||
};
|
||||
|
||||
void KeyPointsFilter::runByKeypointSize( vector<KeyPoint>& keypoints, float minSize, float maxSize )
|
||||
{
|
||||
CV_Assert( minSize >= 0 );
|
||||
CV_Assert( maxSize >= 0);
|
||||
CV_Assert( minSize <= maxSize );
|
||||
|
||||
keypoints.erase( remove_if(keypoints.begin(), keypoints.end(), SizePredicate(minSize, maxSize)),
|
||||
keypoints.end() );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -244,21 +244,21 @@ void DescriptorMatcher::match( const Mat& queryDescriptors, vector<DMatch>& matc
|
||||
|
||||
void DescriptorMatcher::checkMasks( const vector<Mat>& masks, int queryDescriptorsCount ) const
|
||||
{
|
||||
if( isMaskSupported() && !masks.empty() )
|
||||
{
|
||||
// Check masks
|
||||
size_t imageCount = trainDescCollection.size();
|
||||
CV_Assert( masks.size() == imageCount );
|
||||
for( size_t i = 0; i < imageCount; i++ )
|
||||
{
|
||||
if( !masks[i].empty() && !trainDescCollection[i].empty() )
|
||||
{
|
||||
CV_Assert( masks[i].rows == queryDescriptorsCount &&
|
||||
masks[i].cols == trainDescCollection[i].rows &&
|
||||
masks[i].type() == CV_8UC1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
if( isMaskSupported() && !masks.empty() )
|
||||
{
|
||||
// Check masks
|
||||
size_t imageCount = trainDescCollection.size();
|
||||
CV_Assert( masks.size() == imageCount );
|
||||
for( size_t i = 0; i < imageCount; i++ )
|
||||
{
|
||||
if( !masks[i].empty() && !trainDescCollection[i].empty() )
|
||||
{
|
||||
CV_Assert( masks[i].rows == queryDescriptorsCount &&
|
||||
masks[i].cols == trainDescCollection[i].rows &&
|
||||
masks[i].type() == CV_8UC1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorMatcher::knnMatch( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int knn,
|
||||
@ -736,10 +736,20 @@ GenericDescriptorMatcher::GenericDescriptorMatcher()
|
||||
GenericDescriptorMatcher::~GenericDescriptorMatcher()
|
||||
{}
|
||||
|
||||
void GenericDescriptorMatcher::add( const vector<Mat>& imgCollection,
|
||||
vector<vector<KeyPoint> >& pointCollection )
|
||||
void GenericDescriptorMatcher::add( const vector<Mat>& images,
|
||||
vector<vector<KeyPoint> >& keypoints )
|
||||
{
|
||||
trainPointCollection.add( imgCollection, pointCollection );
|
||||
CV_Assert( !images.empty() );
|
||||
CV_Assert( images.size() == keypoints.size() );
|
||||
|
||||
for( size_t i = 0; i < images.size(); i++ )
|
||||
{
|
||||
CV_Assert( !images[i].empty() );
|
||||
KeyPointsFilter::runByImageBorder( keypoints[i], images[i].size(), 0 );
|
||||
KeyPointsFilter::runByKeypointSize( keypoints[i], std::numeric_limits<float>::epsilon() );
|
||||
}
|
||||
|
||||
trainPointCollection.add( images, keypoints );
|
||||
}
|
||||
|
||||
const vector<Mat>& GenericDescriptorMatcher::getTrainImages() const
|
||||
@ -827,6 +837,14 @@ void GenericDescriptorMatcher::knnMatch( const Mat& queryImage, vector<KeyPoint>
|
||||
vector<vector<DMatch> >& matches, int knn,
|
||||
const vector<Mat>& masks, bool compactResult )
|
||||
{
|
||||
matches.clear();
|
||||
|
||||
if( queryImage.empty() || queryKeypoints.empty() )
|
||||
return;
|
||||
|
||||
KeyPointsFilter::runByImageBorder( queryKeypoints, queryImage.size(), 0 );
|
||||
KeyPointsFilter::runByKeypointSize( queryKeypoints, std::numeric_limits<float>::epsilon() );
|
||||
|
||||
train();
|
||||
knnMatchImpl( queryImage, queryKeypoints, matches, knn, masks, compactResult );
|
||||
}
|
||||
@ -835,6 +853,14 @@ void GenericDescriptorMatcher::radiusMatch( const Mat& queryImage, vector<KeyPoi
|
||||
vector<vector<DMatch> >& matches, float maxDistance,
|
||||
const vector<Mat>& masks, bool compactResult )
|
||||
{
|
||||
matches.clear();
|
||||
|
||||
if( queryImage.empty() || queryKeypoints.empty() )
|
||||
return;
|
||||
|
||||
KeyPointsFilter::runByImageBorder( queryKeypoints, queryImage.size(), 0 );
|
||||
KeyPointsFilter::runByKeypointSize( queryKeypoints, std::numeric_limits<float>::epsilon() );
|
||||
|
||||
train();
|
||||
radiusMatchImpl( queryImage, queryKeypoints, matches, maxDistance, masks, compactResult );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user