diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp index ab209932f..37969f9cf 100644 --- a/modules/features2d/include/opencv2/features2d/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d/features2d.hpp @@ -1356,6 +1356,32 @@ protected: CV_EXPORTS Ptr createFeatureDetector( const string& detectorType ); +class DenseFeatureDetector : public FeatureDetector +{ +public: + DenseFeatureDetector() : initFeatureScale(1), featureScaleLevels(1), featureScaleMul(0.1f), + initXyStep(6), initImgBound(0), varyXyStepWithScale(true), varyImgBoundWithScale(false) {} + DenseFeatureDetector( float _initFeatureScale, int _featureScaleLevels=1, float _featureScaleMul=0.1f, + int _initXyStep=6, int _initImgBound=0, bool _varyXyStepWithScale=true, bool _varyImgBoundWithScale=false ) : + initFeatureScale(_initFeatureScale), featureScaleLevels(_featureScaleLevels), featureScaleMul(_featureScaleMul), + initXyStep(_initXyStep), initImgBound(_initImgBound), varyXyStepWithScale(_varyXyStepWithScale), varyImgBoundWithScale(_varyImgBoundWithScale) {} + +protected: + + virtual void detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const = 0; + + float initFeatureScale; + int featureScaleLevels; + float featureScaleMul; + + int initXyStep; + int initImgBound; + + bool varyXyStepWithScale; + bool varyImgBoundWithScale; + +}; + /* * Adapts a detector to partition the source image into a grid and detect * points in each cell. diff --git a/modules/features2d/src/detectors.cpp b/modules/features2d/src/detectors.cpp index 726e12fcf..9ce4ae755 100644 --- a/modules/features2d/src/detectors.cpp +++ b/modules/features2d/src/detectors.cpp @@ -334,44 +334,32 @@ void SurfFeatureDetector::detectImpl( const Mat& image, const Mat& mask, surf(grayImage, mask, keypoints); } -Ptr createFeatureDetector( const string& detectorType ) +/* + * GridAdaptedFeatureDetector + */ +void DenseFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const { - FeatureDetector* fd = 0; - if( !detectorType.compare( "FAST" ) ) + keypoints.clear(); + + float curScale = initFeatureScale; + int curStep = initXyStep; + int curBound = initImgBound; + for( int curLevel = 0; curLevel < featureScaleLevels; curLevel++ ) { - fd = new FastFeatureDetector( 10/*threshold*/, true/*nonmax_suppression*/ ); + for( int x = curBound; x < image.cols - curBound; x += curStep ) + { + for( int y = curBound; y < image.rows - curBound; y += curStep ) + { + keypoints.push_back( KeyPoint(static_cast(x), static_cast(y), curScale) ); + } + } + + curScale = curScale * featureScaleMul; + if( varyXyStepWithScale ) curStep = static_cast( curStep * featureScaleMul + 0.5f ); + if( varyImgBoundWithScale ) curBound = static_cast( curBound * featureScaleMul + 0.5f ); } - else if( !detectorType.compare( "STAR" ) ) - { - fd = new StarFeatureDetector( 16/*max_size*/, 5/*response_threshold*/, 10/*line_threshold_projected*/, - 8/*line_threshold_binarized*/, 5/*suppress_nonmax_size*/ ); - } - else if( !detectorType.compare( "SIFT" ) ) - { - fd = new SiftFeatureDetector(SIFT::DetectorParams::GET_DEFAULT_THRESHOLD(), - SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD()); - } - else if( !detectorType.compare( "SURF" ) ) - { - fd = new SurfFeatureDetector( 400./*hessian_threshold*/, 3 /*octaves*/, 4/*octave_layers*/ ); - } - else if( !detectorType.compare( "MSER" ) ) - { - fd = new MserFeatureDetector( 5/*delta*/, 60/*min_area*/, 14400/*_max_area*/, 0.25f/*max_variation*/, - 0.2/*min_diversity*/, 200/*max_evolution*/, 1.01/*area_threshold*/, 0.003/*min_margin*/, - 5/*edge_blur_size*/ ); - } - else if( !detectorType.compare( "GFTT" ) ) - { - fd = new GoodFeaturesToTrackDetector( 1000/*maxCorners*/, 0.01/*qualityLevel*/, 1./*minDistance*/, - 3/*int _blockSize*/, false/*useHarrisDetector*/, 0.04/*k*/ ); - } - else if( !detectorType.compare( "HARRIS" ) ) - { - fd = new GoodFeaturesToTrackDetector( 1000/*maxCorners*/, 0.01/*qualityLevel*/, 1./*minDistance*/, - 3/*int _blockSize*/, true/*useHarrisDetector*/, 0.04/*k*/ ); - } - return fd; + + removeInvalidPoints( mask, keypoints ); } /* @@ -468,4 +456,44 @@ void PyramidAdaptedFeatureDetector::detectImpl( const Mat& image, const Mat& mas } } +Ptr createFeatureDetector( const string& detectorType ) +{ + FeatureDetector* fd = 0; + if( !detectorType.compare( "FAST" ) ) + { + fd = new FastFeatureDetector( 10/*threshold*/, true/*nonmax_suppression*/ ); + } + else if( !detectorType.compare( "STAR" ) ) + { + fd = new StarFeatureDetector( 16/*max_size*/, 5/*response_threshold*/, 10/*line_threshold_projected*/, + 8/*line_threshold_binarized*/, 5/*suppress_nonmax_size*/ ); + } + else if( !detectorType.compare( "SIFT" ) ) + { + fd = new SiftFeatureDetector(SIFT::DetectorParams::GET_DEFAULT_THRESHOLD(), + SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD()); + } + else if( !detectorType.compare( "SURF" ) ) + { + fd = new SurfFeatureDetector( 400./*hessian_threshold*/, 3 /*octaves*/, 4/*octave_layers*/ ); + } + else if( !detectorType.compare( "MSER" ) ) + { + fd = new MserFeatureDetector( 5/*delta*/, 60/*min_area*/, 14400/*_max_area*/, 0.25f/*max_variation*/, + 0.2/*min_diversity*/, 200/*max_evolution*/, 1.01/*area_threshold*/, 0.003/*min_margin*/, + 5/*edge_blur_size*/ ); + } + else if( !detectorType.compare( "GFTT" ) ) + { + fd = new GoodFeaturesToTrackDetector( 1000/*maxCorners*/, 0.01/*qualityLevel*/, 1./*minDistance*/, + 3/*int _blockSize*/, false/*useHarrisDetector*/, 0.04/*k*/ ); + } + else if( !detectorType.compare( "HARRIS" ) ) + { + fd = new GoodFeaturesToTrackDetector( 1000/*maxCorners*/, 0.01/*qualityLevel*/, 1./*minDistance*/, + 3/*int _blockSize*/, true/*useHarrisDetector*/, 0.04/*k*/ ); + } + return fd; +} + }