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
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() );
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<KeyPoint>& keypoints ) const;
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<KeyPoint>& keypoints, Mat& descriptors) const;
* query The query set of descriptors
* matches Indices of the closest matches from the training set
*/
-
-
- // TODO: remove vector<double>* distances = 0 ???
- void match( const Mat& query, vector<int>& matches, vector<double>* distances = 0 ) const;
+ void match( const Mat& query, vector<int>& matches ) const;
/*
* Find the best matches between two descriptor sets, with constraints
}
}
-inline void DescriptorMatcher::match( const Mat& query, vector<int>& matches, vector<double>* distances ) const
+inline void DescriptorMatcher::match( const Mat& query, vector<int>& matches ) const
{
- if( distances )
- matchImpl( query, train, Mat(), matches, *distances );
- else
- {
- vector<double> innDistances;
- matchImpl( query, train, Mat(), matches, innDistances );
- }
+ vector<double> innDistances;
+ matchImpl( query, train, Mat(), matches, innDistances );
}
inline void DescriptorMatcher::match( const Mat& query, const Mat& mask,
/****************************************************************************************\
* 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,
/*
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)
{
}
// MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#include "precomp.hpp"
-#include<iostream>
-#include<limits>
+#include <iostream>
+#include <limits>
#define log2(a) (log((a))/CV_LOG2)
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,
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<KeyPoint>& keypoints) const
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) );
}
}
}
{
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);
}
}
maxSize = std::max(maxSize, ((CvSURFPoint*)cvGetSeqElem( keypoints, k ))->size);
maxSize = cvCeil((PATCH_SZ+1)*maxSize*1.2f/9.0f);
- Ptr<CvMat> winbuf = cvCreateMat( 1, maxSize*maxSize, CV_8U );
+ Ptr<CvMat> winbuf = cvCreateMat( 1, maxSize > 0 ? maxSize*maxSize : 1, CV_8U );
for( k = k1; k < k2; k++ )
{
void drawCorrespondences( const Mat& img1, const Mat& img2, const Mat& transfMtr,
const vector<KeyPoint>& keypoints1, const vector<KeyPoint>& keypoints2,
- const vector<int>& matches, const vector<double>& distances,
- float maxDist, Mat& drawImg )
+ const vector<int>& matches, float maxDist, Mat& drawImg )
{
Scalar RED = CV_RGB(255, 0, 0);
Scalar PINK = CV_RGB(255,130,230);
Mat vec1(3, 1, CV_32FC1), vec2;
float err = 3;
vector<int>::const_iterator mit = matches.begin();
- vector<double>::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;
}
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);
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" ) )
{
cout << "< Matching keypoints by descriptors... ";
vector<int> matches;
- vector<double> distances;
Ptr<DescriptorMatcher> 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);
}