fixed #1044
This commit is contained in:
parent
71d14386e4
commit
66c116ec6a
@ -266,7 +266,7 @@ CV_EXPORTS void read(const FileNode& node, CV_OUT vector<KeyPoint>& keypoints);
|
|||||||
/*
|
/*
|
||||||
* A class filters a vector of 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,
|
* 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.
|
* it has only 3 needed by now static methods.
|
||||||
*/
|
*/
|
||||||
class CV_EXPORTS KeyPointsFilter
|
class CV_EXPORTS KeyPointsFilter
|
||||||
{
|
{
|
||||||
@ -281,6 +281,10 @@ public:
|
|||||||
* Remove keypoints of sizes out of range.
|
* Remove keypoints of sizes out of range.
|
||||||
*/
|
*/
|
||||||
static void runByKeypointSize( vector<KeyPoint>& keypoints, float minSize, float maxSize=std::numeric_limits<float>::max() );
|
static void runByKeypointSize( vector<KeyPoint>& keypoints, float minSize, float maxSize=std::numeric_limits<float>::max() );
|
||||||
|
/*
|
||||||
|
* Remove keypoints from some image by mask for pixels of this image.
|
||||||
|
*/
|
||||||
|
static void runByPixelsMask( vector<KeyPoint>& keypoints, const Mat& mask );
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1243,13 +1247,7 @@ public:
|
|||||||
static Ptr<FeatureDetector> create( const string& detectorType );
|
static Ptr<FeatureDetector> create( const string& detectorType );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const = 0;
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const = 0;
|
||||||
/*
|
|
||||||
* Remove keypoints that are not in the mask.
|
|
||||||
* Helper function, useful when wrapping a library call for keypoint detection that
|
|
||||||
* does not support a mask argument.
|
|
||||||
*/
|
|
||||||
static void removeInvalidPoints( const Mat& mask, vector<KeyPoint>& keypoints );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CV_EXPORTS FastFeatureDetector : public FeatureDetector
|
class CV_EXPORTS FastFeatureDetector : public FeatureDetector
|
||||||
|
@ -48,17 +48,6 @@ namespace cv
|
|||||||
/*
|
/*
|
||||||
* FeatureDetector
|
* FeatureDetector
|
||||||
*/
|
*/
|
||||||
class MaskPredicate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MaskPredicate( const Mat& _mask ) : mask(_mask) {}
|
|
||||||
bool operator() (const KeyPoint& key_pt) const
|
|
||||||
{
|
|
||||||
return mask.at<uchar>( (int)(key_pt.pt.y + 0.5f), (int)(key_pt.pt.x + 0.5f) ) == 0;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
const Mat mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
FeatureDetector::~FeatureDetector()
|
FeatureDetector::~FeatureDetector()
|
||||||
{}
|
{}
|
||||||
@ -82,14 +71,6 @@ void FeatureDetector::detect(const vector<Mat>& imageCollection, vector<vector<K
|
|||||||
detect( imageCollection[i], pointCollection[i], masks.empty() ? Mat() : masks[i] );
|
detect( imageCollection[i], pointCollection[i], masks.empty() ? Mat() : masks[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeatureDetector::removeInvalidPoints( const Mat& mask, vector<KeyPoint>& keypoints )
|
|
||||||
{
|
|
||||||
if( mask.empty() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
keypoints.erase(remove_if(keypoints.begin(), keypoints.end(), MaskPredicate(mask)), keypoints.end());
|
|
||||||
};
|
|
||||||
|
|
||||||
void FeatureDetector::read( const FileNode& )
|
void FeatureDetector::read( const FileNode& )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -179,7 +160,7 @@ void FastFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoi
|
|||||||
Mat grayImage = image;
|
Mat grayImage = image;
|
||||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
||||||
FAST( grayImage, keypoints, threshold, nonmaxSuppression );
|
FAST( grayImage, keypoints, threshold, nonmaxSuppression );
|
||||||
removeInvalidPoints( mask, keypoints );
|
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -360,7 +341,7 @@ void StarFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoi
|
|||||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
|
||||||
|
|
||||||
star(grayImage, keypoints);
|
star(grayImage, keypoints);
|
||||||
removeInvalidPoints(mask, keypoints);
|
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -482,7 +463,7 @@ void DenseFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypo
|
|||||||
if( params.varyImgBoundWithScale ) curBound = static_cast<int>( curBound * params.featureScaleMul + 0.5f );
|
if( params.varyImgBoundWithScale ) curBound = static_cast<int>( curBound * params.featureScaleMul + 0.5f );
|
||||||
}
|
}
|
||||||
|
|
||||||
removeInvalidPoints( mask, keypoints );
|
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -566,7 +547,7 @@ void PyramidAdaptedFeatureDetector::detectImpl( const Mat& image, vector<KeyPoin
|
|||||||
{
|
{
|
||||||
// Detect on current level of the pyramid
|
// Detect on current level of the pyramid
|
||||||
vector<KeyPoint> new_pts;
|
vector<KeyPoint> new_pts;
|
||||||
detector->detect(src, new_pts);
|
detector->detect( src, new_pts, mask );
|
||||||
for( vector<KeyPoint>::iterator it = new_pts.begin(), end = new_pts.end(); it != end; ++it)
|
for( vector<KeyPoint>::iterator it = new_pts.begin(), end = new_pts.end(); it != end; ++it)
|
||||||
{
|
{
|
||||||
it->pt.x *= multiplier;
|
it->pt.x *= multiplier;
|
||||||
@ -574,7 +555,6 @@ void PyramidAdaptedFeatureDetector::detectImpl( const Mat& image, vector<KeyPoin
|
|||||||
it->size *= multiplier;
|
it->size *= multiplier;
|
||||||
it->octave = l;
|
it->octave = l;
|
||||||
}
|
}
|
||||||
removeInvalidPoints( mask, new_pts );
|
|
||||||
keypoints.insert( keypoints.end(), new_pts.begin(), new_pts.end() );
|
keypoints.insert( keypoints.end(), new_pts.begin(), new_pts.end() );
|
||||||
|
|
||||||
// Downsample
|
// Downsample
|
||||||
|
@ -200,4 +200,25 @@ void KeyPointsFilter::runByKeypointSize( vector<KeyPoint>& keypoints, float minS
|
|||||||
keypoints.end() );
|
keypoints.end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MaskPredicate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MaskPredicate( const Mat& _mask ) : mask(_mask) {}
|
||||||
|
bool operator() (const KeyPoint& key_pt) const
|
||||||
|
{
|
||||||
|
return mask.at<uchar>( (int)(key_pt.pt.y + 0.5f), (int)(key_pt.pt.x + 0.5f) ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Mat mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
void KeyPointsFilter::runByPixelsMask( vector<KeyPoint>& keypoints, const Mat& mask )
|
||||||
|
{
|
||||||
|
if( mask.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
keypoints.erase(remove_if(keypoints.begin(), keypoints.end(), MaskPredicate(mask)), keypoints.end());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2194,16 +2194,49 @@ static void removeDuplicatedKeypoints(vector<KeyPoint>& keypoints)
|
|||||||
keypoints.resize(j);
|
keypoints.resize(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// detectors
|
// detectors
|
||||||
void SIFT::operator()(const Mat& img, const Mat& mask,
|
void SIFT::operator()(const Mat& image, const Mat& mask,
|
||||||
vector<KeyPoint>& keypoints) const
|
vector<KeyPoint>& keypoints) const
|
||||||
{
|
{
|
||||||
if( img.empty() || img.type() != CV_8UC1 )
|
if( image.empty() || image.type() != CV_8UC1 )
|
||||||
CV_Error( CV_StsBadArg, "img is empty or has incorrect type" );
|
CV_Error( CV_StsBadArg, "image is empty or has incorrect type (!=CV_8UC1)" );
|
||||||
|
|
||||||
|
if( !mask.empty() && mask.type() != CV_8UC1 )
|
||||||
|
CV_Error( CV_StsBadArg, "mask has incorrect type (!=CV_8UC1)" );
|
||||||
|
|
||||||
|
Mat subImage, subMask;
|
||||||
|
Rect brect( 0, 0, image.cols, image.rows );
|
||||||
|
if( mask.empty() )
|
||||||
|
{
|
||||||
|
subImage = image;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vector<Point> points;
|
||||||
|
points.reserve( image.rows * image.cols );
|
||||||
|
for( int y = 0; y < mask.rows; y++ )
|
||||||
|
{
|
||||||
|
for( int x = 0; x < mask.cols; x++ )
|
||||||
|
{
|
||||||
|
if( mask.at<uchar>(y,x) )
|
||||||
|
points.push_back( cv::Point(x,y) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
brect = cv::boundingRect( points );
|
||||||
|
|
||||||
|
if( brect.x == 0 && brect.y == 0 && brect.width == mask.cols && brect.height == mask.rows )
|
||||||
|
{
|
||||||
|
subImage = image;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
subImage = image( brect );
|
||||||
|
subMask = mask( brect );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Mat fimg;
|
Mat fimg;
|
||||||
img.convertTo(fimg, CV_32FC1, 1.0/255.0);
|
subImage.convertTo( fimg, CV_32FC1, 1.0/255.0 );
|
||||||
|
|
||||||
const double sigman = .5 ;
|
const double sigman = .5 ;
|
||||||
const double sigma0 = 1.6 * powf(2.0f, 1.0f / commParams.nOctaveLayers) ;
|
const double sigma0 = 1.6 * powf(2.0f, 1.0f / commParams.nOctaveLayers) ;
|
||||||
@ -2225,7 +2258,20 @@ void SIFT::operator()(const Mat& img, const Mat& mask,
|
|||||||
keypoints.push_back( vlKeypointToOcv(vlsift, *iter, angleVal*a_180divPI) );
|
keypoints.push_back( vlKeypointToOcv(vlsift, *iter, angleVal*a_180divPI) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeDuplicatedKeypoints(keypoints);
|
removeDuplicatedKeypoints(keypoints);
|
||||||
|
|
||||||
|
if( !subMask.empty() )
|
||||||
|
{
|
||||||
|
// filter points by subMask and convert the points coordinates from subImage size to image size
|
||||||
|
KeyPointsFilter::runByPixelsMask( keypoints, subMask );
|
||||||
|
int dx = brect.x, dy = brect.y;
|
||||||
|
for( vector<KeyPoint>::iterator it = keypoints.begin(); it != keypoints.end(); ++it )
|
||||||
|
{
|
||||||
|
it->pt.x += dx;
|
||||||
|
it->pt.y += dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InvalidKeypoint
|
struct InvalidKeypoint
|
||||||
@ -2234,16 +2280,16 @@ struct InvalidKeypoint
|
|||||||
};
|
};
|
||||||
|
|
||||||
// descriptors
|
// descriptors
|
||||||
void SIFT::operator()(const Mat& img, const Mat& mask,
|
void SIFT::operator()(const Mat& image, const Mat& mask,
|
||||||
vector<KeyPoint>& keypoints,
|
vector<KeyPoint>& keypoints,
|
||||||
Mat& descriptors,
|
Mat& descriptors,
|
||||||
bool useProvidedKeypoints) const
|
bool useProvidedKeypoints) const
|
||||||
{
|
{
|
||||||
if( img.empty() || img.type() != CV_8UC1 )
|
if( image.empty() || image.type() != CV_8UC1 )
|
||||||
CV_Error( CV_StsBadArg, "img is empty or has incorrect type" );
|
CV_Error( CV_StsBadArg, "img is empty or has incorrect type" );
|
||||||
|
|
||||||
Mat fimg;
|
Mat fimg;
|
||||||
img.convertTo(fimg, CV_32FC1, 1.0/255.0);
|
image.convertTo(fimg, CV_32FC1, 1.0/255.0);
|
||||||
|
|
||||||
const double sigman = .5 ;
|
const double sigman = .5 ;
|
||||||
const double sigma0 = 1.6 * powf(2.0f, 1.0f / commParams.nOctaveLayers) ;
|
const double sigma0 = 1.6 * powf(2.0f, 1.0f / commParams.nOctaveLayers) ;
|
||||||
@ -2251,7 +2297,12 @@ void SIFT::operator()(const Mat& img, const Mat& mask,
|
|||||||
const double a_PIdiv180 = CV_PI/180.;
|
const double a_PIdiv180 = CV_PI/180.;
|
||||||
|
|
||||||
if( !useProvidedKeypoints )
|
if( !useProvidedKeypoints )
|
||||||
(*this)(img, mask, keypoints);
|
(*this)(image, mask, keypoints);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// filter keypoints by mask
|
||||||
|
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
||||||
|
}
|
||||||
|
|
||||||
VL::Sift vlsift((float*)fimg.data, fimg.cols, fimg.rows,
|
VL::Sift vlsift((float*)fimg.data, fimg.cols, fimg.rows,
|
||||||
sigman, sigma0, commParams.nOctaves, commParams.nOctaveLayers,
|
sigman, sigma0, commParams.nOctaves, commParams.nOctaveLayers,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user