updated sift wrapper (recalculation angles mode)
This commit is contained in:
parent
ccbe405322
commit
cd81db88d5
@ -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<KeyPoint>& 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<KeyPoint>& 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<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
|
||||
@ -1479,15 +1484,10 @@ inline void DescriptorMatcher::add( const Mat& descriptors )
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -78,9 +78,9 @@ void DescriptorExtractor::removeBorderKeypoints( vector<KeyPoint>& 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,
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -47,8 +47,8 @@
|
||||
// MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include<iostream>
|
||||
#include<limits>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
#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<KeyPoint>& 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);
|
||||
}
|
||||
}
|
||||
|
@ -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<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++ )
|
||||
{
|
||||
|
@ -14,8 +14,7 @@ inline Point2f applyHomography( const Mat_<double>& H, const Point2f& pt )
|
||||
|
||||
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);
|
||||
@ -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<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;
|
||||
@ -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<FeatureDetector> detector, Ptr<DescriptorExtractor> descriptor,
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user