diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp index aa83845c34..f6582c5e80 100644 --- a/modules/features2d/include/opencv2/features2d/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d/features2d.hpp @@ -224,25 +224,26 @@ public: static const int DEFAULT_NOCTAVES = 4; static const int DEFAULT_NOCTAVE_LAYERS = 3; static const int DEFAULT_FIRST_OCTAVE = -1; + enum{ FIRST_ANGLE = 0, AVERAGE_ANGLE = 1 }; + CommonParams() : nOctaves(DEFAULT_NOCTAVES), nOctaveLayers(DEFAULT_NOCTAVE_LAYERS), - firstOctave(DEFAULT_FIRST_OCTAVE) {} - CommonParams( int _nOctaves, int _nOctaveLayers, int _firstOctave ) : + firstOctave(DEFAULT_FIRST_OCTAVE), angleMode(FIRST_ANGLE) {} + CommonParams( int _nOctaves, int _nOctaveLayers, int _firstOctave, int _angleMode ) : nOctaves(_nOctaves), nOctaveLayers(_nOctaveLayers), - firstOctave(_firstOctave) {} + firstOctave(_firstOctave), angleMode(_angleMode) {} int nOctaves, nOctaveLayers, firstOctave; + int angleMode; }; struct DetectorParams { static double GET_DEFAULT_THRESHOLD() { return 0.04 / SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS / 2.0; } static double GET_DEFAULT_EDGE_THRESHOLD() { return 10.0; } - enum{ FIRST_ANGLE = 0, AVERAGE_ANGLE = 1 }; - DetectorParams() : threshold(GET_DEFAULT_THRESHOLD()), edgeThreshold(GET_DEFAULT_EDGE_THRESHOLD()), - angleMode(FIRST_ANGLE) {} - DetectorParams( double _threshold, double _edgeThreshold, int _angleMode ) : - threshold(_threshold), edgeThreshold(_edgeThreshold), angleMode(_angleMode) {} + + DetectorParams() : threshold(GET_DEFAULT_THRESHOLD()), edgeThreshold(GET_DEFAULT_EDGE_THRESHOLD()) {} + DetectorParams( double _threshold, double _edgeThreshold ) : + threshold(_threshold), edgeThreshold(_edgeThreshold) {} double threshold, edgeThreshold; - int angleMode; }; struct DescriptorParams @@ -250,24 +251,30 @@ public: static double GET_DEFAULT_MAGNIFICATION() { return 3.0; } static const bool DEFAULT_IS_NORMALIZE = true; static const int DESCRIPTOR_SIZE = 128; - DescriptorParams() : magnification(GET_DEFAULT_MAGNIFICATION()), isNormalize(DEFAULT_IS_NORMALIZE) {} - DescriptorParams( double _magnification, bool _isNormalize ) : - magnification(_magnification), isNormalize(_isNormalize) {} + DescriptorParams() : magnification(GET_DEFAULT_MAGNIFICATION()), isNormalize(DEFAULT_IS_NORMALIZE), + recalculateAngles(true) {} + DescriptorParams( double _magnification, bool _isNormalize, bool _recalculateAngles ) : + magnification(_magnification), isNormalize(_isNormalize), + recalculateAngles(_recalculateAngles) {} double magnification; bool isNormalize; + bool recalculateAngles; }; SIFT(); // sift-detector constructor - SIFT( double _threshold, double _edgeThreshold, int _angleMode=DetectorParams::FIRST_ANGLE, + SIFT( double _threshold, double _edgeThreshold, int _nOctaves=CommonParams::DEFAULT_NOCTAVES, int _nOctaveLayers=CommonParams::DEFAULT_NOCTAVE_LAYERS, - int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE ); + int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE, + int _angleMode=CommonParams::FIRST_ANGLE ); // sift-descriptor constructor SIFT( double _magnification, bool _isNormalize=true, + bool _recalculateAngles = true, int _nOctaves=CommonParams::DEFAULT_NOCTAVES, int _nOctaveLayers=CommonParams::DEFAULT_NOCTAVE_LAYERS, - int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE ); + int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE, + int _angleMode=CommonParams::FIRST_ANGLE ); SIFT( const CommonParams& _commParams, const DetectorParams& _detectorParams = DetectorParams(), const DescriptorParams& _descriptorParams = DescriptorParams() ); @@ -1231,10 +1238,10 @@ class CV_EXPORTS SiftFeatureDetector : public FeatureDetector public: SiftFeatureDetector( double threshold=SIFT::DetectorParams::GET_DEFAULT_THRESHOLD(), double edgeThreshold=SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD(), - int angleMode=SIFT::DetectorParams::FIRST_ANGLE, int nOctaves=SIFT::CommonParams::DEFAULT_NOCTAVES, int nOctaveLayers=SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS, - int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE ); + int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE, + int angleMode=SIFT::CommonParams::FIRST_ANGLE ); protected: virtual void detectImpl( const Mat& image, const Mat& mask, vector& keypoints ) const; @@ -1291,10 +1298,11 @@ protected: class CV_EXPORTS SiftDescriptorExtractor : public DescriptorExtractor { public: - SiftDescriptorExtractor( double magnification, bool isNormalize=true, + SiftDescriptorExtractor( double magnification, bool isNormalize=true, bool recalculateAngles=true, int nOctaves=SIFT::CommonParams::DEFAULT_NOCTAVES, int nOctaveLayers=SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS, - int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE ); + int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE, + int angleMode=SIFT::CommonParams::FIRST_ANGLE ); virtual void compute( const Mat& image, vector& keypoints, Mat& descriptors) const; @@ -1408,10 +1416,7 @@ public: * query The query set of descriptors * matches Indices of the closest matches from the training set */ - - - // TODO: remove vector* distances = 0 ??? - void match( const Mat& query, vector& matches, vector* distances = 0 ) const; + void match( const Mat& query, vector& matches ) const; /* * Find the best matches between two descriptor sets, with constraints @@ -1479,15 +1484,10 @@ inline void DescriptorMatcher::add( const Mat& descriptors ) } } -inline void DescriptorMatcher::match( const Mat& query, vector& matches, vector* distances ) const +inline void DescriptorMatcher::match( const Mat& query, vector& matches ) const { - if( distances ) - matchImpl( query, train, Mat(), matches, *distances ); - else - { - vector innDistances; - matchImpl( query, train, Mat(), matches, innDistances ); - } + vector innDistances; + matchImpl( query, train, Mat(), matches, innDistances ); } inline void DescriptorMatcher::match( const Mat& query, const Mat& mask, diff --git a/modules/features2d/src/descriptors.cpp b/modules/features2d/src/descriptors.cpp index d7092c6b6f..5951dcfa70 100644 --- a/modules/features2d/src/descriptors.cpp +++ b/modules/features2d/src/descriptors.cpp @@ -78,9 +78,9 @@ void DescriptorExtractor::removeBorderKeypoints( vector& keypoints, /****************************************************************************************\ * SiftDescriptorExtractor * \****************************************************************************************/ -SiftDescriptorExtractor::SiftDescriptorExtractor( double magnification, bool isNormalize, - int nOctaves, int nOctaveLayers, int firstOctave ) - : sift( magnification, isNormalize, nOctaves, nOctaveLayers, firstOctave ) +SiftDescriptorExtractor::SiftDescriptorExtractor( double magnification, bool isNormalize, bool recalculateAngles, + int nOctaves, int nOctaveLayers, int firstOctave, int angleMode ) + : sift( magnification, isNormalize, recalculateAngles, nOctaves, nOctaveLayers, firstOctave, angleMode ) {} void SiftDescriptorExtractor::compute( const Mat& image, diff --git a/modules/features2d/src/detectors.cpp b/modules/features2d/src/detectors.cpp index 484e975157..a0288d473e 100644 --- a/modules/features2d/src/detectors.cpp +++ b/modules/features2d/src/detectors.cpp @@ -152,9 +152,9 @@ void StarFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector< /* SiftFeatureDetector */ -SiftFeatureDetector::SiftFeatureDetector(double threshold, double edgeThreshold, int angleMode, - int nOctaves, int nOctaveLayers, int firstOctave) : - sift(threshold, edgeThreshold, angleMode, nOctaves, nOctaveLayers, firstOctave) +SiftFeatureDetector::SiftFeatureDetector(double threshold, double edgeThreshold, + int nOctaves, int nOctaveLayers, int firstOctave, int angleMode) : + sift(threshold, edgeThreshold, nOctaves, nOctaveLayers, firstOctave, angleMode) { } diff --git a/modules/features2d/src/sift.cpp b/modules/features2d/src/sift.cpp index b66fc5aa26..de32eb175a 100644 --- a/modules/features2d/src/sift.cpp +++ b/modules/features2d/src/sift.cpp @@ -47,8 +47,8 @@ // MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. #include "precomp.hpp" -#include -#include +#include +#include #define log2(a) (log((a))/CV_LOG2) @@ -1981,18 +1981,18 @@ using namespace cv; SIFT::SIFT() {} -SIFT::SIFT( double _threshold, double _edgeThreshold, int _angleMode, - int _nOctaves, int _nOctaveLayers, int _firstOctave ) +SIFT::SIFT( double _threshold, double _edgeThreshold, int _nOctaves, + int _nOctaveLayers, int _firstOctave, int _angleMode ) { - detectorParams = DetectorParams(_threshold, _edgeThreshold, _angleMode); - commParams = CommonParams(_nOctaves, _nOctaveLayers, _firstOctave); + detectorParams = DetectorParams(_threshold, _edgeThreshold); + commParams = CommonParams(_nOctaves, _nOctaveLayers, _firstOctave, _angleMode); } -SIFT::SIFT( double _magnification, bool _isNormalize, - int _nOctaves, int _nOctaveLayers, int _firstOctave ) +SIFT::SIFT( double _magnification, bool _isNormalize, bool _recalculateAngles, int _nOctaves, + int _nOctaveLayers, int _firstOctave, int _angleMode ) { - descriptorParams = DescriptorParams(_magnification, _isNormalize); - commParams = CommonParams(_nOctaves, _nOctaveLayers, _firstOctave); + descriptorParams = DescriptorParams(_magnification, _isNormalize, _recalculateAngles); + commParams = CommonParams(_nOctaves, _nOctaveLayers, _firstOctave, _angleMode); } SIFT::SIFT( const CommonParams& _commParams, @@ -2015,6 +2015,31 @@ inline void ocvKeypointToVl( const KeyPoint& ocvKeypoint, const VL::Sift& vlSift vlKeypoint = vlSift.getKeypoint(ocvKeypoint.pt.x, ocvKeypoint.pt.y, ocvKeypoint.size); } +float computeKeypointOrientations( VL::Sift& sift, const VL::Sift::Keypoint& keypoint, int angleMode ) +{ + float angleVal = -1; + VL::float_t angles[4]; + int angleCount = sift.computeKeypointOrientations(angles, keypoint); + if( angleCount > 0 ) + { + if( angleMode == SIFT::CommonParams::FIRST_ANGLE ) + { + angleVal = angles[0]; + } + else if( angleMode == SIFT::CommonParams::AVERAGE_ANGLE ) + { + for( int i = 0; i < angleCount; i++ ) + angleVal += angles[i]; + angleVal /= angleCount; + } + else + { + assert(0); + } + } + return angleVal; +} + // detectors void SIFT::operator()(const Mat& img, const Mat& mask, vector& keypoints) const @@ -2038,27 +2063,10 @@ void SIFT::operator()(const Mat& img, const Mat& mask, for( VL::Sift::KeypointsConstIter iter = vlsift.keypointsBegin(); iter != vlsift.keypointsEnd(); ++iter ) { - VL::float_t angles[4]; - int angleCount = vlsift.computeKeypointOrientations(angles, *iter); - if( angleCount > 0 ) + float angleVal = computeKeypointOrientations( vlsift, *iter, commParams.angleMode ); + if( angleVal >= 0 ) { - double angleVal = 0; - if( detectorParams.angleMode == DetectorParams::FIRST_ANGLE ) - { - angleVal = angles[0]; - } - else if( detectorParams.angleMode == DetectorParams::AVERAGE_ANGLE ) - { - for( int i = 0; i < angleCount; i++ ) - angleVal += angles[i]; - angleVal /= angleCount; - } - else - { - assert(0); - } - - keypoints.push_back( vlKeypointToOcv(*iter, angleVal*180.0/CV_PI ) ); + keypoints.push_back( vlKeypointToOcv(*iter, angleVal*180.0/CV_PI) ); } } } @@ -2093,6 +2101,13 @@ void SIFT::operator()(const Mat& img, const Mat& mask, { VL::Sift::Keypoint vlkpt; ocvKeypointToVl( *iter, vlsift, vlkpt ); - vlsift.computeKeypointDescriptor((VL::float_t*)descriptors.ptr(pi), vlkpt, iter->angle*CV_PI/180.0); + float angleVal = iter->angle*CV_PI/180.0; + if( descriptorParams.recalculateAngles ) + { + float recalcAngleVal = computeKeypointOrientations( vlsift, vlkpt, commParams.angleMode ); + if( recalcAngleVal >= 0 ) + angleVal = recalcAngleVal; + } + vlsift.computeKeypointDescriptor((VL::float_t*)descriptors.ptr(pi), vlkpt, angleVal); } } diff --git a/modules/features2d/src/surf.cpp b/modules/features2d/src/surf.cpp index 9dd1e844d3..7c96b019a3 100644 --- a/modules/features2d/src/surf.cpp +++ b/modules/features2d/src/surf.cpp @@ -437,7 +437,7 @@ struct SURFInvoker maxSize = std::max(maxSize, ((CvSURFPoint*)cvGetSeqElem( keypoints, k ))->size); maxSize = cvCeil((PATCH_SZ+1)*maxSize*1.2f/9.0f); - Ptr winbuf = cvCreateMat( 1, maxSize*maxSize, CV_8U ); + Ptr winbuf = cvCreateMat( 1, maxSize > 0 ? maxSize*maxSize : 1, CV_8U ); for( k = k1; k < k2; k++ ) { diff --git a/samples/c/detectors_sample.cpp b/samples/c/detectors_sample.cpp index 3c0ca6f955..6031e0aa09 100644 --- a/samples/c/detectors_sample.cpp +++ b/samples/c/detectors_sample.cpp @@ -14,8 +14,7 @@ inline Point2f applyHomography( const Mat_& H, const Point2f& pt ) void drawCorrespondences( const Mat& img1, const Mat& img2, const Mat& transfMtr, const vector& keypoints1, const vector& keypoints2, - const vector& matches, const vector& distances, - float maxDist, Mat& drawImg ) + const vector& matches, float maxDist, Mat& drawImg ) { Scalar RED = CV_RGB(255, 0, 0); Scalar PINK = CV_RGB(255,130,230); @@ -49,9 +48,8 @@ void drawCorrespondences( const Mat& img1, const Mat& img2, const Mat& transfMtr Mat vec1(3, 1, CV_32FC1), vec2; float err = 3; vector::const_iterator mit = matches.begin(); - vector::const_iterator dit = distances.begin(); - assert( matches.size() == distances.size() && matches.size() == keypoints1.size() ); - for( int i1 = 0; mit < matches.end(); ++mit, ++dit, i1++ ) + assert( matches.size() == keypoints1.size() ); + for( int i1 = 0; mit < matches.end(); ++mit, i1++ ) { Point2f pt1 = keypoints1[i1].pt, pt2 = keypoints2[*mit].pt; Point2f diff = applyHomography(transfMtr, pt1) - pt2; @@ -63,12 +61,13 @@ void drawCorrespondences( const Mat& img1, const Mat& img2, const Mat& transfMtr } else { - if( *dit > maxDist ) + /*if( *dit > maxDist ) { circle(drawImg, pt1, 3, PINK); circle(drawImg, Point2f(pt2.x+img1.cols, pt2.y), 3, PINK); } - else + // TODO add key point filter + else*/ { circle(drawImg, pt1, 3, BLUE); circle(drawImg, Point2f(pt2.x+img1.cols, pt2.y), 3, BLUE); @@ -93,8 +92,7 @@ FeatureDetector* createDetector( const string& detectorType ) else if( !detectorType.compare( "SIFT" ) ) { fd = new SiftFeatureDetector(SIFT::DetectorParams::GET_DEFAULT_THRESHOLD(), - SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD(), - SIFT::DetectorParams::FIRST_ANGLE); + SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD()); } else if( !detectorType.compare( "SURF" ) ) { @@ -184,17 +182,16 @@ void iter( Ptr detector, Ptr descriptor, cout << "< Matching keypoints by descriptors... "; vector matches; - vector distances; Ptr matcher = createDescMatcher(); matcher->add( descs2 ); - matcher->match( descs1, matches, &distances ); + matcher->match( descs1, matches ); cout << ">" << endl; // TODO time Mat drawImg; drawCorrespondences( img1, img2, transfMtr, keypoints1, keypoints2, - matches, distances, maxDist, drawImg ); + matches, maxDist, drawImg ); imshow( winName, drawImg); }