Both detectors and descriptors in OpenCV have wrappers with common interface that enables to switch easily between different algorithms solving the same problem. All objects that implement keypoint detectors inherit FeatureDetector interface. Descriptors that are represented as vectors in a multidimensional space can be computed with DescriptorExtractor interface. DescriptorMatcher interface can be used to find matches between two sets of descriptors. GenericDescriptorMatch is a more generic interface for descriptors. It does not make any assumptions about descriptor representation. Every descriptor with DescriptorExtractor interface has a wrapper with GenericDescriptorMatch interface (see VectorDescriptorMatch). There are descriptors such as one way descriptor and ferns that have GenericDescriptorMatch interface implemented, but do not support DescriptorExtractor.
Abstract base class for 2D image feature detectors.
class FeatureDetector
{
public:
void detect( const Mat& image, vector<KeyPoint>& keypoints,
const Mat& mask=Mat() ) const;
virtual void read( const FileNode& fn ) {};
virtual void write( FileStorage& fs ) const {};
protected:
...
};
Detect keypoints in an image.
Parameters: |
|
---|
Write feature detector to file storage.
Parameter: | fs – File storage in which detector will be written. |
---|
Wrapping class for feature detection using FAST() method.
class FastFeatureDetector : public FeatureDetector
{
public:
FastFeatureDetector( int _threshold = 1, bool _nonmaxSuppression = true );
virtual void read (const FileNode& fn);
virtual void write (FileStorage& fs) const;
protected:
...
};
Wrapping class for feature detection using goodFeaturesToTrack() method.
class GoodFeaturesToTrackDetector : public FeatureDetector
{
public:
GoodFeaturesToTrackDetector( int _maxCorners, double _qualityLevel,
double _minDistance, int _blockSize=3,
bool _useHarrisDetector=false, double _k=0.04 );
virtual void read (const FileNode& fn);
virtual void write (FileStorage& fs) const;
protected:
...
}
Wrapping class for feature detection using MSER() class.
class MserFeatureDetector : public FeatureDetector
{
public:
MserFeatureDetector( CvMSERParams params = cvMSERParams () );
MserFeatureDetector( int delta, int minArea, int maxArea, float maxVariation,
float minDiversity, int maxEvolution, double areaThreshold,
double minMargin, int edgeBlurSize );
virtual void read (const FileNode& fn);
virtual void write (FileStorage& fs) const;
protected:
...
}
Wrapping class for feature detection using StarDetector() class.
class StarFeatureDetector : public FeatureDetector
{
public:
StarFeatureDetector( int maxSize=16, int responseThreshold=30,
int lineThresholdProjected = 10,
int lineThresholdBinarized=8, int suppressNonmaxSize=5 );
virtual void read (const FileNode& fn);
virtual void write (FileStorage& fs) const;
protected:
...
}
Wrapping class for feature detection using SIFT() class.
class SiftFeatureDetector : public FeatureDetector
{
public:
SiftFeatureDetector( double threshold=SIFT::DetectorParams::GET_DEFAULT_THRESHOLD(),
double edgeThreshold=SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD(),
int nOctaves=SIFT::CommonParams::DEFAULT_NOCTAVES,
int nOctaveLayers=SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS,
int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
int angleMode=SIFT::CommonParams::FIRST_ANGLE );
virtual void read (const FileNode& fn);
virtual void write (FileStorage& fs) const;
protected:
...
}
Wrapping class for feature detection using SURF() class.
class SurfFeatureDetector : public FeatureDetector
{
public:
SurfFeatureDetector( double hessianThreshold = 400., int octaves = 3,
int octaveLayers = 4 );
virtual void read (const FileNode& fn);
virtual void write (FileStorage& fs) const;
protected:
...
}
Abstract base class for computing descriptors for image keypoints.
class DescriptorExtractor
{
public:
virtual void compute( const Mat& image, vector<KeyPoint>& keypoints,
Mat& descriptors ) const = 0;
virtual void read (const FileNode &fn) {};
virtual void write (FileStorage &fs) const {};
protected:
...
};
In this interface we assume a keypoint descriptor can be represented as a dense, fixed-dimensional vector of some basic type. Most descriptors used in practice follow this pattern, as it makes it very easy to compute distances between descriptors. Therefore we represent a collection of descriptors as a Mat() , where each row is one keypoint descriptor.
Compute the descriptors for a set of keypoints in an image. Must be implemented by the subclass.
Parameters: |
|
---|
Write descriptor extractor to file storage.
Parameter: | fs – File storage in which detector will be written. |
---|
Wrapping class for descriptors computing using SIFT() class.
class SiftDescriptorExtractor : public DescriptorExtractor
{
public:
SiftDescriptorExtractor(
double magnification=SIFT::DescriptorParams::GET_DEFAULT_MAGNIFICATION(),
bool isNormalize=true, bool recalculateAngles=true,
int nOctaves=SIFT::CommonParams::DEFAULT_NOCTAVES,
int nOctaveLayers=SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS,
int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
int angleMode=SIFT::CommonParams::FIRST_ANGLE );
virtual void compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors) const;
virtual void read (const FileNode &fn);
virtual void write (FileStorage &fs) const;
protected:
...
}
Wrapping class for descriptors computing using SURF() class.
class SurfDescriptorExtractor : public DescriptorExtractor
{
public:
SurfDescriptorExtractor( int nOctaves=4,
int nOctaveLayers=2, bool extended=false );
virtual void compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors) const;
virtual void read (const FileNode &fn);
virtual void write (FileStorage &fs) const;
protected:
...
}
Abstract base class for matching two sets of descriptors.
class DescriptorMatcher
{
public:
void add( const Mat& descriptors );
// Index the descriptors training set.
void index();
void match( const Mat& query, vector<int>& matches ) const;
void match( const Mat& query, const Mat& mask,
vector<int>& matches ) const;
virtual void clear();
protected:
...
};
of this method the mask is used to describe which descriptors can be matched.descriptors1[i]can be matched with descriptors2[j]only if mask.at<char>(i,j)is non-zero.
Brute-force descriptor matcher. For each descriptor in the first set, this matcher finds the closest descriptor in the second set by trying each one.
template<class Distance>
class BruteForceMatcher : public DescriptorMatcher
{
public:
BruteForceMatcher( Distance d = Distance() ) : distance(d) {}
protected:
...
}
For efficiency, BruteForceMatcher is templated on the distance metric. For float descriptors, a common choice would be L2<float> . Class L2 is defined as:
template<typename T>
struct Accumulator
{
typedef T Type;
};
template<> struct Accumulator<unsigned char> { typedef unsigned int Type; };
template<> struct Accumulator<unsigned short> { typedef unsigned int Type; };
template<> struct Accumulator<char> { typedef int Type; };
template<> struct Accumulator<short> { typedef int Type; };
/*
* Squared Euclidean distance functor
*/
template<class T>
struct L2
{
typedef T ValueType;
typedef typename Accumulator<T>::Type ResultType;
ResultType operator()( const T* a, const T* b, int size ) const;
{
ResultType result = ResultType();
for( int i = 0; i < size; i++ )
{
ResultType diff = a[i] - b[i];
result += diff*diff;
}
return sqrt(result);
}
};
A storage for sets of keypoints together with corresponding images and class IDs
class KeyPointCollection
{
public:
// Adds keypoints from a single image to the storage.
// image Source image
// points A vector of keypoints
void add( const Mat& _image, const vector<KeyPoint>& _points );
// Returns the total number of keypoints in the collection
size_t calcKeypointCount() const;
// Returns the keypoint by its global index
KeyPoint getKeyPoint( int index ) const;
// Clears images, keypoints and startIndices
void clear();
vector<Mat> images;
vector<vector<KeyPoint> > points;
// global indices of the first points in each image,
// startIndices.size() = points.size()
vector<int> startIndices;
};
Abstract interface for a keypoint descriptor.
class GenericDescriptorMatch
{
public:
enum IndexType
{
NoIndex,
KDTreeIndex
};
GenericDescriptorMatch() {}
virtual ~GenericDescriptorMatch() {}
virtual void add( KeyPointCollection& keypoints );
virtual void add( const Mat& image, vector<KeyPoint>& points ) = 0;
virtual void classify( const Mat& image, vector<KeyPoint>& points );
virtual void match( const Mat& image, vector<KeyPoint>& points,
vector<int>& indices ) = 0;
virtual void clear();
virtual void read( const FileNode& fn );
virtual void write( FileStorage& fs ) const;
protected:
KeyPointCollection collection;
};
KeyPointCollection() KeyPoint()
Keypoints can be passed using (with with corresponding images) or as a vector of from a single image.
param keypoints: Keypoints collection with corresponding images.
Class used for matching descriptors that can be described as vectors in a finite-dimensional space.
template<class Extractor, class Matcher>
class VectorDescriptorMatch : public GenericDescriptorMatch
{
public:
VectorDescriptorMatch( const Extractor& _extractor = Extractor(),
const Matcher& _matcher = Matcher() );
~VectorDescriptorMatch();
// Builds flann index
void index();
// Calculates descriptors for a set of keypoints from a single image
virtual void add( const Mat& image, vector<KeyPoint>& keypoints );
// Matches a set of keypoints with the training set
virtual void match( const Mat& image, vector<KeyPoint>& points,
vector<int>& keypointIndices );
// Clears object (i.e. storing keypoints)
virtual void clear();
// Reads object from file node
virtual void read (const FileNode& fn);
// Writes object to file storage
virtual void write (FileStorage& fs) const;
protected:
Extractor extractor;
Matcher matcher;
};
Wrapping class for computing, matching and classification of descriptors using OneWayDescriptorBase() class.
class OneWayDescriptorMatch : public GenericDescriptorMatch
{
public:
class Params
{
public:
static const int POSE_COUNT = 500;
static const int PATCH_WIDTH = 24;
static const int PATCH_HEIGHT = 24;
static float GET_MIN_SCALE() { return 0.7f; }
static float GET_MAX_SCALE() { return 1.5f; }
static float GET_STEP_SCALE() { return 1.2f; }
Params( int _poseCount = POSE_COUNT,
Size _patchSize = Size(PATCH_WIDTH, PATCH_HEIGHT),
string _pcaFilename = string (),
string _trainPath = string(),
string _trainImagesList = string(),
float _minScale = GET_MIN_SCALE(), float _maxScale = GET_MAX_SCALE(),
float _stepScale = GET_STEP_SCALE() );
int poseCount;
Size patchSize;
string pcaFilename;
string trainPath;
string trainImagesList;
float minScale, maxScale, stepScale;
};
OneWayDescriptorMatch();
// Equivalent to calling PointMatchOneWay() followed by Initialize(_params)
OneWayDescriptorMatch( const Params& _params );
virtual ~OneWayDescriptorMatch();
// Sets one way descriptor parameters
void initialize( const Params& _params, OneWayDescriptorBase *_base = 0 );
// Calculates one way descriptors for a set of keypoints
virtual void add( const Mat& image, vector<KeyPoint>& keypoints );
// Calculates one way descriptors for a set of keypoints
virtual void add( KeyPointCollection& keypoints );
// Matches a set of keypoints from a single image of the training set.
// A rectangle with a center in a keypoint and size
// (patch_width/2*scale, patch_height/2*scale) is cropped from the source image
// for each keypoint. scale is iterated from DescriptorOneWayParams::min_scale
// to DescriptorOneWayParams::max_scale. The minimum distance to each
// training patch with all its affine poses is found over all scales.
// The class ID of a match is returned for each keypoint. The distance
// is calculated over PCA components loaded with DescriptorOneWay::Initialize,
// kd tree is used for finding minimum distances.
virtual void match( const Mat& image, vector<KeyPoint>& points,
vector<int>& indices );
// Classify a set of keypoints. The same as match, but returns point
// classes rather than indices.
virtual void classify( const Mat& image, vector<KeyPoint>& points );
// Clears keypoints storing in collection and OneWayDescriptorBase
virtual void clear ();
// Reads match object from a file node
virtual void read (const FileNode &fn);
// Writes match object to a file storage
virtual void write (FileStorage& fs) const;
protected:
Ptr<OneWayDescriptorBase> base;
Params params;
};
Wrapping class for computing, matching and classification of descriptors using RTreeClassifier() class.
class CV_EXPORTS CalonderDescriptorMatch : public GenericDescriptorMatch
{
public:
class Params
{
public:
static const int DEFAULT_NUM_TREES = 80;
static const int DEFAULT_DEPTH = 9;
static const int DEFAULT_VIEWS = 5000;
static const size_t DEFAULT_REDUCED_NUM_DIM = 176;
static const size_t DEFAULT_NUM_QUANT_BITS = 4;
static const int DEFAULT_PATCH_SIZE = PATCH_SIZE;
Params( const RNG& _rng = RNG(),
const PatchGenerator& _patchGen = PatchGenerator(),
int _numTrees=DEFAULT_NUM_TREES,
int _depth=DEFAULT_DEPTH,
int _views=DEFAULT_VIEWS,
size_t _reducedNumDim=DEFAULT_REDUCED_NUM_DIM,
int _numQuantBits=DEFAULT_NUM_QUANT_BITS,
bool _printStatus=true,
int _patchSize=DEFAULT_PATCH_SIZE );
Params( const string& _filename );
RNG rng;
PatchGenerator patchGen;
int numTrees;
int depth;
int views;
int patchSize;
size_t reducedNumDim;
int numQuantBits;
bool printStatus;
string filename;
};
CalonderDescriptorMatch();
CalonderDescriptorMatch( const Params& _params );
virtual ~CalonderDescriptorMatch();
void initialize( const Params& _params );
virtual void add( const Mat& image, vector<KeyPoint>& keypoints );
virtual void match( const Mat& image, vector<KeyPoint>& keypoints,
vector<int>& indices );
virtual void classify( const Mat& image, vector<KeyPoint>& keypoints );
virtual void clear ();
virtual void read( const FileNode &fn );
virtual void write( FileStorage& fs ) const;
protected:
...
};
Wrapping class for computing, matching and classification of descriptors using FernClassifier() class.
class FernDescriptorMatch : public GenericDescriptorMatch
{
public:
class Params
{
public:
Params( int _nclasses=0,
int _patchSize=FernClassifier::PATCH_SIZE,
int _signatureSize=FernClassifier::DEFAULT_SIGNATURE_SIZE,
int _nstructs=FernClassifier::DEFAULT_STRUCTS,
int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE,
int _nviews=FernClassifier::DEFAULT_VIEWS,
int _compressionMethod=FernClassifier::COMPRESSION_NONE,
const PatchGenerator& patchGenerator=PatchGenerator() );
Params( const string& _filename );
int nclasses;
int patchSize;
int signatureSize;
int nstructs;
int structSize;
int nviews;
int compressionMethod;
PatchGenerator patchGenerator;
string filename;
};
FernDescriptorMatch();
FernDescriptorMatch( const Params& _params );
virtual ~FernDescriptorMatch();
void initialize( const Params& _params );
virtual void add( const Mat& image, vector<KeyPoint>& keypoints );
virtual void match( const Mat& image, vector<KeyPoint>& keypoints,
vector<int>& indices );
virtual void classify( const Mat& image, vector<KeyPoint>& keypoints );
virtual void clear ();
virtual void read( const FileNode &fn );
virtual void write( FileStorage& fs ) const;
protected:
...
};
Match is a line connecting two keypoints (circles).
param img1: First source image.
- keypoints1 Keypoints from first source image.
- img1 Second source image.
- keypoints2 Keypoints from second source image.
- matches Matches from first image to second one, i.e. keypoints1[i] has corresponding point keypoints2[matches[i]]
- outImg Output image. Its content depends on flags value what is drawn in output image. See below possible flags bit values.
- matchColor Color of matches (lines and connected keypoints). If matchColor ==Scalar::all(-1) color will be generated randomly.
- singlePointColor Color of single keypoints (circles), i.e. keypoints not having the matches. If singlePointColor ==Scalar::all(-1) color will be generated randomly.
- matchesMask Mask determining which matches will be drawn. If mask is empty all matches will be drawn.
- flags Each bit of flags sets some feature of drawing. Possible flags bit values is defined by DrawMatchesFlags, see below.
struct DrawMatchesFlags
{
enum{ DEFAULT = 0, // Output image matrix will be created (Mat::create),
// i.e. existing memory of output image may be reused.
// Two source image, matches and single keypoints will be drawn.
DRAW_OVER_OUTIMG = 1, // Output image matrix will not be created (Mat::create).
// Matches will be drawn on existing content
// of output image.
NOT_DRAW_SINGLE_POINTS = 2 // Single keypoints will not be drawn.
};
};