Commit b9662e09 authored by Maria Dimashova's avatar Maria Dimashova

added the filtering of keypoints having zero size (#877)

parent d3aa2280
...@@ -263,6 +263,26 @@ CV_EXPORTS void write(FileStorage& fs, const string& name, const vector<KeyPoint ...@@ -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 //! reads vector of keypoints from the specified file storage node
CV_EXPORTS void read(const FileNode& node, CV_OUT vector<KeyPoint>& keypoints); 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. SIFT implementation.
...@@ -1625,12 +1645,6 @@ public: ...@@ -1625,12 +1645,6 @@ public:
protected: protected:
virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const = 0; 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 );
}; };
/* /*
...@@ -1715,7 +1729,7 @@ void CalonderDescriptorExtractor<T>::computeImpl( const cv::Mat& image, ...@@ -1715,7 +1729,7 @@ void CalonderDescriptorExtractor<T>::computeImpl( const cv::Mat& image,
cv::Mat& descriptors) const cv::Mat& descriptors) const
{ {
// Cannot compute descriptors for keypoints on the image border. // 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 /// @todo Check 16-byte aligned
descriptors.create(keypoints.size(), classifier_.classes(), cv::DataType<T>::type); descriptors.create(keypoints.size(), classifier_.classes(), cv::DataType<T>::type);
......
...@@ -208,7 +208,7 @@ void BriefDescriptorExtractor::computeImpl(const Mat& image, std::vector<KeyPoin ...@@ -208,7 +208,7 @@ void BriefDescriptorExtractor::computeImpl(const Mat& image, std::vector<KeyPoin
integral( grayImage, sum, CV_32S); integral( grayImage, sum, CV_32S);
//Remove keypoints very close to the border //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); descriptors = Mat::zeros((int)keypoints.size(), bytes_, CV_8U);
test_fn_(sum, keypoints, descriptors); test_fn_(sum, keypoints, descriptors);
......
...@@ -52,30 +52,20 @@ namespace cv ...@@ -52,30 +52,20 @@ namespace cv
/* /*
* DescriptorExtractor * DescriptorExtractor
*/ */
struct RoiPredicate
{
RoiPredicate( const Rect& _r ) : r(_r)
{}
bool operator()( const KeyPoint& keyPt ) const
{
return !r.contains( keyPt.pt );
}
Rect r;
};
DescriptorExtractor::~DescriptorExtractor() DescriptorExtractor::~DescriptorExtractor()
{} {}
void DescriptorExtractor::compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const void DescriptorExtractor::compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const
{ {
if( image.empty() || keypoints.empty() ) if( image.empty() || keypoints.empty() )
{
descriptors.release();
return; return;
}
// Check keypoints are in image. Do filter bad points here? KeyPointsFilter::runByImageBorder( keypoints, image.size(), 0 );
//for( size_t i = 0; i < keypoints.size(); i++ ) KeyPointsFilter::runByKeypointSize( keypoints, std::numeric_limits<float>::epsilon() );
// CV_Assert( Rect(0,0, image.cols, image.rows).contains(keypoints[i].pt) );
computeImpl( image, keypoints, descriptors ); computeImpl( image, keypoints, descriptors );
} }
...@@ -99,18 +89,6 @@ bool DescriptorExtractor::empty() const ...@@ -99,18 +89,6 @@ bool DescriptorExtractor::empty() const
return false; 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) Ptr<DescriptorExtractor> DescriptorExtractor::create(const string& descriptorExtractorType)
{ {
DescriptorExtractor* de = 0; DescriptorExtractor* de = 0;
......
...@@ -152,4 +152,52 @@ float KeyPoint::overlap( const KeyPoint& kp1, const KeyPoint& kp2 ) ...@@ -152,4 +152,52 @@ float KeyPoint::overlap( const KeyPoint& kp1, const KeyPoint& kp2 )
return ovrl; 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() );
}
} }
...@@ -736,10 +736,20 @@ GenericDescriptorMatcher::GenericDescriptorMatcher() ...@@ -736,10 +736,20 @@ GenericDescriptorMatcher::GenericDescriptorMatcher()
GenericDescriptorMatcher::~GenericDescriptorMatcher() GenericDescriptorMatcher::~GenericDescriptorMatcher()
{} {}
void GenericDescriptorMatcher::add( const vector<Mat>& imgCollection, void GenericDescriptorMatcher::add( const vector<Mat>& images,
vector<vector<KeyPoint> >& pointCollection ) 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 const vector<Mat>& GenericDescriptorMatcher::getTrainImages() const
...@@ -827,6 +837,14 @@ void GenericDescriptorMatcher::knnMatch( const Mat& queryImage, vector<KeyPoint> ...@@ -827,6 +837,14 @@ void GenericDescriptorMatcher::knnMatch( const Mat& queryImage, vector<KeyPoint>
vector<vector<DMatch> >& matches, int knn, vector<vector<DMatch> >& matches, int knn,
const vector<Mat>& masks, bool compactResult ) 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(); train();
knnMatchImpl( queryImage, queryKeypoints, matches, knn, masks, compactResult ); knnMatchImpl( queryImage, queryKeypoints, matches, knn, masks, compactResult );
} }
...@@ -835,6 +853,14 @@ void GenericDescriptorMatcher::radiusMatch( const Mat& queryImage, vector<KeyPoi ...@@ -835,6 +853,14 @@ void GenericDescriptorMatcher::radiusMatch( const Mat& queryImage, vector<KeyPoi
vector<vector<DMatch> >& matches, float maxDistance, vector<vector<DMatch> >& matches, float maxDistance,
const vector<Mat>& masks, bool compactResult ) 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(); train();
radiusMatchImpl( queryImage, queryKeypoints, matches, maxDistance, masks, compactResult ); radiusMatchImpl( queryImage, queryKeypoints, matches, maxDistance, masks, compactResult );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment