Commit 4e60deca authored by Maria Dimashova's avatar Maria Dimashova

added GridAdaptedFeatureDetector, PyramidAdaptedFeatureDetector and funcs to…

added GridAdaptedFeatureDetector, PyramidAdaptedFeatureDetector and funcs to draw keypoints and matches
parent 9c94a96c
......@@ -1477,6 +1477,44 @@ protected:
CV_EXPORTS Ptr<FeatureDetector> createDetector( const string& detectorType );
/*
* Adapts a detector to partition the source image into a grid and detect
* points in each cell.
*/
class CV_EXPORTS GridAdaptedFeatureDetector : public FeatureDetector
{
public:
GridAdaptedFeatureDetector( const Ptr<FeatureDetector>& _detector, int _maxTotalKeypoints,
int _gridRows=4, int _gridCols=4 );
// todo read/write
protected:
Ptr<FeatureDetector> detector;
int maxTotalKeypoints;
int gridRows;
int gridCols;
virtual void detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints ) const;
};
/*
* Adapts a detector to detect points over multiple levels of a Gaussian
* pyramid. Useful for detectors that are not inherently scaled.
*/
class PyramidAdaptedFeatureDetector : public FeatureDetector
{
public:
PyramidAdaptedFeatureDetector( const Ptr<FeatureDetector>& _detector, int _levels=2 );
// todo read/write
protected:
Ptr<FeatureDetector> detector;
int levels;
virtual void detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints ) const;
};
/****************************************************************************************\
* DescriptorExtractor *
\****************************************************************************************/
......@@ -2273,18 +2311,38 @@ struct CV_EXPORTS DrawMatchesFlags
enum{ DEFAULT = 0, // Output image matrix will be created (Mat::create),
// i.e. existing memory of output image may be reused.
// Two source image, matches and single keypoints will be drawn.
// For each keypoint only the center point will be drawn (without
// the circle around keypoint with keypoint size and orientation).
DRAW_OVER_OUTIMG = 1, // Output image matrix will not be created (Mat::create).
// Matches will be drawn on existing content of output image.
NOT_DRAW_SINGLE_POINTS = 2 // Single keypoints will not be drawn.
NOT_DRAW_SINGLE_POINTS = 2, // Single keypoints will not be drawn.
DRAW_RICH_KEYPOINTS = 4 // For each keypoint the circle around keypoint with keypoint size and
// orientation will be drawn.
};
};
// Draw keypoints.
CV_EXPORTS void drawKeypoints( const Mat& image, const vector<KeyPoint>& keypoints, Mat& outImg,
const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );
// Draws matches of keypints from two images on output image.
CV_EXPORTS void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
const Mat& img2, const vector<KeyPoint>& keypoints2,
const vector<int>& matches, Mat& outImg,
const Scalar& matchColor = Scalar::all(-1), const Scalar& singlePointColor = Scalar::all(-1),
const vector<char>& matchesMask = vector<char>(), int flags = DrawMatchesFlags::DEFAULT );
const vector<int>& matches1to2, Mat& outImg,
const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
const vector<char>& matchesMask=vector<char>(), int flags=DrawMatchesFlags::DEFAULT );
CV_EXPORTS void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
const Mat& img2, const vector<KeyPoint>& keypoints2,
const vector<DMatch>& matches1to2, Mat& outImg,
const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
const vector<char>& matchesMask=vector<char>(), int flags=DrawMatchesFlags::DEFAULT );
CV_EXPORTS void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
const Mat& img2, const vector<KeyPoint>& keypoints2,
const vector<vector<DMatch> >& matches1to2, Mat& outImg,
const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
const vector<vector<char> >& matchesMask=vector<vector<char> >(), int flags=DrawMatchesFlags::DEFAULT );
}
......
This diff is collapsed.
......@@ -46,8 +46,8 @@ using namespace std;
namespace cv
{
/*
FeatureDetector
*/
* FeatureDetector
*/
struct MaskPredicate
{
MaskPredicate( const Mat& _mask ) : mask(_mask)
......@@ -70,8 +70,8 @@ void FeatureDetector::removeInvalidPoints( const Mat& mask, vector<KeyPoint>& ke
};
/*
FastFeatureDetector
*/
* FastFeatureDetector
*/
FastFeatureDetector::FastFeatureDetector( int _threshold, bool _nonmaxSuppression )
: threshold(_threshold), nonmaxSuppression(_nonmaxSuppression)
{}
......@@ -95,8 +95,8 @@ void FastFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<
}
/*
GoodFeaturesToTrackDetector
*/
* GoodFeaturesToTrackDetector
*/
GoodFeaturesToTrackDetector::GoodFeaturesToTrackDetector( int _maxCorners, double _qualityLevel, \
double _minDistance, int _blockSize,
bool _useHarrisDetector, double _k )
......@@ -140,8 +140,8 @@ void GoodFeaturesToTrackDetector::detectImpl( const Mat& image, const Mat& mask,
}
/*
MserFeatureDetector
*/
* MserFeatureDetector
*/
MserFeatureDetector::MserFeatureDetector( int delta, int minArea, int maxArea,
double maxVariation, double minDiversity,
int maxEvolution, double areaThreshold,
......@@ -204,8 +204,8 @@ void MserFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<
}
/*
StarFeatureDetector
*/
* StarFeatureDetector
*/
StarFeatureDetector::StarFeatureDetector(int maxSize, int responseThreshold,
int lineThresholdProjected,
int lineThresholdBinarized,
......@@ -244,8 +244,8 @@ void StarFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<
}
/*
SiftFeatureDetector
*/
* SiftFeatureDetector
*/
SiftFeatureDetector::SiftFeatureDetector(double threshold, double edgeThreshold,
int nOctaves, int nOctaveLayers, int firstOctave, int angleMode) :
sift(threshold, edgeThreshold, nOctaves, nOctaveLayers, firstOctave, angleMode)
......@@ -286,8 +286,8 @@ void SiftFeatureDetector::detectImpl( const Mat& image, const Mat& mask,
}
/*
SurfFeatureDetector
*/
* SurfFeatureDetector
*/
SurfFeatureDetector::SurfFeatureDetector( double hessianThreshold, int octaves, int octaveLayers)
: surf(hessianThreshold, octaves, octaveLayers)
{}
......@@ -360,4 +360,98 @@ Ptr<FeatureDetector> createDetector( const string& detectorType )
return fd;
}
/*
* GridAdaptedFeatureDetector
*/
GridAdaptedFeatureDetector::GridAdaptedFeatureDetector( const Ptr<FeatureDetector>& _detector,
int _maxTotalKeypoints, int _gridRows, int _gridCols )
: detector(_detector), maxTotalKeypoints(_maxTotalKeypoints), gridRows(_gridRows), gridCols(_gridCols)
{}
struct ResponseComparator
{
bool operator() (const KeyPoint& a, const KeyPoint& b)
{
return std::abs(a.response) > std::abs(b.response);
}
};
void keepStrongest( int N, vector<KeyPoint>& keypoints )
{
if( (int)keypoints.size() > N )
{
vector<KeyPoint>::iterator nth = keypoints.begin() + N;
std::nth_element( keypoints.begin(), nth, keypoints.end(), ResponseComparator() );
keypoints.erase( nth, keypoints.end() );
}
}
void GridAdaptedFeatureDetector::detectImpl( const Mat &image, const Mat &mask,
vector<KeyPoint> &keypoints ) const
{
keypoints.clear();
keypoints.reserve(maxTotalKeypoints);
int maxPerCell = maxTotalKeypoints / (gridRows * gridCols);
for( int i = 0; i < gridRows; ++i )
{
Range row_range((i*image.rows)/gridRows, ((i+1)*image.rows)/gridRows);
for( int j = 0; j < gridCols; ++j )
{
Range col_range((j*image.cols)/gridCols, ((j+1)*image.cols)/gridCols);
Mat sub_image = image(row_range, col_range);
Mat sub_mask;
if( !mask.empty() )
sub_mask = mask(row_range, col_range);
vector<KeyPoint> sub_keypoints;
detector->detect( sub_image, sub_keypoints, sub_mask );
keepStrongest( maxPerCell, sub_keypoints );
for( std::vector<cv::KeyPoint>::iterator it = sub_keypoints.begin(), end = sub_keypoints.end();
it != end; ++it )
{
it->pt.x += col_range.start;
it->pt.y += row_range.start;
}
keypoints.insert( keypoints.end(), sub_keypoints.begin(), sub_keypoints.end() );
}
}
}
/*
* GridAdaptedFeatureDetector
*/
PyramidAdaptedFeatureDetector::PyramidAdaptedFeatureDetector( const Ptr<FeatureDetector>& _detector, int _levels )
: detector(_detector), levels(_levels)
{}
void PyramidAdaptedFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints ) const
{
Mat src = image;
for( int l = 0, multiplier = 1; l <= levels; ++l, multiplier *= 2 )
{
// Detect on current level of the pyramid
vector<KeyPoint> new_pts;
detector->detect(src, new_pts);
for( vector<KeyPoint>::iterator it = new_pts.begin(), end = new_pts.end(); it != end; ++it)
{
it->pt.x *= multiplier;
it->pt.y *= multiplier;
it->size *= multiplier;
it->octave = l;
}
removeInvalidPoints( mask, new_pts );
keypoints.insert( keypoints.end(), new_pts.begin(), new_pts.end() );
// Downsample
if( l < levels )
{
Mat dst;
pyrDown(src, dst);
src = dst;
}
}
}
}
......@@ -8,6 +8,9 @@
using namespace cv;
using namespace std;
#define DRAW_RICH_KEYPOINTS_MODE 0
#define DRAW_OUTLIERS_MODE 0
void warpPerspectiveRand( const Mat& src, Mat& dst, Mat& H, RNG& rng )
{
H.create(3, 3, CV_32FC1);
......@@ -79,12 +82,18 @@ void doIteration( const Mat& img1, Mat& img2, bool isWarpPerspective,
matchesMask[i1] = 1;
}
// draw inliers
drawMatches( img1, keypoints1, img2, keypoints2, matches, drawImg, CV_RGB(0, 255, 0), CV_RGB(0, 0, 255), matchesMask );
#if 0 // draw outliers
drawMatches( img1, keypoints1, img2, keypoints2, matches, drawImg, CV_RGB(0, 255, 0), CV_RGB(0, 0, 255), matchesMask
#if DRAW_RICH_KEYPOINTS_MODE
, DrawMatchesFlags::DRAW_RICH_KEYPOINTS
#endif
);
#if DRAW_OUTLIERS_MODE
// draw outliers
for( size_t i1 = 0; i1 < matchesMask.size(); i1++ )
matchesMask[i1] = !matchesMask[i1];
drawMatches( img1, keypoints1, img2, keypoints2, matches, drawImg, CV_RGB(0, 0, 255), CV_RGB(255, 0, 0), matchesMask,
DrawMatchesFlags::DRAW_OVER_OUTIMG | DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS )
DrawMatchesFlags::DRAW_OVER_OUTIMG | DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
#endif
}
else
......
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