Commit 99a5f4cf authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

Merge pull request #113 from vpisarev/refactor_features2d_take4

Refactored features2d & xfeatures2d
parents 37c503d4 fba1825a
......@@ -93,10 +93,10 @@ bool CustomPattern::init(Mat& image, const float pixel_size, OutputArray output)
if (!detector) // if no detector chosen, use default
{
detector = FeatureDetector::create("ORB");
detector->set("nFeatures", 2000);
detector->set("scaleFactor", 1.15);
detector->set("nLevels", 30);
detector = ORB::create();
detector->set(ORB::NFEATURES, 2000);
detector->set(ORB::SCALE_FACTOR, 1.15);
detector->set(ORB::NLEVELS, 30);
}
detector->detect(img_roi, keypoints);
......@@ -108,7 +108,7 @@ bool CustomPattern::init(Mat& image, const float pixel_size, OutputArray output)
refineKeypointsPos(img_roi, keypoints);
if (!descriptorExtractor) // if no extractor chosen, use default
descriptorExtractor = DescriptorExtractor::create("ORB");
descriptorExtractor = ORB::create();
descriptorExtractor->compute(img_roi, keypoints, descriptor);
if (!descriptorMatcher)
......
......@@ -191,7 +191,9 @@ int main(int argc, char* argv[])
{
//Extract MSER
vector<vector<Point> > contours;
MSER(21,(int)(0.00002*grey.cols*grey.rows),(int)(0.05*grey.cols*grey.rows),1,0.7)(grey, contours);
vector<Rect> bboxes;
Ptr<MSER> mser = MSER::create(21,(int)(0.00002*grey.cols*grey.rows),(int)(0.05*grey.cols*grey.rows),1,0.7);
mser->detectRegions(grey, contours, bboxes);
//Convert the output of MSER to suitable input for the grouping/recognition algorithms
if (contours.size() > 0)
......
......@@ -47,106 +47,23 @@ namespace cv
namespace xfeatures2d
{
CV_EXPORTS bool initModule_xfeatures2d(void);
/*!
FREAK implementation
*/
class CV_EXPORTS FREAK : public DescriptorExtractor
class CV_EXPORTS FREAK : public Feature2D
{
public:
/** Constructor
* @param orientationNormalized enable orientation normalization
* @param scaleNormalized enable scale normalization
* @param patternScale scaling of the description pattern
* @param nbOctave number of octaves covered by the detected keypoints
* @param selectedPairs (optional) user defined selected pairs
*/
explicit FREAK( bool orientationNormalized = true,
bool scaleNormalized = true,
float patternScale = 22.0f,
int nOctaves = 4,
const std::vector<int>& selectedPairs = std::vector<int>());
FREAK( const FREAK& rhs );
FREAK& operator=( const FREAK& );
virtual ~FREAK();
/** returns the descriptor length in bytes */
virtual int descriptorSize() const;
/** returns the descriptor type */
virtual int descriptorType() const;
/** returns the default norm type */
virtual int defaultNorm() const;
/** select the 512 "best description pairs"
* @param images grayscale images set
* @param keypoints set of detected keypoints
* @param corrThresh correlation threshold
* @param verbose print construction information
* @return list of best pair indexes
*/
std::vector<int> selectPairs( const std::vector<Mat>& images, std::vector<std::vector<KeyPoint> >& keypoints,
const double corrThresh = 0.7, bool verbose = true );
AlgorithmInfo* info() const;
enum
{
NB_SCALES = 64, NB_PAIRS = 512, NB_ORIENPAIRS = 45
};
protected:
virtual void computeImpl( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const;
void buildPattern();
template <typename imgType, typename iiType>
imgType meanIntensity( InputArray image, InputArray integral, const float kp_x, const float kp_y,
const unsigned int scale, const unsigned int rot, const unsigned int point ) const;
template <typename srcMatType, typename iiMatType>
void computeDescriptors( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const;
template <typename srcMatType>
void extractDescriptor(srcMatType *pointsValue, void ** ptr) const;
bool orientationNormalized; //true if the orientation is normalized, false otherwise
bool scaleNormalized; //true if the scale is normalized, false otherwise
double patternScale; //scaling of the pattern
int nOctaves; //number of octaves
bool extAll; // true if all pairs need to be extracted for pairs selection
double patternScale0;
int nOctaves0;
std::vector<int> selectedPairs0;
struct PatternPoint
{
float x; // x coordinate relative to center
float y; // x coordinate relative to center
float sigma; // Gaussian smoothing sigma
};
struct DescriptionPair
{
uchar i; // index of the first point
uchar j; // index of the second point
};
struct OrientationPair
{
uchar i; // index of the first point
uchar j; // index of the second point
int weight_dx; // dx/(norm_sq))*4096
int weight_dy; // dy/(norm_sq))*4096
};
std::vector<PatternPoint> patternLookup; // look-up table for the pattern points (position+sigma of all points at all scales and orientation)
int patternSizes[NB_SCALES]; // size of the pattern at a specific scale (used to check if a point is within image boundaries)
DescriptionPair descriptionPairs[NB_PAIRS];
OrientationPair orientationPairs[NB_ORIENPAIRS];
static Ptr<FREAK> create(bool orientationNormalized = true,
bool scaleNormalized = true,
float patternScale = 22.0f,
int nOctaves = 4,
const std::vector<int>& selectedPairs = std::vector<int>());
};
......@@ -155,63 +72,23 @@ protected:
The class implements the keypoint detector introduced by K. Konolige.
*/
class CV_EXPORTS_W StarDetector : public FeatureDetector
class CV_EXPORTS StarDetector : public FeatureDetector
{
public:
//! the full constructor
CV_WRAP StarDetector(int _maxSize=45, int _responseThreshold=30,
int _lineThresholdProjected=10,
int _lineThresholdBinarized=8,
int _suppressNonmaxSize=5);
//! finds the keypoints in the image
CV_WRAP_AS(detect) void operator()(const Mat& image,
CV_OUT std::vector<KeyPoint>& keypoints) const;
AlgorithmInfo* info() const;
protected:
void detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() ) const;
int maxSize;
int responseThreshold;
int lineThresholdProjected;
int lineThresholdBinarized;
int suppressNonmaxSize;
static Ptr<StarDetector> create(int maxSize=45, int responseThreshold=30,
int lineThresholdProjected=10,
int lineThresholdBinarized=8,
int suppressNonmaxSize=5);
};
typedef StarDetector StarFeatureDetector;
/*
* BRIEF Descriptor
*/
class CV_EXPORTS BriefDescriptorExtractor : public DescriptorExtractor
{
public:
static const int PATCH_SIZE = 48;
static const int KERNEL_SIZE = 9;
// bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.
BriefDescriptorExtractor( int bytes = 32 );
virtual void read( const FileNode& );
virtual void write( FileStorage& ) const;
virtual int descriptorSize() const;
virtual int descriptorType() const;
virtual int defaultNorm() const;
/// @todo read and write for brief
AlgorithmInfo* info() const;
protected:
virtual void computeImpl(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors) const;
typedef void(*PixelTestFn)(InputArray, const std::vector<KeyPoint>&, OutputArray);
int bytes_;
PixelTestFn test_fn_;
static Ptr<BriefDescriptorExtractor> create( int bytes = 32 );
};
}
......
......@@ -58,45 +58,9 @@ namespace xfeatures2d
class CV_EXPORTS_W SIFT : public Feature2D
{
public:
CV_WRAP explicit SIFT( int nfeatures = 0, int nOctaveLayers = 3,
double contrastThreshold = 0.04, double edgeThreshold = 10,
double sigma = 1.6);
//! returns the descriptor size in floats (128)
CV_WRAP int descriptorSize() const;
//! returns the descriptor type
CV_WRAP int descriptorType() const;
//! returns the default norm type
CV_WRAP int defaultNorm() const;
//! finds the keypoints using SIFT algorithm
void operator()(InputArray img, InputArray mask,
std::vector<KeyPoint>& keypoints) const;
//! finds the keypoints and computes descriptors for them using SIFT algorithm.
//! Optionally it can compute descriptors for the user-provided keypoints
void operator()(InputArray img, InputArray mask,
std::vector<KeyPoint>& keypoints,
OutputArray descriptors,
bool useProvidedKeypoints = false) const;
AlgorithmInfo* info() const;
void buildGaussianPyramid( const Mat& base, std::vector<Mat>& pyr, int nOctaves ) const;
void buildDoGPyramid( const std::vector<Mat>& pyr, std::vector<Mat>& dogpyr ) const;
void findScaleSpaceExtrema( const std::vector<Mat>& gauss_pyr, const std::vector<Mat>& dog_pyr,
std::vector<KeyPoint>& keypoints ) const;
protected:
void detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask = noArray() ) const;
void computeImpl( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const;
CV_PROP_RW int nfeatures;
CV_PROP_RW int nOctaveLayers;
CV_PROP_RW double contrastThreshold;
CV_PROP_RW double edgeThreshold;
CV_PROP_RW double sigma;
CV_WRAP static Ptr<SIFT> create( int nfeatures = 0, int nOctaveLayers = 3,
double contrastThreshold = 0.04, double edgeThreshold = 10,
double sigma = 1.6);
};
typedef SIFT SiftFeatureDetector;
......@@ -110,42 +74,10 @@ typedef SIFT SiftDescriptorExtractor;
class CV_EXPORTS_W SURF : public Feature2D
{
public:
//! the default constructor
CV_WRAP SURF();
//! the full constructor taking all the necessary parameters
explicit CV_WRAP SURF(double hessianThreshold,
int nOctaves = 4, int nOctaveLayers = 2,
bool extended = true, bool upright = false);
//! returns the descriptor size in float's (64 or 128)
CV_WRAP int descriptorSize() const;
//! returns the descriptor type
CV_WRAP int descriptorType() const;
//! returns the descriptor type
CV_WRAP int defaultNorm() const;
//! finds the keypoints using fast hessian detector used in SURF
void operator()(InputArray img, InputArray mask,
CV_OUT std::vector<KeyPoint>& keypoints) const;
//! finds the keypoints and computes their descriptors. Optionally it can compute descriptors for the user-provided keypoints
void operator()(InputArray img, InputArray mask,
CV_OUT std::vector<KeyPoint>& keypoints,
OutputArray descriptors,
bool useProvidedKeypoints = false) const;
AlgorithmInfo* info() const;
CV_PROP_RW double hessianThreshold;
CV_PROP_RW int nOctaves;
CV_PROP_RW int nOctaveLayers;
CV_PROP_RW bool extended;
CV_PROP_RW bool upright;
protected:
void detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask = noArray() ) const;
void computeImpl( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const;
enum { HESSIAN_THRESHOLD = 10000, NOCTAVES=10001, NOCTAVE_LAYERS=10002, EXTENDED=10003, UPRIGHT=10004 };
CV_WRAP static Ptr<SURF> create(double hessianThreshold=100,
int nOctaves = 4, int nOctaveLayers = 3,
bool extended = false, bool upright = false);
};
typedef SURF SurfFeatureDetector;
......
......@@ -21,10 +21,10 @@ PERF_TEST_P(surf, detect, testing::Values(SURF_IMAGES))
Mat mask;
declare.in(frame).time(90);
SURF detector;
Ptr<SURF> detector = SURF::create();
vector<KeyPoint> points;
TEST_CYCLE() detector(frame, mask, points);
TEST_CYCLE() detector->detect(frame, points, mask);
SANITY_CHECK_KEYPOINTS(points, 1e-3);
}
......@@ -38,12 +38,12 @@ PERF_TEST_P(surf, extract, testing::Values(SURF_IMAGES))
Mat mask;
declare.in(frame).time(90);
SURF detector;
Ptr<SURF> detector = SURF::create();
vector<KeyPoint> points;
vector<float> descriptors;
detector(frame, mask, points);
detector->detect(frame, points, mask);
TEST_CYCLE() detector(frame, mask, points, descriptors, true);
TEST_CYCLE() detector->compute(frame, points, descriptors);
SANITY_CHECK(descriptors, 1e-4);
}
......@@ -56,11 +56,11 @@ PERF_TEST_P(surf, full, testing::Values(SURF_IMAGES))
Mat mask;
declare.in(frame).time(90);
SURF detector;
Ptr<SURF> detector = SURF::create();
vector<KeyPoint> points;
vector<float> descriptors;
TEST_CYCLE() detector(frame, mask, points, descriptors, false);
TEST_CYCLE() detector->detectAndCompute(frame, mask, points, descriptors, false);
SANITY_CHECK_KEYPOINTS(points, 1e-3);
SANITY_CHECK(descriptors, 1e-4);
......
......@@ -2512,6 +2512,23 @@ static void computeGnuPlotOutput( const string& resPath, const string& objClassN
vocData.savePrecRecallToGnuplot( resPath + plotsDir + "/" + plotFile, precision, recall, ap, objClassName, CV_VOC_PLOT_PNG );
}
static Ptr<Feature2D> createByName(const String& name)
{
if( name == "SIFT" )
return SIFT::create();
if( name == "SURF" )
return SURF::create();
if( name == "ORB" )
return ORB::create();
if( name == "BRISK" )
return BRISK::create();
if( name == "KAZE" )
return KAZE::create();
if( name == "AKAZE" )
return AKAZE::create();
return Ptr<Feature2D>();
}
int main(int argc, char** argv)
{
if( argc != 3 && argc != 6 )
......@@ -2520,9 +2537,6 @@ int main(int argc, char** argv)
return -1;
}
initModule_features2d();
initModule_xfeatures2d();
const string vocPath = argv[1], resPath = argv[2];
// Read or set default parameters
......@@ -2563,8 +2577,13 @@ int main(int argc, char** argv)
}
// Create detector, descriptor, matcher.
Ptr<FeatureDetector> featureDetector = FeatureDetector::create( ddmParams.detectorType );
Ptr<DescriptorExtractor> descExtractor = DescriptorExtractor::create( ddmParams.descriptorType );
if( ddmParams.detectorType != ddmParams.descriptorType )
{
cout << "detector and descriptor should be the same\n";
return -1;
}
Ptr<Feature2D> featureDetector = createByName( ddmParams.detectorType );
Ptr<DescriptorExtractor> descExtractor = featureDetector;
Ptr<BOWImgDescriptorExtractor> bowExtractor;
if( !featureDetector || !descExtractor )
{
......
......@@ -34,20 +34,15 @@ int main(int argc, char** argv)
return -1;
}
// detecting keypoints
SurfFeatureDetector detector(5000);
// detecting keypoints & computing descriptors
Ptr<SURF> surf = SURF::create(5000);
vector<KeyPoint> keypoints1, keypoints2;
detector.detect(img1, keypoints1);
detector.detect(img2, keypoints2);
// computing descriptors
SurfDescriptorExtractor extractor;
Mat descriptors1, descriptors2;
extractor.compute(img1, keypoints1, descriptors1);
extractor.compute(img2, keypoints2, descriptors2);
surf->detectAndCompute(img1, Mat(), keypoints1, descriptors1);
surf->detectAndCompute(img2, Mat(), keypoints2, descriptors2);
// matching descriptors
BFMatcher matcher(extractor.defaultNorm());
BFMatcher matcher(surf->defaultNorm());
vector<DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);
......
......@@ -35,18 +35,17 @@ static double getTime()
return work_end /((double)getTickFrequency() )* 1000.;
}
template<class KPDetector>
struct SURFDetector
{
KPDetector surf;
Ptr<Feature2D> surf;
SURFDetector(double hessian = 800.0)
:surf(hessian)
{
surf = SURF::create(hessian);
}
template<class T>
void operator()(const T& in, const T& mask, std::vector<cv::KeyPoint>& pts, T& descriptors, bool useProvided = false)
{
surf(in, mask, pts, descriptors, useProvided);
surf->detectAndCompute(in, mask, pts, descriptors, useProvided);
}
};
......@@ -191,7 +190,7 @@ int main(int argc, char* argv[])
descriptors2 = _descriptors2.getMat(ACCESS_RW);
//instantiate detectors/matchers
SURFDetector<SURF> surf;
SURFDetector surf;
SURFMatcher<BFMatcher> matcher;
......
......@@ -123,7 +123,7 @@ int main(int ac, char ** av)
return 1;
}
BriefDescriptorExtractor brief(32);
Ptr<BriefDescriptorExtractor> brief = BriefDescriptorExtractor::create(32);
VideoCapture capture;
capture.open(atoi(av[1]));
......@@ -143,7 +143,7 @@ int main(int ac, char ** av)
vector<DMatch> matches;
BFMatcher desc_matcher(brief.defaultNorm());
BFMatcher desc_matcher(brief->defaultNorm());
vector<Point2f> train_pts, query_pts;
vector<KeyPoint> train_kpts, query_kpts;
......@@ -154,7 +154,7 @@ int main(int ac, char ** av)
bool ref_live = true;
Mat train_desc, query_desc;
FastFeatureDetector detector(10, true);
Ptr<FastFeatureDetector> detector = FastFeatureDetector::create(10, true);
Mat H_prev = Mat::eye(3, 3, CV_32FC1);
for (;;)
......@@ -165,9 +165,8 @@ int main(int ac, char ** av)
cvtColor(frame, gray, COLOR_RGB2GRAY);
detector.detect(gray, query_kpts); //Find interest points
brief.compute(gray, query_kpts, query_desc); //Compute brief descriptors at each keypoint location
detector->detect(gray, query_kpts); //Find interest points
brief->compute(gray, query_kpts, query_desc); //Compute brief descriptors at each keypoint location
if (!train_kpts.empty())
{
......
......@@ -52,9 +52,41 @@ namespace cv
namespace xfeatures2d
{
/*
* BRIEF Descriptor
*/
class BriefDescriptorExtractorImpl : public BriefDescriptorExtractor
{
public:
enum { PATCH_SIZE = 48, KERNEL_SIZE = 9 };
// bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.
BriefDescriptorExtractorImpl( int bytes = 32 );
virtual void read( const FileNode& );
virtual void write( FileStorage& ) const;
virtual int descriptorSize() const;
virtual int descriptorType() const;
virtual int defaultNorm() const;
virtual void compute(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors);
protected:
typedef void(*PixelTestFn)(InputArray, const std::vector<KeyPoint>&, OutputArray);
int bytes_;
PixelTestFn test_fn_;
};
Ptr<BriefDescriptorExtractor> BriefDescriptorExtractor::create( int bytes )
{
return makePtr<BriefDescriptorExtractorImpl>(bytes);
}
inline int smoothedSum(const Mat& sum, const KeyPoint& pt, int y, int x)
{
static const int HALF_KERNEL = BriefDescriptorExtractor::KERNEL_SIZE / 2;
static const int HALF_KERNEL = BriefDescriptorExtractorImpl::KERNEL_SIZE / 2;
int img_y = (int)(pt.pt.y + 0.5) + y;
int img_x = (int)(pt.pt.x + 0.5) + x;
......@@ -99,7 +131,7 @@ static void pixelTests64(InputArray _sum, const std::vector<KeyPoint>& keypoints
}
}
BriefDescriptorExtractor::BriefDescriptorExtractor(int bytes) :
BriefDescriptorExtractorImpl::BriefDescriptorExtractorImpl(int bytes) :
bytes_(bytes), test_fn_(NULL)
{
switch (bytes)
......@@ -118,22 +150,22 @@ BriefDescriptorExtractor::BriefDescriptorExtractor(int bytes) :
}
}
int BriefDescriptorExtractor::descriptorSize() const
int BriefDescriptorExtractorImpl::descriptorSize() const
{
return bytes_;
}
int BriefDescriptorExtractor::descriptorType() const
int BriefDescriptorExtractorImpl::descriptorType() const
{
return CV_8UC1;
}
int BriefDescriptorExtractor::defaultNorm() const
int BriefDescriptorExtractorImpl::defaultNorm() const
{
return NORM_HAMMING;
}
void BriefDescriptorExtractor::read( const FileNode& fn)
void BriefDescriptorExtractorImpl::read( const FileNode& fn)
{
int dSize = fn["descriptorSize"];
switch (dSize)
......@@ -153,12 +185,14 @@ void BriefDescriptorExtractor::read( const FileNode& fn)
bytes_ = dSize;
}
void BriefDescriptorExtractor::write( FileStorage& fs) const
void BriefDescriptorExtractorImpl::write( FileStorage& fs) const
{
fs << "descriptorSize" << bytes_;
}
void BriefDescriptorExtractor::computeImpl(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors) const
void BriefDescriptorExtractorImpl::compute(InputArray image,
std::vector<KeyPoint>& keypoints,
OutputArray descriptors)
{
// Construct integral image for fast smoothing (box filter)
Mat sum;
......
......@@ -46,6 +46,99 @@ namespace cv
namespace xfeatures2d
{
/*!
FREAK implementation
*/
class FREAK_Impl : public FREAK
{
public:
/** Constructor
* @param orientationNormalized enable orientation normalization
* @param scaleNormalized enable scale normalization
* @param patternScale scaling of the description pattern
* @param nbOctave number of octaves covered by the detected keypoints
* @param selectedPairs (optional) user defined selected pairs
*/
explicit FREAK_Impl( bool orientationNormalized = true,
bool scaleNormalized = true,
float patternScale = 22.0f,
int nOctaves = 4,
const std::vector<int>& selectedPairs = std::vector<int>());
virtual ~FREAK_Impl();
/** returns the descriptor length in bytes */
virtual int descriptorSize() const;
/** returns the descriptor type */
virtual int descriptorType() const;
/** returns the default norm type */
virtual int defaultNorm() const;
/** select the 512 "best description pairs"
* @param images grayscale images set
* @param keypoints set of detected keypoints
* @param corrThresh correlation threshold
* @param verbose print construction information
* @return list of best pair indexes
*/
std::vector<int> selectPairs( const std::vector<Mat>& images, std::vector<std::vector<KeyPoint> >& keypoints,
const double corrThresh = 0.7, bool verbose = true );
virtual void compute( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors );
protected:
void buildPattern();
template <typename imgType, typename iiType>
imgType meanIntensity( InputArray image, InputArray integral, const float kp_x, const float kp_y,
const unsigned int scale, const unsigned int rot, const unsigned int point );
template <typename srcMatType, typename iiMatType>
void computeDescriptors( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors );
template <typename srcMatType>
void extractDescriptor(srcMatType *pointsValue, void ** ptr);
bool orientationNormalized; //true if the orientation is normalized, false otherwise
bool scaleNormalized; //true if the scale is normalized, false otherwise
double patternScale; //scaling of the pattern
int nOctaves; //number of octaves
bool extAll; // true if all pairs need to be extracted for pairs selection
double patternScale0;
int nOctaves0;
std::vector<int> selectedPairs0;
struct PatternPoint
{
float x; // x coordinate relative to center
float y; // x coordinate relative to center
float sigma; // Gaussian smoothing sigma
};
struct DescriptionPair
{
uchar i; // index of the first point
uchar j; // index of the second point
};
struct OrientationPair
{
uchar i; // index of the first point
uchar j; // index of the second point
int weight_dx; // dx/(norm_sq))*4096
int weight_dy; // dy/(norm_sq))*4096
};
std::vector<PatternPoint> patternLookup; // look-up table for the pattern points (position+sigma of all points at all scales and orientation)
int patternSizes[NB_SCALES]; // size of the pattern at a specific scale (used to check if a point is within image boundaries)
DescriptionPair descriptionPairs[NB_PAIRS];
OrientationPair orientationPairs[NB_ORIENPAIRS];
};
static const double FREAK_LOG2 = 0.693147180559945;
static const int FREAK_NB_ORIENTATION = 256;
static const int FREAK_NB_POINTS = 43;
......@@ -55,7 +148,7 @@ static const int FREAK_NB_PAIRS = FREAK::NB_PAIRS;
static const int FREAK_NB_ORIENPAIRS = FREAK::NB_ORIENPAIRS;
// default pairs
static const int FREAK_DEF_PAIRS[FREAK::NB_PAIRS] =
static const int FREAK_DEF_PAIRS[FREAK_Impl::NB_PAIRS] =
{
404,431,818,511,181,52,311,874,774,543,719,230,417,205,11,
560,149,265,39,306,165,857,250,8,61,15,55,717,44,412,
......@@ -108,7 +201,7 @@ struct sortMean
}
};
void FREAK::buildPattern()
void FREAK_Impl::buildPattern()
{
if( patternScale == patternScale0 && nOctaves == nOctaves0 && !patternLookup.empty() )
return;
......@@ -229,7 +322,7 @@ void FREAK::buildPattern()
}
}
void FREAK::computeImpl( InputArray _image, std::vector<KeyPoint>& keypoints, OutputArray _descriptors ) const
void FREAK_Impl::compute( InputArray _image, std::vector<KeyPoint>& keypoints, OutputArray _descriptors )
{
Mat image = _image.getMat();
if( image.empty() )
......@@ -237,7 +330,7 @@ void FREAK::computeImpl( InputArray _image, std::vector<KeyPoint>& keypoints, Ou
if( keypoints.empty() )
return;
((FREAK*)this)->buildPattern();
((FREAK_Impl*)this)->buildPattern();
// Convert to gray if not already
Mat grayImage = image;
......@@ -271,7 +364,7 @@ void FREAK::computeImpl( InputArray _image, std::vector<KeyPoint>& keypoints, Ou
}
template <typename srcMatType>
void FREAK::extractDescriptor(srcMatType *pointsValue, void ** ptr) const
void FREAK_Impl::extractDescriptor(srcMatType *pointsValue, void ** ptr)
{
std::bitset<FREAK_NB_PAIRS>** ptrScalar = (std::bitset<FREAK_NB_PAIRS>**) ptr;
......@@ -293,7 +386,7 @@ void FREAK::extractDescriptor(srcMatType *pointsValue, void ** ptr) const
#if CV_SSE2
template <>
void FREAK::extractDescriptor(uchar *pointsValue, void ** ptr) const
void FREAK_Impl::extractDescriptor(uchar *pointsValue, void ** ptr)
{
__m128i** ptrSSE = (__m128i**) ptr;
......@@ -352,7 +445,7 @@ void FREAK::extractDescriptor(uchar *pointsValue, void ** ptr) const
#endif
template <typename srcMatType, typename iiMatType>
void FREAK::computeDescriptors( InputArray _image, std::vector<KeyPoint>& keypoints, OutputArray _descriptors ) const {
void FREAK_Impl::computeDescriptors( InputArray _image, std::vector<KeyPoint>& keypoints, OutputArray _descriptors ){
Mat image = _image.getMat();
Mat imgIntegral;
......@@ -529,12 +622,13 @@ void FREAK::computeDescriptors( InputArray _image, std::vector<KeyPoint>& keypoi
// simply take average on a square patch, not even gaussian approx
template <typename imgType, typename iiType>
imgType FREAK::meanIntensity( InputArray _image, InputArray _integral,
imgType FREAK_Impl::meanIntensity( InputArray _image, InputArray _integral,
const float kp_x,
const float kp_y,
const unsigned int scale,
const unsigned int rot,
const unsigned int point) const {
const unsigned int point)
{
Mat image = _image.getMat(), integral = _integral.getMat();
// get point position in image
const PatternPoint& FreakPoint = patternLookup[scale*FREAK_NB_ORIENTATION*FREAK_NB_POINTS + rot*FREAK_NB_POINTS + point];
......@@ -584,7 +678,7 @@ imgType FREAK::meanIntensity( InputArray _image, InputArray _integral,
}
// pair selection algorithm from a set of training images and corresponding keypoints
std::vector<int> FREAK::selectPairs(const std::vector<Mat>& images
std::vector<int> FREAK_Impl::selectPairs(const std::vector<Mat>& images
, std::vector<std::vector<KeyPoint> >& keypoints
, const double corrTresh
, bool verbose )
......@@ -599,7 +693,7 @@ std::vector<int> FREAK::selectPairs(const std::vector<Mat>& images
for( size_t i = 0;i < images.size(); ++i )
{
Mat descriptorsTmp;
computeImpl(images[i],keypoints[i],descriptorsTmp);
compute(images[i],keypoints[i],descriptorsTmp);
descriptors.push_back(descriptorsTmp);
}
......@@ -705,31 +799,41 @@ void FREAKImpl::drawPattern()
// -------------------------------------------------
/* FREAK interface implementation */
FREAK::FREAK( bool _orientationNormalized, bool _scaleNormalized
FREAK_Impl::FREAK_Impl( bool _orientationNormalized, bool _scaleNormalized
, float _patternScale, int _nOctaves, const std::vector<int>& _selectedPairs )
: orientationNormalized(_orientationNormalized), scaleNormalized(_scaleNormalized),
patternScale(_patternScale), nOctaves(_nOctaves), extAll(false), nOctaves0(0), selectedPairs0(_selectedPairs)
{
}
FREAK::~FREAK()
FREAK_Impl::~FREAK_Impl()
{
}
int FREAK::descriptorSize() const
int FREAK_Impl::descriptorSize() const
{
return FREAK_NB_PAIRS / 8; // descriptor length in bytes
}
int FREAK::descriptorType() const
int FREAK_Impl::descriptorType() const
{
return CV_8U;
}
int FREAK::defaultNorm() const
int FREAK_Impl::defaultNorm() const
{
return NORM_HAMMING;
}
Ptr<FREAK> FREAK::create(bool orientationNormalized,
bool scaleNormalized,
float patternScale,
int nOctaves,
const std::vector<int>& selectedPairs)
{
return makePtr<FREAK_Impl>(orientationNormalized, scaleNormalized,
patternScale, nOctaves, selectedPairs);
}
}
} // END NAMESPACE CV
......@@ -111,6 +111,53 @@ namespace cv
namespace xfeatures2d
{
/*!
SIFT implementation.
The class implements SIFT algorithm by D. Lowe.
*/
class SIFT_Impl : public SIFT
{
public:
explicit SIFT_Impl( int nfeatures = 0, int nOctaveLayers = 3,
double contrastThreshold = 0.04, double edgeThreshold = 10,
double sigma = 1.6);
//! returns the descriptor size in floats (128)
int descriptorSize() const;
//! returns the descriptor type
int descriptorType() const;
//! returns the default norm type
int defaultNorm() const;
//! finds the keypoints and computes descriptors for them using SIFT algorithm.
//! Optionally it can compute descriptors for the user-provided keypoints
void detectAndCompute(InputArray img, InputArray mask,
std::vector<KeyPoint>& keypoints,
OutputArray descriptors,
bool useProvidedKeypoints = false);
void buildGaussianPyramid( const Mat& base, std::vector<Mat>& pyr, int nOctaves ) const;
void buildDoGPyramid( const std::vector<Mat>& pyr, std::vector<Mat>& dogpyr ) const;
void findScaleSpaceExtrema( const std::vector<Mat>& gauss_pyr, const std::vector<Mat>& dog_pyr,
std::vector<KeyPoint>& keypoints ) const;
protected:
CV_PROP_RW int nfeatures;
CV_PROP_RW int nOctaveLayers;
CV_PROP_RW double contrastThreshold;
CV_PROP_RW double edgeThreshold;
CV_PROP_RW double sigma;
};
Ptr<SIFT> SIFT::create( int _nfeatures, int _nOctaveLayers,
double _contrastThreshold, double _edgeThreshold, double _sigma )
{
return makePtr<SIFT_Impl>(_nfeatures, _nOctaveLayers, _contrastThreshold, _edgeThreshold, _sigma);
}
/******************************* Defs and macros *****************************/
// default width of descriptor histogram array
......@@ -196,7 +243,7 @@ static Mat createInitialImage( const Mat& img, bool doubleImageSize, float sigma
}
void SIFT::buildGaussianPyramid( const Mat& base, std::vector<Mat>& pyr, int nOctaves ) const
void SIFT_Impl::buildGaussianPyramid( const Mat& base, std::vector<Mat>& pyr, int nOctaves ) const
{
std::vector<double> sig(nOctaveLayers + 3);
pyr.resize(nOctaves*(nOctaveLayers + 3));
......@@ -236,7 +283,7 @@ void SIFT::buildGaussianPyramid( const Mat& base, std::vector<Mat>& pyr, int nOc
}
void SIFT::buildDoGPyramid( const std::vector<Mat>& gpyr, std::vector<Mat>& dogpyr ) const
void SIFT_Impl::buildDoGPyramid( const std::vector<Mat>& gpyr, std::vector<Mat>& dogpyr ) const
{
int nOctaves = (int)gpyr.size()/(nOctaveLayers + 3);
dogpyr.resize( nOctaves*(nOctaveLayers + 2) );
......@@ -434,7 +481,7 @@ static bool adjustLocalExtrema( const std::vector<Mat>& dog_pyr, KeyPoint& kpt,
//
// Detects features at extrema in DoG scale space. Bad features are discarded
// based on contrast and ratio of principal curvatures.
void SIFT::findScaleSpaceExtrema( const std::vector<Mat>& gauss_pyr, const std::vector<Mat>& dog_pyr,
void SIFT_Impl::findScaleSpaceExtrema( const std::vector<Mat>& gauss_pyr, const std::vector<Mat>& dog_pyr,
std::vector<KeyPoint>& keypoints ) const
{
int nOctaves = (int)gauss_pyr.size()/(nOctaveLayers + 3);
......@@ -687,40 +734,33 @@ static void calcDescriptors(const std::vector<Mat>& gpyr, const std::vector<KeyP
//////////////////////////////////////////////////////////////////////////////////////////
SIFT::SIFT( int _nfeatures, int _nOctaveLayers,
SIFT_Impl::SIFT_Impl( int _nfeatures, int _nOctaveLayers,
double _contrastThreshold, double _edgeThreshold, double _sigma )
: nfeatures(_nfeatures), nOctaveLayers(_nOctaveLayers),
contrastThreshold(_contrastThreshold), edgeThreshold(_edgeThreshold), sigma(_sigma)
{
}
int SIFT::descriptorSize() const
int SIFT_Impl::descriptorSize() const
{
return SIFT_DESCR_WIDTH*SIFT_DESCR_WIDTH*SIFT_DESCR_HIST_BINS;
}
int SIFT::descriptorType() const
int SIFT_Impl::descriptorType() const
{
return CV_32F;
}
int SIFT::defaultNorm() const
int SIFT_Impl::defaultNorm() const
{
return NORM_L2;
}
void SIFT::operator()(InputArray _image, InputArray _mask,
std::vector<KeyPoint>& keypoints) const
{
(*this)(_image, _mask, keypoints, noArray());
}
void SIFT::operator()(InputArray _image, InputArray _mask,
void SIFT_Impl::detectAndCompute(InputArray _image, InputArray _mask,
std::vector<KeyPoint>& keypoints,
OutputArray _descriptors,
bool useProvidedKeypoints) const
bool useProvidedKeypoints)
{
int firstOctave = -1, actualNOctaves = 0, actualNLayers = 0;
Mat image = _image.getMat(), mask = _mask.getMat();
......@@ -805,15 +845,5 @@ void SIFT::operator()(InputArray _image, InputArray _mask,
}
}
void SIFT::detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask) const
{
(*this)(image.getMat(), mask.getMat(), keypoints, noArray());
}
void SIFT::computeImpl( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors) const
{
(*this)(image, Mat(), keypoints, descriptors, true);
}
}
}
......@@ -46,6 +46,43 @@ namespace cv
namespace xfeatures2d
{
/*!
The "Star" Detector.
The class implements the keypoint detector introduced by K. Konolige.
*/
class StarDetectorImpl : public StarDetector
{
public:
//! the full constructor
StarDetectorImpl(int _maxSize=45, int _responseThreshold=30,
int _lineThresholdProjected=10,
int _lineThresholdBinarized=8,
int _suppressNonmaxSize=5);
void detect( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() );
protected:
int maxSize;
int responseThreshold;
int lineThresholdProjected;
int lineThresholdBinarized;
int suppressNonmaxSize;
};
Ptr<StarDetector> StarDetector::create(int _maxSize,
int _responseThreshold,
int _lineThresholdProjected,
int _lineThresholdBinarized,
int _suppressNonmaxSize)
{
return makePtr<StarDetectorImpl>(_maxSize, _responseThreshold,
_lineThresholdProjected,
_lineThresholdBinarized,
_suppressNonmaxSize);
}
template <typename inMatType, typename outMatType> static void
computeIntegralImages( const Mat& matI, Mat& matS, Mat& matT, Mat& _FT,
int iiType )
......@@ -432,7 +469,7 @@ StarDetectorSuppressNonmax( const Mat& responses, const Mat& sizes,
}
}
StarDetector::StarDetector(int _maxSize, int _responseThreshold,
StarDetectorImpl::StarDetectorImpl(int _maxSize, int _responseThreshold,
int _lineThresholdProjected,
int _lineThresholdBinarized,
int _suppressNonmaxSize)
......@@ -443,32 +480,32 @@ StarDetector::StarDetector(int _maxSize, int _responseThreshold,
{}
void StarDetector::detectImpl( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask ) const
void StarDetectorImpl::detect( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask )
{
Mat image = _image.getMat(), mask = _mask.getMat(), grayImage = image;
if( image.empty() )
{
keypoints.clear();
return;
}
if( image.channels() > 1 ) cvtColor( image, grayImage, COLOR_BGR2GRAY );
(*this)(grayImage, keypoints);
KeyPointsFilter::runByPixelsMask( keypoints, mask );
}
void StarDetector::operator()(const Mat& img, std::vector<KeyPoint>& keypoints) const
{
Mat responses, sizes;
int border;
// Use 32-bit integers if we won't overflow in the integral image
if ((img.depth() == CV_8U || img.depth() == CV_8S) &&
(img.rows * img.cols) < 8388608 ) // 8388608 = 2 ^ (32 - 8(bit depth) - 1(sign bit))
border = StarDetectorComputeResponses<int>( img, responses, sizes, maxSize, CV_32S );
if ((grayImage.depth() == CV_8U || grayImage.depth() == CV_8S) &&
(int)grayImage.total() < 8388608 ) // 8388608 = 2 ^ (32 - 8(bit depth) - 1(sign bit))
border = StarDetectorComputeResponses<int>( grayImage, responses, sizes, maxSize, CV_32S );
else
border = StarDetectorComputeResponses<double>( img, responses, sizes, maxSize, CV_64F );
border = StarDetectorComputeResponses<double>( grayImage, responses, sizes, maxSize, CV_64F );
keypoints.clear();
if( border >= 0 )
StarDetectorSuppressNonmax( responses, sizes, keypoints, border,
responseThreshold, lineThresholdProjected,
lineThresholdBinarized, suppressNonmaxSize );
responseThreshold, lineThresholdProjected,
lineThresholdBinarized, suppressNonmaxSize );
KeyPointsFilter::runByPixelsMask( keypoints, mask );
}
}
......
......@@ -867,16 +867,7 @@ struct SURFInvoker : ParallelLoopBody
};
SURF::SURF()
{
hessianThreshold = 100;
extended = false;
upright = false;
nOctaves = 4;
nOctaveLayers = 3;
}
SURF::SURF(double _threshold, int _nOctaves, int _nOctaveLayers, bool _extended, bool _upright)
SURF_Impl::SURF_Impl(double _threshold, int _nOctaves, int _nOctaveLayers, bool _extended, bool _upright)
{
hessianThreshold = _threshold;
extended = _extended;
......@@ -885,20 +876,49 @@ SURF::SURF(double _threshold, int _nOctaves, int _nOctaveLayers, bool _extended,
nOctaveLayers = _nOctaveLayers;
}
int SURF::descriptorSize() const { return extended ? 128 : 64; }
int SURF::descriptorType() const { return CV_32F; }
int SURF::defaultNorm() const { return NORM_L2; }
void SURF_Impl::set(int prop, double value)
{
if( prop == HESSIAN_THRESHOLD )
hessianThreshold = value;
else if( prop == NOCTAVES )
nOctaves = cvRound(value);
else if( prop == NOCTAVE_LAYERS )
nOctaveLayers = cvRound(value);
else if( prop == EXTENDED )
extended = value != 0;
else if( prop == UPRIGHT )
upright = value != 0;
else
CV_Error(Error::StsBadArg, "");
}
void SURF::operator()(InputArray imgarg, InputArray maskarg,
CV_OUT std::vector<KeyPoint>& keypoints) const
double SURF_Impl::get(int prop) const
{
(*this)(imgarg, maskarg, keypoints, noArray(), false);
double value = 0;
if( prop == HESSIAN_THRESHOLD )
value = hessianThreshold;
else if( prop == NOCTAVES )
value = nOctaves;
else if( prop == NOCTAVE_LAYERS )
value = nOctaveLayers;
else if( prop == EXTENDED )
value = extended;
else if( prop == UPRIGHT )
value = upright;
else
CV_Error(Error::StsBadArg, "");
return value;
}
void SURF::operator()(InputArray _img, InputArray _mask,
int SURF_Impl::descriptorSize() const { return extended ? 128 : 64; }
int SURF_Impl::descriptorType() const { return CV_32F; }
int SURF_Impl::defaultNorm() const { return NORM_L2; }
void SURF_Impl::detectAndCompute(InputArray _img, InputArray _mask,
CV_OUT std::vector<KeyPoint>& keypoints,
OutputArray _descriptors,
bool useProvidedKeypoints) const
bool useProvidedKeypoints)
{
int imgtype = _img.type(), imgcn = CV_MAT_CN(imgtype);
bool doDescriptors = _descriptors.needed();
......@@ -1012,17 +1032,11 @@ void SURF::operator()(InputArray _img, InputArray _mask,
}
}
void SURF::detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask) const
{
(*this)(image.getMat(), mask.getMat(), keypoints, noArray(), false);
}
void SURF::computeImpl( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors) const
Ptr<SURF> SURF::create(double _threshold, int _nOctaves, int _nOctaveLayers, bool _extended, bool _upright)
{
(*this)(image, Mat(), keypoints, descriptors, true);
return makePtr<SURF_Impl>(_threshold, _nOctaves, _nOctaveLayers, _extended, _upright);
}
}
}
......@@ -10,6 +10,44 @@ namespace xfeatures2d
//! Speeded up robust features, port from CUDA module.
////////////////////////////////// SURF //////////////////////////////////////////
/*!
SURF implementation.
The class implements SURF algorithm by H. Bay et al.
*/
class SURF_Impl : public SURF
{
public:
//! the full constructor taking all the necessary parameters
explicit CV_WRAP SURF_Impl(double hessianThreshold,
int nOctaves = 4, int nOctaveLayers = 2,
bool extended = true, bool upright = false);
//! returns the descriptor size in float's (64 or 128)
CV_WRAP int descriptorSize() const;
//! returns the descriptor type
CV_WRAP int descriptorType() const;
//! returns the descriptor type
CV_WRAP int defaultNorm() const;
void set(int, double);
double get(int) const;
//! finds the keypoints and computes their descriptors.
// Optionally it can compute descriptors for the user-provided keypoints
void detectAndCompute(InputArray img, InputArray mask,
CV_OUT std::vector<KeyPoint>& keypoints,
OutputArray descriptors,
bool useProvidedKeypoints = false);
CV_PROP_RW double hessianThreshold;
CV_PROP_RW int nOctaves;
CV_PROP_RW int nOctaveLayers;
CV_PROP_RW bool extended;
CV_PROP_RW bool upright;
};
class SURF_OCL
{
......@@ -29,7 +67,7 @@ public:
//! the full constructor taking all the necessary parameters
SURF_OCL();
bool init(const SURF* params);
bool init(const SURF_Impl* params);
//! returns the descriptor size in float's (64 or 128)
int descriptorSize() const { return params->extended ? 128 : 64; }
......@@ -71,7 +109,7 @@ protected:
bool detectKeypoints(UMat &keypoints);
const SURF* params;
const SURF_Impl* params;
//! max keypoints = min(keypointsRatio * img.size().area(), 65535)
UMat sum, intBuffer;
......
......@@ -79,7 +79,7 @@ SURF_OCL::SURF_OCL()
status = -1;
}
bool SURF_OCL::init(const SURF* p)
bool SURF_OCL::init(const SURF_Impl* p)
{
params = p;
if(status < 0)
......
......@@ -41,59 +41,3 @@
//M*/
#include "precomp.hpp"
namespace cv
{
namespace xfeatures2d
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////
CV_INIT_ALGORITHM(BriefDescriptorExtractor, "Feature2D.BRIEF",
obj.info()->addParam(obj, "bytes", obj.bytes_))
///////////////////////////////////////////////////////////////////////////////////////////////////////////
CV_INIT_ALGORITHM(StarDetector, "Feature2D.STAR",
obj.info()->addParam(obj, "maxSize", obj.maxSize);
obj.info()->addParam(obj, "responseThreshold", obj.responseThreshold);
obj.info()->addParam(obj, "lineThresholdProjected", obj.lineThresholdProjected);
obj.info()->addParam(obj, "lineThresholdBinarized", obj.lineThresholdBinarized);
obj.info()->addParam(obj, "suppressNonmaxSize", obj.suppressNonmaxSize))
///////////////////////////////////////////////////////////////////////////////////////////////////////////
CV_INIT_ALGORITHM(FREAK, "Feature2D.FREAK",
obj.info()->addParam(obj, "orientationNormalized", obj.orientationNormalized);
obj.info()->addParam(obj, "scaleNormalized", obj.scaleNormalized);
obj.info()->addParam(obj, "patternScale", obj.patternScale);
obj.info()->addParam(obj, "nbOctave", obj.nOctaves))
///////////////////////////////////////////////////////////////////////////////////////////////////////////
CV_INIT_ALGORITHM(SURF, "Feature2D.SURF",
obj.info()->addParam(obj, "hessianThreshold", obj.hessianThreshold);
obj.info()->addParam(obj, "nOctaves", obj.nOctaves);
obj.info()->addParam(obj, "nOctaveLayers", obj.nOctaveLayers);
obj.info()->addParam(obj, "extended", obj.extended);
obj.info()->addParam(obj, "upright", obj.upright))
///////////////////////////////////////////////////////////////////////////////////////////////////////////
CV_INIT_ALGORITHM(SIFT, "Feature2D.SIFT",
obj.info()->addParam(obj, "nFeatures", obj.nfeatures);
obj.info()->addParam(obj, "nOctaveLayers", obj.nOctaveLayers);
obj.info()->addParam(obj, "contrastThreshold", obj.contrastThreshold);
obj.info()->addParam(obj, "edgeThreshold", obj.edgeThreshold);
obj.info()->addParam(obj, "sigma", obj.sigma))
///////////////////////////////////////////////////////////////////////////////////////////////////////////
bool initModule_xfeatures2d(void)
{
Ptr<Algorithm> sift = createSIFT_ptr_hidden(), surf = createSURF_ptr_hidden();
return sift->info() != 0 && surf->info() != 0;
}
}
}
......@@ -61,7 +61,7 @@ public:
~CV_DetectorsTest();
protected:
void run(int);
template <class T> bool testDetector(const Mat& img, const T& detector, vector<KeyPoint>& expected);
bool testDetector(const Mat& img, Ptr<Feature2D> detector, vector<KeyPoint>& expected);
void LoadExpected(const string& file, vector<KeyPoint>& out);
};
......@@ -153,10 +153,10 @@ struct WrapPoint
struct sortByR { bool operator()(const KeyPoint& kp1, const KeyPoint& kp2) { return norm(kp1.pt) < norm(kp2.pt); } };
template <class T> bool CV_DetectorsTest::testDetector(const Mat& img, const T& detector, vector<KeyPoint>& exp)
bool CV_DetectorsTest::testDetector(const Mat& img, Ptr<Feature2D> detector, vector<KeyPoint>& exp)
{
vector<KeyPoint> orig_kpts;
detector(img, orig_kpts);
detector->detect(img, orig_kpts);
typedef void (*TransfFunc )(const Mat&, Mat&, Mat& FransfFunc);
const TransfFunc transfFunc[] = { getRotation, getZoom, getBlur, getBrightness };
......@@ -173,7 +173,7 @@ template <class T> bool CV_DetectorsTest::testDetector(const Mat& img, const T&
for(size_t i = 0; i < case_num; ++i)
{
transfFunc[i](img, affs[i], new_imgs[i]);
detector(new_imgs[i], new_kpts[i]);
detector->detect(new_imgs[i], new_kpts[i]);
transform(orig_kpts.begin(), orig_kpts.end(), back_inserter(transf_kpts[i]), WrapPoint(affs[i]));
//show(names[i], new_imgs[i], new_kpts[i], transf_kpts[i]);
}
......@@ -253,14 +253,6 @@ template <class T> bool CV_DetectorsTest::testDetector(const Mat& img, const T&
return true;
}
struct SurfNoMaskWrap
{
const SURF& detector;
SurfNoMaskWrap(const SURF& surf) : detector(surf) {}
SurfNoMaskWrap& operator=(const SurfNoMaskWrap&);
void operator()(const Mat& img, vector<KeyPoint>& kpts) const { detector(img, Mat(), kpts); }
};
void CV_DetectorsTest::LoadExpected(const string& file, vector<KeyPoint>& out)
{
Mat mat_exp;
......@@ -298,14 +290,14 @@ void CV_DetectorsTest::run( int /*start_from*/ )
if (exp.empty())
return;
if (!testDetector(to_test, SurfNoMaskWrap(SURF(1536+512+512, 2)), exp))
if (!testDetector(to_test, SURF::create(1536+512+512, 2, 2, true, false), exp))
return;
LoadExpected(string(ts->get_data_path()) + "detectors/star.xml", exp);
if (exp.empty())
return;
if (!testDetector(to_test, StarDetector(45, 30, 10, 8, 5), exp))
if (!testDetector(to_test, StarDetector::create(45, 30, 10, 8, 5), exp))
return;
ts->set_failed_test_info( cvtest::TS::OK);
......
......@@ -977,19 +977,19 @@ void CV_DescriptorMatcherTest::run( int )
TEST( Features2d_Detector_SIFT, regression )
{
CV_FeatureDetectorTest test( "detector-sift", FeatureDetector::create("SIFT") );
CV_FeatureDetectorTest test( "detector-sift", SIFT::create() );
test.safe_run();
}
TEST( Features2d_Detector_SURF, regression )
{
CV_FeatureDetectorTest test( "detector-surf", FeatureDetector::create("SURF") );
CV_FeatureDetectorTest test( "detector-surf", SURF::create() );
test.safe_run();
}
TEST( Features2d_Detector_STAR, regression )
{
CV_FeatureDetectorTest test( "detector-star", FeatureDetector::create("STAR") );
CV_FeatureDetectorTest test( "detector-star", StarDetector::create() );
test.safe_run();
}
......@@ -999,14 +999,14 @@ TEST( Features2d_Detector_STAR, regression )
TEST( Features2d_DescriptorExtractor_SIFT, regression )
{
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-sift", 0.03f,
DescriptorExtractor::create("SIFT") );
SIFT::create() );
test.safe_run();
}
TEST( Features2d_DescriptorExtractor_SURF, regression )
{
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-surf", 0.05f,
DescriptorExtractor::create("SURF") );
SURF::create() );
test.safe_run();
}
......@@ -1014,14 +1014,14 @@ TEST( Features2d_DescriptorExtractor_FREAK, regression )
{
// TODO adjust the parameters below
CV_DescriptorExtractorTest<Hamming> test( "descriptor-freak", (CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
DescriptorExtractor::create("FREAK") );
FREAK::create() );
test.safe_run();
}
TEST( Features2d_DescriptorExtractor_BRIEF, regression )
{
CV_DescriptorExtractorTest<Hamming> test( "descriptor-brief", 1,
DescriptorExtractor::create("BRIEF") );
BriefDescriptorExtractor::create() );
test.safe_run();
}
......@@ -1049,10 +1049,10 @@ TEST(Features2d_BruteForceDescriptorMatcher_knnMatch, regression)
const int sz = 100;
const int k = 3;
Ptr<DescriptorExtractor> ext = DescriptorExtractor::create("SURF");
Ptr<DescriptorExtractor> ext = SURF::create();
ASSERT_TRUE(ext != NULL);
Ptr<FeatureDetector> det = FeatureDetector::create("SURF");
Ptr<FeatureDetector> det = SURF::create();
//"%YAML:1.0\nhessianThreshold: 8000.\noctaves: 3\noctaveLayers: 4\nupright: 0\n"
ASSERT_TRUE(det != NULL);
......@@ -1104,13 +1104,13 @@ TEST(Features2d_BruteForceDescriptorMatcher_knnMatch, regression)
class CV_DetectPlanarTest : public cvtest::BaseTest
{
public:
CV_DetectPlanarTest(const string& _fname, int _min_ninliers) : fname(_fname), min_ninliers(_min_ninliers) {}
CV_DetectPlanarTest(const string& _fname, int _min_ninliers, const Ptr<Feature2D>& _f2d)
: fname(_fname), min_ninliers(_min_ninliers), f2d(_f2d) {}
protected:
void run(int)
{
Ptr<Feature2D> f = Algorithm::create<Feature2D>("Feature2D." + fname);
if(!f)
if(f2d.empty())
return;
string path = string(ts->get_data_path()) + "detectors_descriptors_evaluation/planar/";
string imgname1 = path + "box.png";
......@@ -1125,15 +1125,15 @@ protected:
}
vector<KeyPoint> kpt1, kpt2;
Mat d1, d2;
f->operator()(img1, Mat(), kpt1, d1);
f->operator()(img1, Mat(), kpt2, d2);
f2d->detectAndCompute(img1, Mat(), kpt1, d1);
f2d->detectAndCompute(img1, Mat(), kpt2, d2);
for( size_t i = 0; i < kpt1.size(); i++ )
CV_Assert(kpt1[i].response > 0 );
for( size_t i = 0; i < kpt2.size(); i++ )
CV_Assert(kpt2[i].response > 0 );
vector<DMatch> matches;
BFMatcher(f->defaultNorm(), true).match(d1, d2, matches);
BFMatcher(f2d->defaultNorm(), true).match(d1, d2, matches);
vector<Point2f> pt1, pt2;
for( size_t i = 0; i < matches.size(); i++ ) {
......@@ -1154,10 +1154,11 @@ protected:
string fname;
int min_ninliers;
Ptr<Feature2D> f2d;
};
TEST(Features2d_SIFTHomographyTest, regression) { CV_DetectPlanarTest test("SIFT", 80); test.safe_run(); }
TEST(Features2d_SURFHomographyTest, regression) { CV_DetectPlanarTest test("SURF", 80); test.safe_run(); }
TEST(Features2d_SIFTHomographyTest, regression) { CV_DetectPlanarTest test("SIFT", 80, SIFT::create()); test.safe_run(); }
TEST(Features2d_SURFHomographyTest, regression) { CV_DetectPlanarTest test("SURF", 80, SURF::create()); test.safe_run(); }
class FeatureDetectorUsingMaskTest : public cvtest::BaseTest
{
......@@ -1222,12 +1223,12 @@ protected:
TEST(Features2d_SIFT_using_mask, regression)
{
FeatureDetectorUsingMaskTest test(Algorithm::create<FeatureDetector>("Feature2D.SIFT"));
FeatureDetectorUsingMaskTest test(SIFT::create());
test.safe_run();
}
TEST(DISABLED_Features2d_SURF_using_mask, regression)
{
FeatureDetectorUsingMaskTest test(Algorithm::create<FeatureDetector>("Feature2D.SURF"));
FeatureDetectorUsingMaskTest test(SURF::create());
test.safe_run();
}
......@@ -55,13 +55,12 @@ const string IMAGE_FILENAME = "tsukuba.png";
class CV_FeatureDetectorKeypointsTest : public cvtest::BaseTest
{
public:
CV_FeatureDetectorKeypointsTest(const Ptr<FeatureDetector>& _detector) :
explicit CV_FeatureDetectorKeypointsTest(const Ptr<Feature2D>& _detector) :
detector(_detector) {}
protected:
virtual void run(int)
{
cv::initModule_features2d();
CV_Assert(detector);
string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME;
......@@ -113,7 +112,7 @@ protected:
ts->set_failed_test_info(cvtest::TS::OK);
}
Ptr<FeatureDetector> detector;
Ptr<Feature2D> detector;
};
......@@ -121,18 +120,18 @@ protected:
TEST(Features2d_Detector_Keypoints_SURF, validation)
{
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.SURF"));
CV_FeatureDetectorKeypointsTest test(xfeatures2d::SURF::create());
test.safe_run();
}
TEST(Features2d_Detector_Keypoints_SIFT, validation)
{
CV_FeatureDetectorKeypointsTest test(FeatureDetector::create("SIFT"));
CV_FeatureDetectorKeypointsTest test(xfeatures2d::SIFT::create());
test.safe_run();
}
TEST(Features2d_Detector_Keypoints_Star, validation)
{
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.STAR"));
CV_FeatureDetectorKeypointsTest test(xfeatures2d::StarDetector::create());
test.safe_run();
}
......@@ -616,7 +616,7 @@ protected:
*/
TEST(Features2d_RotationInvariance_Detector_SURF, regression)
{
DetectorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.SURF"),
DetectorRotationInvarianceTest test(SURF::create(),
0.44f,
0.76f);
test.safe_run();
......@@ -624,7 +624,7 @@ TEST(Features2d_RotationInvariance_Detector_SURF, regression)
TEST(Features2d_RotationInvariance_Detector_SIFT, DISABLED_regression)
{
DetectorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.SIFT"),
DetectorRotationInvarianceTest test(SIFT::create(),
0.45f,
0.70f);
test.safe_run();
......@@ -635,8 +635,8 @@ TEST(Features2d_RotationInvariance_Detector_SIFT, DISABLED_regression)
*/
TEST(Features2d_RotationInvariance_Descriptor_SURF, regression)
{
DescriptorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.SURF"),
Algorithm::create<DescriptorExtractor>("Feature2D.SURF"),
DescriptorRotationInvarianceTest test(SURF::create(),
SURF::create(),
NORM_L1,
0.83f);
test.safe_run();
......@@ -644,8 +644,8 @@ TEST(Features2d_RotationInvariance_Descriptor_SURF, regression)
TEST(Features2d_RotationInvariance_Descriptor_SIFT, regression)
{
DescriptorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.SIFT"),
Algorithm::create<DescriptorExtractor>("Feature2D.SIFT"),
DescriptorRotationInvarianceTest test(SIFT::create(),
SIFT::create(),
NORM_L1,
0.98f);
test.safe_run();
......@@ -656,7 +656,7 @@ TEST(Features2d_RotationInvariance_Descriptor_SIFT, regression)
*/
TEST(Features2d_ScaleInvariance_Detector_SURF, regression)
{
DetectorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.SURF"),
DetectorScaleInvarianceTest test(SURF::create(),
0.64f,
0.84f);
test.safe_run();
......@@ -664,7 +664,7 @@ TEST(Features2d_ScaleInvariance_Detector_SURF, regression)
TEST(Features2d_ScaleInvariance_Detector_SIFT, regression)
{
DetectorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.SIFT"),
DetectorScaleInvarianceTest test(SIFT::create(),
0.69f,
0.99f);
test.safe_run();
......@@ -675,8 +675,8 @@ TEST(Features2d_ScaleInvariance_Detector_SIFT, regression)
*/
TEST(Features2d_ScaleInvariance_Descriptor_SURF, regression)
{
DescriptorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.SURF"),
Algorithm::create<DescriptorExtractor>("Feature2D.SURF"),
DescriptorScaleInvarianceTest test(SURF::create(),
SURF::create(),
NORM_L1,
0.61f);
test.safe_run();
......@@ -684,8 +684,8 @@ TEST(Features2d_ScaleInvariance_Descriptor_SURF, regression)
TEST(Features2d_ScaleInvariance_Descriptor_SIFT, regression)
{
DescriptorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.SIFT"),
Algorithm::create<DescriptorExtractor>("Feature2D.SIFT"),
DescriptorScaleInvarianceTest test(SIFT::create(),
SIFT::create(),
NORM_L1,
0.78f);
test.safe_run();
......@@ -698,11 +698,10 @@ TEST(Features2d_RotationInvariance2_Detector_SURF, regression)
line(cross, Point(30, 50), Point(69, 50), Scalar(100), 3);
line(cross, Point(50, 30), Point(50, 69), Scalar(100), 3);
SURF surf(8000., 3, 4, true, false);
Ptr<SURF> surf = SURF::create(8000., 3, 4, true, false);
vector<KeyPoint> keypoints;
surf(cross, noArray(), keypoints);
surf->detect(cross, keypoints);
ASSERT_EQ(keypoints.size(), (vector<KeyPoint>::size_type) 5);
ASSERT_LT( fabs(keypoints[1].response - keypoints[2].response), 1e-6);
......
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