Commit 7e5c11a9 authored by Maria Dimashova's avatar Maria Dimashova

added tests for some detectors; made features2d object create functions as…

added tests for some detectors; made features2d object create functions as static classes methods; fixed OpponentColorDescriptorExtractor, BriefDescriptorExtractor (on rgb); renamed DynamicDetector
parent 9ad7a1c9
...@@ -1250,11 +1250,14 @@ public: ...@@ -1250,11 +1250,14 @@ public:
*/ */
void detect( const vector<Mat>& images, vector<vector<KeyPoint> >& keypoints, const vector<Mat>& masks=vector<Mat>() ) const; void detect( const vector<Mat>& images, vector<vector<KeyPoint> >& keypoints, const vector<Mat>& masks=vector<Mat>() ) const;
// Read detector object from a file node // Read detector object from a file node.
virtual void read( const FileNode& ); virtual void read( const FileNode& );
// Read detector object from a file node // Read detector object from a file node.
virtual void write( FileStorage& ) const; virtual void write( FileStorage& ) const;
// Create feature detector by detector name.
static Ptr<FeatureDetector> create( const string& detectorType );
protected: protected:
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const = 0; virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const = 0;
/* /*
...@@ -1416,7 +1419,7 @@ public: ...@@ -1416,7 +1419,7 @@ public:
* gridRows Grid rows count. * gridRows Grid rows count.
* gridCols Grid column count. * gridCols Grid column count.
*/ */
GridAdaptedFeatureDetector( const Ptr<FeatureDetector>& detector, int maxTotalKeypoints, GridAdaptedFeatureDetector( const Ptr<FeatureDetector>& detector, int maxTotalKeypoints=1000,
int gridRows=4, int gridCols=4 ); int gridRows=4, int gridCols=4 );
// TODO implement read/write // TODO implement read/write
...@@ -1448,19 +1451,15 @@ protected: ...@@ -1448,19 +1451,15 @@ protected:
int levels; int levels;
}; };
/* /** \brief A feature detector parameter adjuster, this is used by the DynamicAdaptedFeatureDetector
* Dynamic Feature Detectors
*/
/** \brief A feature detector parameter adjuster, this is used by the DynamicDetector
* and is a wrapper for FeatureDetector that allow them to be adjusted after a detection * and is a wrapper for FeatureDetector that allow them to be adjusted after a detection
*/ */
class CV_EXPORTS AdjusterAdapter: public FeatureDetector { class CV_EXPORTS AdjusterAdapter: public FeatureDetector
public: {
public:
/** pure virtual interface /** pure virtual interface
*/ */
virtual ~AdjusterAdapter() { virtual ~AdjusterAdapter() {}
}
/** too few features were detected so, adjust the detector params accordingly /** too few features were detected so, adjust the detector params accordingly
* \param min the minimum number of desired features * \param min the minimum number of desired features
* \param n_detected the number previously detected * \param n_detected the number previously detected
...@@ -1475,6 +1474,8 @@ public: ...@@ -1475,6 +1474,8 @@ public:
* \return false if the parameters can't be adjusted any more * \return false if the parameters can't be adjusted any more
*/ */
virtual bool good() const = 0; virtual bool good() const = 0;
static Ptr<AdjusterAdapter> create( const string& detectorType );
}; };
/** \brief an adaptively adjusting detector that iteratively detects until the desired number /** \brief an adaptively adjusting detector that iteratively detects until the desired number
* of features are detected. * of features are detected.
...@@ -1485,24 +1486,24 @@ public: ...@@ -1485,24 +1486,24 @@ public:
* sample usage: * sample usage:
//will create a detector that attempts to find 100 - 110 FAST Keypoints, and will at most run //will create a detector that attempts to find 100 - 110 FAST Keypoints, and will at most run
//FAST feature detection 10 times until that number of keypoints are found //FAST feature detection 10 times until that number of keypoints are found
Ptr<FeatureDetector> detector(new DynamicDetector (100, 110, 10,new FastAdjuster(20,true))); Ptr<FeatureDetector> detector(new DynamicAdaptedFeatureDetector(new FastAdjuster(20,true),100, 110, 10));
*/ */
class CV_EXPORTS DynamicDetector: public FeatureDetector { class CV_EXPORTS DynamicAdaptedFeatureDetector: public FeatureDetector
{
public: public:
/** \param min_features the minimum desired features /** \param adjaster an AdjusterAdapter that will do the detection and parameter adjustment
* \param max_features the maximum desired number of features * \param max_features the maximum desired number of features
* \param max_iters the maximum number of times to try to adjust the feature detector params * \param max_iters the maximum number of times to try to adjust the feature detector params
* for the FastAdjuster this can be high, but with Star or Surf this can get time consuming * for the FastAdjuster this can be high, but with Star or Surf this can get time consuming
* \param a an AdjusterAdapter that will do the detection and parameter adjustment * \param min_features the minimum desired features
*/ */
DynamicDetector(int min_features, int max_features, int max_iters, DynamicAdaptedFeatureDetector( const Ptr<AdjusterAdapter>& adjaster, int min_features=400, int max_features=500, int max_iters=5 );
const Ptr<AdjusterAdapter>& a);
protected: protected:
virtual void detectImpl(const cv::Mat& image, virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask =
cv::Mat()) const;
private: private:
int escape_iters_; int escape_iters_;
int min_features_, max_features_; int min_features_, max_features_;
...@@ -1512,7 +1513,8 @@ private: ...@@ -1512,7 +1513,8 @@ private:
/**\brief an adjust for the FAST detector. This will basically decrement or increment the /**\brief an adjust for the FAST detector. This will basically decrement or increment the
* threshhold by 1 * threshhold by 1
*/ */
class CV_EXPORTS FastAdjuster: public AdjusterAdapter { class CV_EXPORTS FastAdjuster: public AdjusterAdapter
{
public: public:
/**\param init_thresh the initial threshhold to start with, default = 20 /**\param init_thresh the initial threshhold to start with, default = 20
* \param nonmax whether to use non max or not for fast feature detection * \param nonmax whether to use non max or not for fast feature detection
...@@ -1521,50 +1523,50 @@ public: ...@@ -1521,50 +1523,50 @@ public:
virtual void tooFew(int min, int n_detected); virtual void tooFew(int min, int n_detected);
virtual void tooMany(int max, int n_detected); virtual void tooMany(int max, int n_detected);
virtual bool good() const; virtual bool good() const;
protected: protected:
virtual void detectImpl(const cv::Mat& image, virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask =
cv::Mat()) const;
int thresh_; int thresh_;
bool nonmax_; bool nonmax_;
}; };
/** An adjuster for StarFeatureDetector, this one adjusts the responseThreshold for now /** An adjuster for StarFeatureDetector, this one adjusts the responseThreshold for now
* TODO find a faster way to converge the parameters for Star - use CvStarDetectorParams * TODO find a faster way to converge the parameters for Star - use CvStarDetectorParams
*/ */
struct CV_EXPORTS StarAdjuster: public AdjusterAdapter { class CV_EXPORTS StarAdjuster: public AdjusterAdapter
{
public:
StarAdjuster(double initial_thresh = 30.0); StarAdjuster(double initial_thresh = 30.0);
virtual void tooFew(int min, int n_detected); virtual void tooFew(int min, int n_detected);
virtual void tooMany(int max, int n_detected); virtual void tooMany(int max, int n_detected);
virtual bool good() const; virtual bool good() const;
protected: protected:
virtual void detectImpl(const cv::Mat& image, virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask =
cv::Mat()) const;
double thresh_; double thresh_;
CvStarDetectorParams params_; //todo use these instead of thresh_ CvStarDetectorParams params_; //todo use these instead of thresh_
}; };
struct CV_EXPORTS SurfAdjuster: public AdjusterAdapter { class CV_EXPORTS SurfAdjuster: public AdjusterAdapter
SurfAdjuster(); {
public:
SurfAdjuster();
virtual void tooFew(int min, int n_detected); virtual void tooFew(int min, int n_detected);
virtual void tooMany(int max, int n_detected); virtual void tooMany(int max, int n_detected);
virtual bool good() const; virtual bool good() const;
protected: protected:
virtual void detectImpl(const cv::Mat& image, virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask =
cv::Mat()) const;
double thresh_; double thresh_;
}; };
CV_EXPORTS Mat windowedMatchingMask( const vector<KeyPoint>& keypoints1, const vector<KeyPoint>& keypoints2, CV_EXPORTS Mat windowedMatchingMask( const vector<KeyPoint>& keypoints1, const vector<KeyPoint>& keypoints2,
float maxDeltaX, float maxDeltaY ); float maxDeltaX, float maxDeltaY );
CV_EXPORTS Ptr<FeatureDetector> createFeatureDetector( const string& detectorType );
/****************************************************************************************\ /****************************************************************************************\
* DescriptorExtractor * * DescriptorExtractor *
\****************************************************************************************/ \****************************************************************************************/
...@@ -1606,6 +1608,8 @@ public: ...@@ -1606,6 +1608,8 @@ public:
virtual int descriptorSize() const = 0; virtual int descriptorSize() const = 0;
virtual int descriptorType() const = 0; virtual int descriptorType() const = 0;
static Ptr<DescriptorExtractor> create( const string& descriptorExtractorType );
protected: protected:
virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const = 0; virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const = 0;
...@@ -1771,8 +1775,6 @@ protected: ...@@ -1771,8 +1775,6 @@ protected:
PixelTestFn test_fn_; PixelTestFn test_fn_;
}; };
CV_EXPORTS Ptr<DescriptorExtractor> createDescriptorExtractor( const string& descriptorExtractorType );
/****************************************************************************************\ /****************************************************************************************\
* Distance * * Distance *
\****************************************************************************************/ \****************************************************************************************/
...@@ -1981,6 +1983,7 @@ public: ...@@ -1981,6 +1983,7 @@ public:
// but with empty train data. // but with empty train data.
virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const = 0; virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const = 0;
static Ptr<DescriptorMatcher> create( const string& descriptorMatcherType );
protected: protected:
/* /*
* Class to work with descriptors from several images as with one merged matrix. * Class to work with descriptors from several images as with one merged matrix.
...@@ -2265,9 +2268,6 @@ protected: ...@@ -2265,9 +2268,6 @@ protected:
int addedDescCount; int addedDescCount;
}; };
CV_EXPORTS Ptr<DescriptorMatcher> createDescriptorMatcher( const string& descriptorMatcherType );
/****************************************************************************************\ /****************************************************************************************\
* GenericDescriptorMatcher * * GenericDescriptorMatcher *
\****************************************************************************************/ \****************************************************************************************/
...@@ -2372,6 +2372,9 @@ public: ...@@ -2372,6 +2372,9 @@ public:
// but with empty train data. // but with empty train data.
virtual Ptr<GenericDescriptorMatcher> clone( bool emptyTrainData=false ) const = 0; virtual Ptr<GenericDescriptorMatcher> clone( bool emptyTrainData=false ) const = 0;
static Ptr<GenericDescriptorMatcher> create( const string& genericDescritptorMatcherType,
const string &paramsFilename=string() );
protected: protected:
// In fact the matching is implemented only by the following two methods. These methods suppose // In fact the matching is implemented only by the following two methods. These methods suppose
// that the class object has been trained already. Public match methods call these methods // that the class object has been trained already. Public match methods call these methods
...@@ -2557,9 +2560,6 @@ protected: ...@@ -2557,9 +2560,6 @@ protected:
int prevTrainCount; int prevTrainCount;
}; };
CV_EXPORTS Ptr<GenericDescriptorMatcher> createGenericDescriptorMatcher( const string& genericDescritptorMatcherType,
const string &paramsFilename = string () );
/****************************************************************************************\ /****************************************************************************************\
* VectorDescriptorMatcher * * VectorDescriptorMatcher *
\****************************************************************************************/ \****************************************************************************************/
......
...@@ -92,15 +92,17 @@ void pixelTests64(const Mat& sum, const std::vector<KeyPoint>& keypoints, Mat& d ...@@ -92,15 +92,17 @@ void pixelTests64(const Mat& sum, const std::vector<KeyPoint>& keypoints, Mat& d
namespace cv namespace cv
{ {
HammingLUT::ResultType HammingLUT::operator()( const unsigned char* a, const unsigned char* b, int size ) const HammingLUT::ResultType HammingLUT::operator()( const unsigned char* a, const unsigned char* b, int size ) const
{ {
ResultType result = 0; ResultType result = 0;
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
{ {
result += byteBitsLookUp(a[i] ^ b[i]); result += byteBitsLookUp(a[i] ^ b[i]);
} }
return result; return result;
} }
Hamming::ResultType Hamming::operator()(const unsigned char* a, const unsigned char* b, int size) const Hamming::ResultType Hamming::operator()(const unsigned char* a, const unsigned char* b, int size) const
{ {
#if __GNUC__ #if __GNUC__
...@@ -116,6 +118,7 @@ Hamming::ResultType Hamming::operator()(const unsigned char* a, const unsigned c ...@@ -116,6 +118,7 @@ Hamming::ResultType Hamming::operator()(const unsigned char* a, const unsigned c
return HammingLUT()(a,b,size); return HammingLUT()(a,b,size);
#endif #endif
} }
BriefDescriptorExtractor::BriefDescriptorExtractor(int bytes) : BriefDescriptorExtractor::BriefDescriptorExtractor(int bytes) :
bytes_(bytes), test_fn_(NULL) bytes_(bytes), test_fn_(NULL)
{ {
...@@ -150,12 +153,15 @@ void BriefDescriptorExtractor::computeImpl(const Mat& image, std::vector<KeyPoin ...@@ -150,12 +153,15 @@ void BriefDescriptorExtractor::computeImpl(const Mat& image, std::vector<KeyPoin
// Construct integral image for fast smoothing (box filter) // Construct integral image for fast smoothing (box filter)
Mat sum; Mat sum;
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
///TODO allow the user to pass in a precomputed integral image ///TODO allow the user to pass in a precomputed integral image
//if(image.type() == CV_32S) //if(image.type() == CV_32S)
// sum = image; // sum = image;
//else //else
integral(image, sum, CV_32S); integral( grayImage, sum, CV_32S);
//Remove keypoints very close to the border //Remove keypoints very close to the border
removeBorderKeypoints(keypoints, image.size(), PATCH_SIZE/2 + KERNEL_SIZE/2); removeBorderKeypoints(keypoints, image.size(), PATCH_SIZE/2 + KERNEL_SIZE/2);
......
...@@ -109,6 +109,31 @@ void DescriptorExtractor::removeBorderKeypoints( vector<KeyPoint>& keypoints, ...@@ -109,6 +109,31 @@ void DescriptorExtractor::removeBorderKeypoints( vector<KeyPoint>& keypoints,
} }
} }
Ptr<DescriptorExtractor> DescriptorExtractor::create(const string& descriptorExtractorType)
{
DescriptorExtractor* de = 0;
int pos = 0;
if (!descriptorExtractorType.compare("SIFT"))
{
de = new SiftDescriptorExtractor();
}
else if (!descriptorExtractorType.compare("SURF"))
{
de = new SurfDescriptorExtractor();
}
else if (!descriptorExtractorType.compare("BRIEF"))
{
de = new BriefDescriptorExtractor();
}
else if ( (pos=descriptorExtractorType.find("Opponent")) == 0)
{
pos += string("Opponent").size();
de = new OpponentColorDescriptorExtractor( DescriptorExtractor::create(descriptorExtractorType.substr(pos)) );
}
return de;
}
/****************************************************************************************\ /****************************************************************************************\
* SiftDescriptorExtractor * * SiftDescriptorExtractor *
\****************************************************************************************/ \****************************************************************************************/
...@@ -231,7 +256,9 @@ int SurfDescriptorExtractor::descriptorType() const ...@@ -231,7 +256,9 @@ int SurfDescriptorExtractor::descriptorType() const
\****************************************************************************************/ \****************************************************************************************/
OpponentColorDescriptorExtractor::OpponentColorDescriptorExtractor( const Ptr<DescriptorExtractor>& _descriptorExtractor ) : OpponentColorDescriptorExtractor::OpponentColorDescriptorExtractor( const Ptr<DescriptorExtractor>& _descriptorExtractor ) :
descriptorExtractor(_descriptorExtractor) descriptorExtractor(_descriptorExtractor)
{} {
CV_Assert( !descriptorExtractor.empty() );
}
void convertBGRImageToOpponentColorSpace( const Mat& bgrImage, vector<Mat>& opponentChannels ) void convertBGRImageToOpponentColorSpace( const Mat& bgrImage, vector<Mat>& opponentChannels )
{ {
...@@ -305,7 +332,7 @@ void OpponentColorDescriptorExtractor::computeImpl( const Mat& bgrImage, vector< ...@@ -305,7 +332,7 @@ void OpponentColorDescriptorExtractor::computeImpl( const Mat& bgrImage, vector<
// Compute descriptors three times, once for each Opponent channel // Compute descriptors three times, once for each Opponent channel
// and concatenate into a single color surf descriptor // and concatenate into a single color surf descriptor
int descriptorSize = descriptorExtractor->descriptorSize(); int descriptorSize = descriptorExtractor->descriptorSize();
descriptors.create( static_cast<int>(keypoints.size()), 3*descriptorSize, CV_32FC1 ); descriptors.create( static_cast<int>(keypoints.size()), 3*descriptorSize, descriptorExtractor->descriptorType() );
for( int i = 0; i < 3/*channel count*/; i++ ) for( int i = 0; i < 3/*channel count*/; i++ )
{ {
CV_Assert( opponentChannels[i].type() == CV_8UC1 ); CV_Assert( opponentChannels[i].type() == CV_8UC1 );
...@@ -333,34 +360,5 @@ int OpponentColorDescriptorExtractor::descriptorType() const ...@@ -333,34 +360,5 @@ int OpponentColorDescriptorExtractor::descriptorType() const
{ {
return descriptorExtractor->descriptorType(); return descriptorExtractor->descriptorType();
} }
/****************************************************************************************\
* Factory function for descriptor extractor creating *
\****************************************************************************************/
Ptr<DescriptorExtractor> createDescriptorExtractor(const string& descriptorExtractorType)
{
DescriptorExtractor* de = 0;
if (!descriptorExtractorType.compare("SIFT"))
{
de = new SiftDescriptorExtractor();
}
else if (!descriptorExtractorType.compare("SURF"))
{
de = new SurfDescriptorExtractor();
}
else if (!descriptorExtractorType.compare("OpponentSIFT"))
{
de = new OpponentColorDescriptorExtractor(new SiftDescriptorExtractor);
}
else if (!descriptorExtractorType.compare("OpponentSURF"))
{
de = new OpponentColorDescriptorExtractor(new SurfDescriptorExtractor);
}
else if (!descriptorExtractorType.compare("BRIEF"))
{
de = new BriefDescriptorExtractor();
}
return de;
}
} }
...@@ -97,6 +97,60 @@ void FeatureDetector::read( const FileNode& ) ...@@ -97,6 +97,60 @@ void FeatureDetector::read( const FileNode& )
void FeatureDetector::write( FileStorage& ) const void FeatureDetector::write( FileStorage& ) const
{} {}
Ptr<FeatureDetector> FeatureDetector::create( const string& detectorType )
{
FeatureDetector* fd = 0;
int pos = 0;
if( !detectorType.compare( "FAST" ) )
{
fd = new FastFeatureDetector();
}
else if( !detectorType.compare( "STAR" ) )
{
fd = new StarFeatureDetector();
}
else if( !detectorType.compare( "SIFT" ) )
{
fd = new SiftFeatureDetector();
}
else if( !detectorType.compare( "SURF" ) )
{
fd = new SurfFeatureDetector();
}
else if( !detectorType.compare( "MSER" ) )
{
fd = new MserFeatureDetector();
}
else if( !detectorType.compare( "GFTT" ) )
{
fd = new GoodFeaturesToTrackDetector();
}
else if( !detectorType.compare( "HARRIS" ) )
{
GoodFeaturesToTrackDetector::Params params;
params.useHarrisDetector = true;
fd = new GoodFeaturesToTrackDetector(params);
}
else if( (pos=detectorType.find("Grid")) == 0 )
{
pos += string("Grid").size();
fd = new GridAdaptedFeatureDetector( FeatureDetector::create(detectorType.substr(pos)) );
}
else if( (pos=detectorType.find("Pyramid")) == 0 )
{
pos += string("Pyramid").size();
fd = new PyramidAdaptedFeatureDetector( FeatureDetector::create(detectorType.substr(pos)) );
}
else if( (pos=detectorType.find("Dynamic")) == 0 )
{
pos += string("Dynamic").size();
fd = new DynamicAdaptedFeatureDetector( AdjusterAdapter::create(detectorType.substr(pos)) );
}
return fd;
}
/* /*
* FastFeatureDetector * FastFeatureDetector
*/ */
...@@ -519,53 +573,4 @@ void PyramidAdaptedFeatureDetector::detectImpl( const Mat& image, vector<KeyPoin ...@@ -519,53 +573,4 @@ void PyramidAdaptedFeatureDetector::detectImpl( const Mat& image, vector<KeyPoin
} }
} }
Ptr<FeatureDetector> createFeatureDetector( const string& detectorType )
{
FeatureDetector* fd = 0;
if( !detectorType.compare( "FAST" ) )
{
fd = new FastFeatureDetector();
}
else if( !detectorType.compare( "DynamicFAST" ) )
{
fd = new DynamicDetector(400,500,5,new FastAdjuster());
}
else if( !detectorType.compare( "STAR" ) )
{
fd = new StarFeatureDetector();
}
else if( !detectorType.compare( "DynamicSTAR" ) )
{
fd = new DynamicDetector(400,500,5,new StarAdjuster());
}
else if( !detectorType.compare( "SIFT" ) )
{
fd = new SiftFeatureDetector(SIFT::DetectorParams::GET_DEFAULT_THRESHOLD(),
SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD());
}
else if( !detectorType.compare( "SURF" ) )
{
fd = new SurfFeatureDetector();
}
else if( !detectorType.compare( "DynamicSURF" ) )
{
fd =new DynamicDetector(400,500,5,new SurfAdjuster());
}
else if( !detectorType.compare( "MSER" ) )
{
fd = new MserFeatureDetector();
}
else if( !detectorType.compare( "GFTT" ) )
{
fd = new GoodFeaturesToTrackDetector();
}
else if( !detectorType.compare( "HARRIS" ) )
{
GoodFeaturesToTrackDetector::Params params;
params.useHarrisDetector = true;
fd = new GoodFeaturesToTrackDetector(params);
}
return fd;
}
} }
...@@ -41,14 +41,16 @@ ...@@ -41,14 +41,16 @@
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
namespace cv { namespace cv
DynamicDetector::DynamicDetector(int min_features, {
int max_features, int max_iters, const Ptr<AdjusterAdapter>& a) :
escape_iters_(max_iters), min_features_(min_features), max_features_( DynamicAdaptedFeatureDetector::DynamicAdaptedFeatureDetector(const Ptr<AdjusterAdapter>& a,
max_features), adjuster_(a) { int min_features, int max_features, int max_iters ) :
} escape_iters_(max_iters), min_features_(min_features), max_features_(max_features), adjuster_(a)
void DynamicDetector::detectImpl(const cv::Mat& image, std::vector< {}
cv::KeyPoint>& keypoints, const cv::Mat& mask) const {
void DynamicAdaptedFeatureDetector::detectImpl(const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask) const
{
//for oscillation testing //for oscillation testing
bool down = false; bool down = false;
bool up = false; bool up = false;
...@@ -62,88 +64,131 @@ void DynamicDetector::detectImpl(const cv::Mat& image, std::vector< ...@@ -62,88 +64,131 @@ void DynamicDetector::detectImpl(const cv::Mat& image, std::vector<
//break if the desired number hasn't been reached. //break if the desired number hasn't been reached.
int iter_count = escape_iters_; int iter_count = escape_iters_;
do { do
{
keypoints.clear(); keypoints.clear();
//the adjuster takes care of calling the detector with updated parameters //the adjuster takes care of calling the detector with updated parameters
adjuster.detect(image, keypoints,mask); adjuster.detect(image, keypoints,mask);
if (int(keypoints.size()) < min_features_) { if (int(keypoints.size()) < min_features_)
{
down = true; down = true;
adjuster.tooFew(min_features_, keypoints.size()); adjuster.tooFew(min_features_, keypoints.size());
} else if (int(keypoints.size()) > max_features_) { }
else if (int(keypoints.size()) > max_features_)
{
up = true; up = true;
adjuster.tooMany(max_features_, keypoints.size()); adjuster.tooMany(max_features_, keypoints.size());
} else }
else
thresh_good = true; thresh_good = true;
} while (--iter_count >= 0 && !(down && up) && !thresh_good }
&& adjuster.good()); while (--iter_count >= 0 && !(down && up) && !thresh_good && adjuster.good());
} }
FastAdjuster::FastAdjuster(int init_thresh, bool nonmax) : FastAdjuster::FastAdjuster(int init_thresh, bool nonmax) :
thresh_(init_thresh), nonmax_(nonmax) { thresh_(init_thresh), nonmax_(nonmax)
} {}
void FastAdjuster::detectImpl(const cv::Mat& image,
std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask) const { void FastAdjuster::detectImpl(const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask) const
{
FastFeatureDetector(thresh_, nonmax_).detect(image, keypoints, mask); FastFeatureDetector(thresh_, nonmax_).detect(image, keypoints, mask);
} }
void FastAdjuster::tooFew(int min, int n_detected) {
void FastAdjuster::tooFew(int min, int n_detected)
{
//fast is easy to adjust //fast is easy to adjust
thresh_--; thresh_--;
} }
void FastAdjuster::tooMany(int max, int n_detected) {
void FastAdjuster::tooMany(int max, int n_detected)
{
//fast is easy to adjust //fast is easy to adjust
thresh_++; thresh_++;
} }
//return whether or not the threshhold is beyond //return whether or not the threshhold is beyond
//a useful point //a useful point
bool FastAdjuster::good() const { bool FastAdjuster::good() const
{
return (thresh_ > 1) && (thresh_ < 200); return (thresh_ > 1) && (thresh_ < 200);
} }
StarAdjuster::StarAdjuster(double initial_thresh) : StarAdjuster::StarAdjuster(double initial_thresh) :
thresh_(initial_thresh) { thresh_(initial_thresh)
} {}
void StarAdjuster::detectImpl(const cv::Mat& image,
std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask) const { void StarAdjuster::detectImpl(const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask) const
{
StarFeatureDetector detector_tmp(16, thresh_, 10, 8, 3); StarFeatureDetector detector_tmp(16, thresh_, 10, 8, 3);
detector_tmp.detect(image, keypoints, mask); detector_tmp.detect(image, keypoints, mask);
} }
void StarAdjuster::tooFew(int min, int n_detected) {
void StarAdjuster::tooFew(int min, int n_detected)
{
thresh_ *= 0.9; thresh_ *= 0.9;
if (thresh_ < 1.1) if (thresh_ < 1.1)
thresh_ = 1.1; thresh_ = 1.1;
} }
void StarAdjuster::tooMany(int max, int n_detected) {
void StarAdjuster::tooMany(int max, int n_detected)
{
thresh_ *= 1.1; thresh_ *= 1.1;
} }
bool StarAdjuster::good() const { bool StarAdjuster::good() const
{
return (thresh_ > 2) && (thresh_ < 200); return (thresh_ > 2) && (thresh_ < 200);
} }
SurfAdjuster::SurfAdjuster() : SurfAdjuster::SurfAdjuster() :
thresh_(400.0) { thresh_(400.0)
} {}
void SurfAdjuster::detectImpl(const cv::Mat& image,
std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask) const { void SurfAdjuster::detectImpl(const Mat& image, vector<KeyPoint>& keypoints, const cv::Mat& mask) const
{
SurfFeatureDetector detector_tmp(thresh_); SurfFeatureDetector detector_tmp(thresh_);
detector_tmp.detect(image, keypoints, mask); detector_tmp.detect(image, keypoints, mask);
} }
void SurfAdjuster::tooFew(int min, int n_detected) {
void SurfAdjuster::tooFew(int min, int n_detected)
{
thresh_ *= 0.9; thresh_ *= 0.9;
if (thresh_ < 1.1) if (thresh_ < 1.1)
thresh_ = 1.1; thresh_ = 1.1;
} }
void SurfAdjuster::tooMany(int max, int n_detected) {
void SurfAdjuster::tooMany(int max, int n_detected)
{
thresh_ *= 1.1; thresh_ *= 1.1;
} }
//return whether or not the threshhold is beyond //return whether or not the threshhold is beyond
//a useful point //a useful point
bool SurfAdjuster::good() const { bool SurfAdjuster::good() const
{
return (thresh_ > 2) && (thresh_ < 1000); return (thresh_ > 2) && (thresh_ < 1000);
} }
Ptr<AdjusterAdapter> AdjusterAdapter::create( const string& detectorType )
{
Ptr<AdjusterAdapter> adapter;
if( !detectorType.compare( "FAST" ) )
{
adapter = new FastAdjuster();
}
else if( !detectorType.compare( "STAR" ) )
{
adapter = new StarAdjuster();
}
else if( !detectorType.compare( "SURF" ) )
{
adapter = new SurfAdjuster();
}
return adapter;
}
} }
...@@ -322,7 +322,39 @@ bool DescriptorMatcher::isMaskedOut( const vector<Mat>& masks, int queryIdx ) ...@@ -322,7 +322,39 @@ bool DescriptorMatcher::isMaskedOut( const vector<Mat>& masks, int queryIdx )
return !masks.empty() && outCount == masks.size() ; return !masks.empty() && outCount == masks.size() ;
} }
/*
* Factory function for DescriptorMatcher creating
*/
Ptr<DescriptorMatcher> DescriptorMatcher::create( const string& descriptorMatcherType )
{
DescriptorMatcher* dm = 0;
if( !descriptorMatcherType.compare( "FlannBased" ) )
{
dm = new FlannBasedMatcher();
}
else if( !descriptorMatcherType.compare( "BruteForce" ) ) // L2
{
dm = new BruteForceMatcher<L2<float> >();
}
else if( !descriptorMatcherType.compare( "BruteForce-L1" ) )
{
dm = new BruteForceMatcher<L1<float> >();
}
else if( !descriptorMatcherType.compare("BruteForce-Hamming") )
{
dm = new BruteForceMatcher<Hamming>();
}
else if( !descriptorMatcherType.compare( "BruteForce-HammingLUT") )
{
dm = new BruteForceMatcher<HammingLUT>();
}
return dm;
}
/*
* BruteForce L2 specialization
*/
template<> template<>
void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int knn, void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int knn,
const vector<Mat>& masks, bool compactResult ) const vector<Mat>& masks, bool compactResult )
...@@ -585,36 +617,6 @@ void FlannBasedMatcher::radiusMatchImpl( const Mat& queryDescriptors, vector<vec ...@@ -585,36 +617,6 @@ void FlannBasedMatcher::radiusMatchImpl( const Mat& queryDescriptors, vector<vec
convertToDMatches( mergedDescriptors, indices, dists, matches ); convertToDMatches( mergedDescriptors, indices, dists, matches );
} }
/*
* Factory function for DescriptorMatcher creating
*/
Ptr<DescriptorMatcher> createDescriptorMatcher( const string& descriptorMatcherType )
{
DescriptorMatcher* dm = 0;
if( !descriptorMatcherType.compare( "FlannBased" ) )
{
dm = new FlannBasedMatcher();
}
else if( !descriptorMatcherType.compare( "BruteForce" ) ) // L2
{
dm = new BruteForceMatcher<L2<float> >();
}
else if( !descriptorMatcherType.compare( "BruteForce-L1" ) )
{
dm = new BruteForceMatcher<L1<float> >();
}
else if( !descriptorMatcherType.compare("BruteForce-Hamming") )
{
dm = new BruteForceMatcher<Hamming>();
}
else if( !descriptorMatcherType.compare( "BruteForce-HammingLUT") )
{
dm = new BruteForceMatcher<HammingLUT>();
}
return dm;
}
/****************************************************************************************\ /****************************************************************************************\
* GenericDescriptorMatcher * * GenericDescriptorMatcher *
\****************************************************************************************/ \****************************************************************************************/
...@@ -847,6 +849,34 @@ void GenericDescriptorMatcher::read( const FileNode& ) ...@@ -847,6 +849,34 @@ void GenericDescriptorMatcher::read( const FileNode& )
void GenericDescriptorMatcher::write( FileStorage& ) const void GenericDescriptorMatcher::write( FileStorage& ) const
{} {}
/*
* Factory function for GenericDescriptorMatch creating
*/
Ptr<GenericDescriptorMatcher> GenericDescriptorMatcher::create( const string& genericDescritptorMatcherType,
const string &paramsFilename )
{
Ptr<GenericDescriptorMatcher> descriptorMatcher;
if( ! genericDescritptorMatcherType.compare("ONEWAY") )
{
descriptorMatcher = new OneWayDescriptorMatcher();
}
else if( ! genericDescritptorMatcherType.compare("FERN") )
{
descriptorMatcher = new FernDescriptorMatcher();
}
if( !paramsFilename.empty() && !descriptorMatcher.empty() )
{
FileStorage fs = FileStorage( paramsFilename, FileStorage::READ );
if( fs.isOpened() )
{
descriptorMatcher->read( fs.root() );
fs.release();
}
}
return descriptorMatcher;
}
/****************************************************************************************\ /****************************************************************************************\
* OneWayDescriptorMatcher * * OneWayDescriptorMatcher *
\****************************************************************************************/ \****************************************************************************************/
...@@ -1238,32 +1268,4 @@ Ptr<GenericDescriptorMatcher> VectorDescriptorMatcher::clone( bool emptyTrainDat ...@@ -1238,32 +1268,4 @@ Ptr<GenericDescriptorMatcher> VectorDescriptorMatcher::clone( bool emptyTrainDat
return new VectorDescriptorMatcher( extractor, matcher->clone(emptyTrainData) ); return new VectorDescriptorMatcher( extractor, matcher->clone(emptyTrainData) );
} }
/*
* Factory function for GenericDescriptorMatch creating
*/
Ptr<GenericDescriptorMatcher> createGenericDescriptorMatcher( const string& genericDescritptorMatcherType,
const string &paramsFilename )
{
Ptr<GenericDescriptorMatcher> descriptorMatcher;
if( ! genericDescritptorMatcherType.compare("ONEWAY") )
{
descriptorMatcher = new OneWayDescriptorMatcher();
}
else if( ! genericDescritptorMatcherType.compare("FERN") )
{
descriptorMatcher = new FernDescriptorMatcher();
}
if( !paramsFilename.empty() && !descriptorMatcher.empty() )
{
FileStorage fs = FileStorage( paramsFilename, FileStorage::READ );
if( fs.isOpened() )
{
descriptorMatcher->read( fs.root() );
fs.release();
}
}
return descriptorMatcher;
}
} }
...@@ -2552,8 +2552,8 @@ int main(int argc, char** argv) ...@@ -2552,8 +2552,8 @@ int main(int argc, char** argv)
} }
// Create detector, descriptor, matcher. // Create detector, descriptor, matcher.
Ptr<FeatureDetector> featureDetector = createFeatureDetector( ddmParams.detectorType ); Ptr<FeatureDetector> featureDetector = FeatureDetector::create( ddmParams.detectorType );
Ptr<DescriptorExtractor> descExtractor = createDescriptorExtractor( ddmParams.descriptorType ); Ptr<DescriptorExtractor> descExtractor = DescriptorExtractor::create( ddmParams.descriptorType );
Ptr<BOWImgDescriptorExtractor> bowExtractor; Ptr<BOWImgDescriptorExtractor> bowExtractor;
if( featureDetector.empty() || descExtractor.empty() ) if( featureDetector.empty() || descExtractor.empty() )
{ {
...@@ -2561,7 +2561,7 @@ int main(int argc, char** argv) ...@@ -2561,7 +2561,7 @@ int main(int argc, char** argv)
return -1; return -1;
} }
{ {
Ptr<DescriptorMatcher> descMatcher = createDescriptorMatcher( ddmParams.matcherType ); Ptr<DescriptorMatcher> descMatcher = DescriptorMatcher::create( ddmParams.matcherType );
if( featureDetector.empty() || descExtractor.empty() || descMatcher.empty() ) if( featureDetector.empty() || descExtractor.empty() || descMatcher.empty() )
{ {
cout << "descMatcher was not created" << endl; cout << "descMatcher was not created" << endl;
......
...@@ -651,8 +651,8 @@ int main(int argc, char** argv) ...@@ -651,8 +651,8 @@ int main(int argc, char** argv)
Size calibratedImageSize; Size calibratedImageSize;
readCameraMatrix(intrinsicsFilename, cameraMatrix, distCoeffs, calibratedImageSize); readCameraMatrix(intrinsicsFilename, cameraMatrix, distCoeffs, calibratedImageSize);
Ptr<FeatureDetector> detector = createFeatureDetector(detectorName); Ptr<FeatureDetector> detector = FeatureDetector::create(detectorName);
Ptr<DescriptorExtractor> descriptorExtractor = createDescriptorExtractor(descriptorExtractorName); Ptr<DescriptorExtractor> descriptorExtractor = DescriptorExtractor::create(descriptorExtractorName);
string modelIndexFilename = format("%s_segm/frame_index.yml", modelName); string modelIndexFilename = format("%s_segm/frame_index.yml", modelName);
if(!readModelViews( modelIndexFilename, modelBox, imageList, roiList, poseList)) if(!readModelViews( modelIndexFilename, modelBox, imageList, roiList, poseList))
......
...@@ -223,9 +223,9 @@ int main(int argc, char** argv) ...@@ -223,9 +223,9 @@ int main(int argc, char** argv)
ransacReprojThreshold = atof(argv[7]); ransacReprojThreshold = atof(argv[7]);
cout << "< Creating detector, descriptor extractor and descriptor matcher ..." << endl; cout << "< Creating detector, descriptor extractor and descriptor matcher ..." << endl;
Ptr<FeatureDetector> detector = createFeatureDetector( argv[1] ); Ptr<FeatureDetector> detector = FeatureDetector::create( argv[1] );
Ptr<DescriptorExtractor> descriptorExtractor = createDescriptorExtractor( argv[2] ); Ptr<DescriptorExtractor> descriptorExtractor = DescriptorExtractor::create( argv[2] );
Ptr<DescriptorMatcher> descriptorMatcher = createDescriptorMatcher( argv[3] ); Ptr<DescriptorMatcher> descriptorMatcher = DescriptorMatcher::create( argv[3] );
int mactherFilterType = getMatcherFilterType( argv[4] ); int mactherFilterType = getMatcherFilterType( argv[4] );
bool eval = !isWarpPerspective ? false : (atoi(argv[6]) == 0 ? false : true); bool eval = !isWarpPerspective ? false : (atoi(argv[6]) == 0 ? false : true);
cout << ">" << endl; cout << ">" << endl;
......
...@@ -29,7 +29,7 @@ int main(int argc, char** argv) ...@@ -29,7 +29,7 @@ int main(int argc, char** argv)
std::string alg_name = std::string(argv[3]); std::string alg_name = std::string(argv[3]);
std::string params_filename = std::string(argv[4]); std::string params_filename = std::string(argv[4]);
Ptr<GenericDescriptorMatcher> descriptorMatcher = createGenericDescriptorMatcher(alg_name, params_filename); Ptr<GenericDescriptorMatcher> descriptorMatcher = GenericDescriptorMatcher::create(alg_name, params_filename);
if( descriptorMatcher == 0 ) if( descriptorMatcher == 0 )
{ {
printf ("Cannot create descriptor\n"); printf ("Cannot create descriptor\n");
......
...@@ -62,9 +62,9 @@ bool createDetectorDescriptorMatcher( const string& detectorType, const string& ...@@ -62,9 +62,9 @@ bool createDetectorDescriptorMatcher( const string& detectorType, const string&
Ptr<DescriptorMatcher>& descriptorMatcher ) Ptr<DescriptorMatcher>& descriptorMatcher )
{ {
cout << "< Creating feature detector, descriptor extractor and descriptor matcher ..." << endl; cout << "< Creating feature detector, descriptor extractor and descriptor matcher ..." << endl;
featureDetector = createFeatureDetector( detectorType ); featureDetector = FeatureDetector::create( detectorType );
descriptorExtractor = createDescriptorExtractor( descriptorType ); descriptorExtractor = DescriptorExtractor::create( descriptorType );
descriptorMatcher = createDescriptorMatcher( matcherType ); descriptorMatcher = DescriptorMatcher::create( matcherType );
cout << ">" << endl; cout << ">" << endl;
bool isCreated = !( featureDetector.empty() || descriptorExtractor.empty() || descriptorMatcher.empty() ); bool isCreated = !( featureDetector.empty() || descriptorExtractor.empty() || descriptorMatcher.empty() );
......
...@@ -686,8 +686,8 @@ inline void readKeypoints( FileStorage& fs, vector<KeyPoint>& keypoints, int img ...@@ -686,8 +686,8 @@ inline void readKeypoints( FileStorage& fs, vector<KeyPoint>& keypoints, int img
void DetectorQualityTest::readAlgorithm () void DetectorQualityTest::readAlgorithm ()
{ {
defaultDetector = createFeatureDetector( algName ); defaultDetector = FeatureDetector::create( algName );
specificDetector = createFeatureDetector( algName ); specificDetector = FeatureDetector::create( algName );
if( defaultDetector == 0 ) if( defaultDetector == 0 )
{ {
ts->printf(CvTS::LOG, "Algorithm can not be read\n"); ts->printf(CvTS::LOG, "Algorithm can not be read\n");
...@@ -960,13 +960,13 @@ void DescriptorQualityTest::writePlotData( int di ) const ...@@ -960,13 +960,13 @@ void DescriptorQualityTest::writePlotData( int di ) const
void DescriptorQualityTest::readAlgorithm( ) void DescriptorQualityTest::readAlgorithm( )
{ {
defaultDescMatcher = createGenericDescriptorMatcher( algName ); defaultDescMatcher = GenericDescriptorMatcher::create( algName );
specificDescMatcher = createGenericDescriptorMatcher( algName ); specificDescMatcher = GenericDescriptorMatcher::create( algName );
if( defaultDescMatcher == 0 ) if( defaultDescMatcher == 0 )
{ {
Ptr<DescriptorExtractor> extractor = createDescriptorExtractor( algName ); Ptr<DescriptorExtractor> extractor = DescriptorExtractor::create( algName );
Ptr<DescriptorMatcher> matcher = createDescriptorMatcher( matcherName ); Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create( matcherName );
defaultDescMatcher = new VectorDescriptorMatch( extractor, matcher ); defaultDescMatcher = new VectorDescriptorMatch( extractor, matcher );
specificDescMatcher = new VectorDescriptorMatch( extractor, matcher ); specificDescMatcher = new VectorDescriptorMatch( extractor, matcher );
......
This diff is collapsed.
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