2010-05-12 01:44:00 +08:00
|
|
|
/*M///////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
|
|
|
//
|
|
|
|
// By downloading, copying, installing or using the software you agree to this license.
|
|
|
|
// If you do not agree to this license, do not download, install,
|
|
|
|
// copy or use the software.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// License Agreement
|
|
|
|
// For Open Source Computer Vision Library
|
|
|
|
//
|
|
|
|
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
|
|
|
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
|
|
|
// Third party copyrights are property of their respective owners.
|
|
|
|
//
|
|
|
|
// Redistribution and use in source and binary forms, with or without modification,
|
|
|
|
// are permitted provided that the following conditions are met:
|
|
|
|
//
|
|
|
|
// * Redistribution's of source code must retain the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer.
|
|
|
|
//
|
|
|
|
// * Redistribution's in binary form must reproduce the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
|
|
// and/or other materials provided with the distribution.
|
|
|
|
//
|
|
|
|
// * The name of the copyright holders may not be used to endorse or promote products
|
|
|
|
// derived from this software without specific prior written permission.
|
|
|
|
//
|
|
|
|
// This software is provided by the copyright holders and contributors "as is" and
|
|
|
|
// any express or implied warranties, including, but not limited to, the implied
|
|
|
|
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
|
|
|
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
|
|
|
// indirect, incidental, special, exemplary, or consequential damages
|
|
|
|
// (including, but not limited to, procurement of substitute goods or services;
|
|
|
|
// loss of use, data, or profits; or business interruption) however caused
|
|
|
|
// and on any theory of liability, whether in contract, strict liability,
|
|
|
|
// or tort (including negligence or otherwise) arising in any way out of
|
|
|
|
// the use of this software, even if advised of the possibility of such damage.
|
|
|
|
//
|
|
|
|
//M*/
|
|
|
|
|
|
|
|
#ifndef __OPENCV_FEATURES_2D_HPP__
|
|
|
|
#define __OPENCV_FEATURES_2D_HPP__
|
|
|
|
|
|
|
|
#include "opencv2/core/core.hpp"
|
2011-07-14 07:04:39 +08:00
|
|
|
#include "opencv2/flann/miniflann.hpp"
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
2010-05-12 15:33:21 +08:00
|
|
|
#include <limits>
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef struct CvSURFPoint
|
|
|
|
{
|
|
|
|
CvPoint2D32f pt;
|
2010-12-24 07:01:18 +08:00
|
|
|
|
|
|
|
int laplacian;
|
|
|
|
int size;
|
|
|
|
float dir;
|
|
|
|
float hessian;
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
} CvSURFPoint;
|
|
|
|
|
|
|
|
CV_INLINE CvSURFPoint cvSURFPoint( CvPoint2D32f pt, int laplacian,
|
|
|
|
int size, float dir CV_DEFAULT(0),
|
|
|
|
float hessian CV_DEFAULT(0))
|
|
|
|
{
|
|
|
|
CvSURFPoint kp;
|
2010-12-24 07:01:18 +08:00
|
|
|
|
|
|
|
kp.pt = pt;
|
2010-05-12 01:44:00 +08:00
|
|
|
kp.laplacian = laplacian;
|
2010-12-24 07:01:18 +08:00
|
|
|
kp.size = size;
|
|
|
|
kp.dir = dir;
|
|
|
|
kp.hessian = hessian;
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
return kp;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct CvSURFParams
|
|
|
|
{
|
2010-12-24 07:01:18 +08:00
|
|
|
int extended;
|
2011-06-08 17:23:33 +08:00
|
|
|
int upright;
|
2010-05-12 01:44:00 +08:00
|
|
|
double hessianThreshold;
|
|
|
|
|
2010-12-24 07:01:18 +08:00
|
|
|
int nOctaves;
|
|
|
|
int nOctaveLayers;
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
} CvSURFParams;
|
|
|
|
|
|
|
|
CVAPI(CvSURFParams) cvSURFParams( double hessianThreshold, int extended CV_DEFAULT(0) );
|
|
|
|
|
|
|
|
// If useProvidedKeyPts!=0, keypoints are not detected, but descriptors are computed
|
|
|
|
// at the locations provided in keypoints (a CvSeq of CvSURFPoint).
|
|
|
|
CVAPI(void) cvExtractSURF( const CvArr* img, const CvArr* mask,
|
|
|
|
CvSeq** keypoints, CvSeq** descriptors,
|
|
|
|
CvMemStorage* storage, CvSURFParams params, int useProvidedKeyPts CV_DEFAULT(0) );
|
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
/*!
|
|
|
|
Maximal Stable Regions Parameters
|
|
|
|
*/
|
2010-05-12 01:44:00 +08:00
|
|
|
typedef struct CvMSERParams
|
|
|
|
{
|
2010-06-01 00:47:13 +08:00
|
|
|
//! delta, in the code, it compares (size_{i}-size_{i-delta})/size_{i-delta}
|
2010-05-12 01:44:00 +08:00
|
|
|
int delta;
|
2010-06-01 00:47:13 +08:00
|
|
|
//! prune the area which bigger than maxArea
|
2010-05-12 01:44:00 +08:00
|
|
|
int maxArea;
|
2010-06-01 00:47:13 +08:00
|
|
|
//! prune the area which smaller than minArea
|
2010-05-12 01:44:00 +08:00
|
|
|
int minArea;
|
2010-06-01 00:47:13 +08:00
|
|
|
//! prune the area have simliar size to its children
|
2010-05-12 01:44:00 +08:00
|
|
|
float maxVariation;
|
2010-06-01 00:47:13 +08:00
|
|
|
//! trace back to cut off mser with diversity < min_diversity
|
2010-05-12 01:44:00 +08:00
|
|
|
float minDiversity;
|
2010-06-01 00:47:13 +08:00
|
|
|
|
|
|
|
/////// the next few params for MSER of color image
|
|
|
|
|
|
|
|
//! for color image, the evolution steps
|
2010-05-12 01:44:00 +08:00
|
|
|
int maxEvolution;
|
2010-06-01 00:47:13 +08:00
|
|
|
//! the area threshold to cause re-initialize
|
2010-05-12 01:44:00 +08:00
|
|
|
double areaThreshold;
|
2010-06-01 00:47:13 +08:00
|
|
|
//! ignore too small margin
|
2010-05-12 01:44:00 +08:00
|
|
|
double minMargin;
|
2010-06-01 00:47:13 +08:00
|
|
|
//! the aperture size for edge blur
|
2010-05-12 01:44:00 +08:00
|
|
|
int edgeBlurSize;
|
|
|
|
} CvMSERParams;
|
|
|
|
|
|
|
|
CVAPI(CvMSERParams) cvMSERParams( int delta CV_DEFAULT(5), int min_area CV_DEFAULT(60),
|
|
|
|
int max_area CV_DEFAULT(14400), float max_variation CV_DEFAULT(.25f),
|
|
|
|
float min_diversity CV_DEFAULT(.2f), int max_evolution CV_DEFAULT(200),
|
|
|
|
double area_threshold CV_DEFAULT(1.01),
|
|
|
|
double min_margin CV_DEFAULT(.003),
|
|
|
|
int edge_blur_size CV_DEFAULT(5) );
|
|
|
|
|
|
|
|
// Extracts the contours of Maximally Stable Extremal Regions
|
|
|
|
CVAPI(void) cvExtractMSER( CvArr* _img, CvArr* _mask, CvSeq** contours, CvMemStorage* storage, CvMSERParams params );
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct CvStarKeypoint
|
|
|
|
{
|
|
|
|
CvPoint pt;
|
|
|
|
int size;
|
|
|
|
float response;
|
|
|
|
} CvStarKeypoint;
|
|
|
|
|
|
|
|
CV_INLINE CvStarKeypoint cvStarKeypoint(CvPoint pt, int size, float response)
|
|
|
|
{
|
|
|
|
CvStarKeypoint kpt;
|
|
|
|
kpt.pt = pt;
|
|
|
|
kpt.size = size;
|
|
|
|
kpt.response = response;
|
|
|
|
return kpt;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct CvStarDetectorParams
|
|
|
|
{
|
|
|
|
int maxSize;
|
|
|
|
int responseThreshold;
|
|
|
|
int lineThresholdProjected;
|
|
|
|
int lineThresholdBinarized;
|
|
|
|
int suppressNonmaxSize;
|
|
|
|
} CvStarDetectorParams;
|
|
|
|
|
|
|
|
CV_INLINE CvStarDetectorParams cvStarDetectorParams(
|
|
|
|
int maxSize CV_DEFAULT(45),
|
|
|
|
int responseThreshold CV_DEFAULT(30),
|
|
|
|
int lineThresholdProjected CV_DEFAULT(10),
|
|
|
|
int lineThresholdBinarized CV_DEFAULT(8),
|
|
|
|
int suppressNonmaxSize CV_DEFAULT(5))
|
|
|
|
{
|
|
|
|
CvStarDetectorParams params;
|
|
|
|
params.maxSize = maxSize;
|
|
|
|
params.responseThreshold = responseThreshold;
|
|
|
|
params.lineThresholdProjected = lineThresholdProjected;
|
|
|
|
params.lineThresholdBinarized = lineThresholdBinarized;
|
|
|
|
params.suppressNonmaxSize = suppressNonmaxSize;
|
|
|
|
|
|
|
|
return params;
|
|
|
|
}
|
|
|
|
|
|
|
|
CVAPI(CvSeq*) cvGetStarKeypoints( const CvArr* img, CvMemStorage* storage,
|
|
|
|
CvStarDetectorParams params CV_DEFAULT(cvStarDetectorParams()));
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
|
2010-05-26 20:34:48 +08:00
|
|
|
namespace cv
|
|
|
|
{
|
2010-07-26 16:58:46 +08:00
|
|
|
struct CV_EXPORTS DefaultRngAuto
|
|
|
|
{
|
|
|
|
const uint64 old_state;
|
|
|
|
|
2010-10-12 20:36:20 +08:00
|
|
|
DefaultRngAuto() : old_state(theRNG().state) { theRNG().state = (uint64)-1; }
|
2010-07-26 16:58:46 +08:00
|
|
|
~DefaultRngAuto() { theRNG().state = old_state; }
|
|
|
|
|
|
|
|
DefaultRngAuto& operator=(const DefaultRngAuto&);
|
|
|
|
};
|
|
|
|
|
2010-05-26 20:34:48 +08:00
|
|
|
|
2010-05-18 01:36:58 +08:00
|
|
|
// CvAffinePose: defines a parameterized affine transformation of an image patch.
|
|
|
|
// An image patch is rotated on angle phi (in degrees), then scaled lambda1 times
|
|
|
|
// along horizontal and lambda2 times along vertical direction, and then rotated again
|
|
|
|
// on angle (theta - phi).
|
|
|
|
class CV_EXPORTS CvAffinePose
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
float phi;
|
|
|
|
float theta;
|
|
|
|
float lambda1;
|
|
|
|
float lambda2;
|
|
|
|
};
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
/*!
|
|
|
|
The Keypoint Class
|
|
|
|
|
|
|
|
The class instance stores a keypoint, i.e. a point feature found by one of many available keypoint detectors, such as
|
|
|
|
Harris corner detector, cv::FAST, cv::StarDetector, cv::SURF, cv::SIFT, cv::LDetector etc.
|
|
|
|
|
|
|
|
The keypoint is characterized by the 2D position, scale
|
|
|
|
(proportional to the diameter of the neighborhood that needs to be taken into account),
|
|
|
|
orientation and some other parameters. The keypoint neighborhood is then analyzed by another algorithm that builds a descriptor
|
|
|
|
(usually represented as a feature vector). The keypoints representing the same object in different images can then be matched using
|
|
|
|
cv::KDTree or another method.
|
|
|
|
*/
|
2010-11-03 01:58:22 +08:00
|
|
|
class CV_EXPORTS_W_SIMPLE KeyPoint
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-06-01 00:47:13 +08:00
|
|
|
public:
|
|
|
|
//! the default constructor
|
2010-11-03 01:58:22 +08:00
|
|
|
CV_WRAP KeyPoint() : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {}
|
2010-06-01 00:47:13 +08:00
|
|
|
//! the full constructor
|
2010-05-12 01:44:00 +08:00
|
|
|
KeyPoint(Point2f _pt, float _size, float _angle=-1,
|
|
|
|
float _response=0, int _octave=0, int _class_id=-1)
|
|
|
|
: pt(_pt), size(_size), angle(_angle),
|
|
|
|
response(_response), octave(_octave), class_id(_class_id) {}
|
2010-06-01 00:47:13 +08:00
|
|
|
//! another form of the full constructor
|
2010-11-03 01:58:22 +08:00
|
|
|
CV_WRAP KeyPoint(float x, float y, float _size, float _angle=-1,
|
2010-05-12 01:44:00 +08:00
|
|
|
float _response=0, int _octave=0, int _class_id=-1)
|
|
|
|
: pt(x, y), size(_size), angle(_angle),
|
|
|
|
response(_response), octave(_octave), class_id(_class_id) {}
|
2011-05-31 22:24:45 +08:00
|
|
|
|
|
|
|
size_t hash() const;
|
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
//! converts vector of keypoints to vector of points
|
2010-10-17 04:34:34 +08:00
|
|
|
static void convert(const std::vector<KeyPoint>& keypoints,
|
|
|
|
CV_OUT std::vector<Point2f>& points2f,
|
2010-06-15 23:19:11 +08:00
|
|
|
const std::vector<int>& keypointIndexes=std::vector<int>());
|
2010-06-01 00:47:13 +08:00
|
|
|
//! converts vector of points to the vector of keypoints, where each keypoint is assigned the same size and the same orientation
|
2010-10-17 04:34:34 +08:00
|
|
|
static void convert(const std::vector<Point2f>& points2f,
|
|
|
|
CV_OUT std::vector<KeyPoint>& keypoints,
|
2010-05-12 01:44:00 +08:00
|
|
|
float size=1, float response=1, int octave=0, int class_id=-1);
|
2010-07-28 18:47:48 +08:00
|
|
|
|
|
|
|
//! computes overlap for pair of keypoints;
|
|
|
|
//! overlap is a ratio between area of keypoint regions intersection and
|
|
|
|
//! area of keypoint regions union (now keypoint region is circle)
|
|
|
|
static float overlap(const KeyPoint& kp1, const KeyPoint& kp2);
|
|
|
|
|
2010-11-03 01:58:22 +08:00
|
|
|
CV_PROP_RW Point2f pt; //!< coordinates of the keypoints
|
2011-05-22 04:17:45 +08:00
|
|
|
CV_PROP_RW float size; //!< diameter of the meaningful keypoint neighborhood
|
2010-11-03 01:58:22 +08:00
|
|
|
CV_PROP_RW float angle; //!< computed orientation of the keypoint (-1 if not applicable)
|
|
|
|
CV_PROP_RW float response; //!< the response by which the most strong keypoints have been selected. Can be used for the further sorting or subsampling
|
|
|
|
CV_PROP_RW int octave; //!< octave (pyramid layer) from which the keypoint has been extracted
|
|
|
|
CV_PROP_RW int class_id; //!< object class (if the keypoints need to be clustered by an object they belong to)
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
2011-05-31 22:24:45 +08:00
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
//! writes vector of keypoints to the file storage
|
2010-11-03 01:58:22 +08:00
|
|
|
CV_EXPORTS void write(FileStorage& fs, const string& name, const vector<KeyPoint>& keypoints);
|
2010-06-01 00:47:13 +08:00
|
|
|
//! reads vector of keypoints from the specified file storage node
|
2010-11-03 01:58:22 +08:00
|
|
|
CV_EXPORTS void read(const FileNode& node, CV_OUT vector<KeyPoint>& keypoints);
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-05-02 01:38:52 +08:00
|
|
|
/*
|
|
|
|
* A class filters a vector of keypoints.
|
|
|
|
* Because now it is difficult to provide a convenient interface for all usage scenarios of the keypoints filter class,
|
2011-06-01 02:18:02 +08:00
|
|
|
* it has only 4 needed by now static methods.
|
2011-05-02 01:38:52 +08:00
|
|
|
*/
|
|
|
|
class CV_EXPORTS KeyPointsFilter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
KeyPointsFilter(){}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove keypoints within borderPixels of an image edge.
|
|
|
|
*/
|
|
|
|
static void runByImageBorder( vector<KeyPoint>& keypoints, Size imageSize, int borderSize );
|
|
|
|
/*
|
|
|
|
* Remove keypoints of sizes out of range.
|
|
|
|
*/
|
|
|
|
static void runByKeypointSize( vector<KeyPoint>& keypoints, float minSize, float maxSize=std::numeric_limits<float>::max() );
|
2011-05-05 18:10:46 +08:00
|
|
|
/*
|
|
|
|
* Remove keypoints from some image by mask for pixels of this image.
|
|
|
|
*/
|
|
|
|
static void runByPixelsMask( vector<KeyPoint>& keypoints, const Mat& mask );
|
2011-06-01 02:18:02 +08:00
|
|
|
/*
|
|
|
|
* Remove duplicated keypoints.
|
|
|
|
*/
|
|
|
|
static void removeDuplicated( vector<KeyPoint>& keypoints );
|
2011-05-02 01:38:52 +08:00
|
|
|
};
|
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
/*!
|
|
|
|
SIFT implementation.
|
|
|
|
|
|
|
|
The class implements SIFT algorithm by D. Lowe.
|
|
|
|
*/
|
2011-06-01 02:18:02 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
class CV_EXPORTS SIFT
|
|
|
|
{
|
|
|
|
public:
|
2010-11-16 23:42:31 +08:00
|
|
|
struct CV_EXPORTS CommonParams
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
static const int DEFAULT_NOCTAVES = 4;
|
|
|
|
static const int DEFAULT_NOCTAVE_LAYERS = 3;
|
|
|
|
static const int DEFAULT_FIRST_OCTAVE = -1;
|
2010-12-24 07:01:18 +08:00
|
|
|
enum { FIRST_ANGLE = 0, AVERAGE_ANGLE = 1 };
|
2010-05-20 00:02:30 +08:00
|
|
|
|
2010-06-09 22:23:15 +08:00
|
|
|
CommonParams();
|
2011-06-01 02:18:02 +08:00
|
|
|
CommonParams( int _nOctaves, int _nOctaveLayers, int /*_firstOctave*/, int /*_angleMode*/ );
|
2011-06-07 15:41:59 +08:00
|
|
|
CommonParams( int _nOctaves, int _nOctaveLayers );
|
2011-06-01 02:18:02 +08:00
|
|
|
int nOctaves, nOctaveLayers;
|
|
|
|
int firstOctave; // it is not used now (firstOctave == 0 always)
|
|
|
|
int angleMode; // it is not used now
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
2010-11-16 23:42:31 +08:00
|
|
|
struct CV_EXPORTS DetectorParams
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2011-06-01 02:18:02 +08:00
|
|
|
static double GET_DEFAULT_THRESHOLD() { return 0.04; }
|
2010-05-12 01:44:00 +08:00
|
|
|
static double GET_DEFAULT_EDGE_THRESHOLD() { return 10.0; }
|
2010-05-20 00:02:30 +08:00
|
|
|
|
2010-06-09 22:23:15 +08:00
|
|
|
DetectorParams();
|
|
|
|
DetectorParams( double _threshold, double _edgeThreshold );
|
2010-05-12 01:44:00 +08:00
|
|
|
double threshold, edgeThreshold;
|
|
|
|
};
|
|
|
|
|
2010-11-16 23:42:31 +08:00
|
|
|
struct CV_EXPORTS DescriptorParams
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
static double GET_DEFAULT_MAGNIFICATION() { return 3.0; }
|
|
|
|
static const bool DEFAULT_IS_NORMALIZE = true;
|
2010-05-18 01:36:58 +08:00
|
|
|
static const int DESCRIPTOR_SIZE = 128;
|
2010-06-09 22:23:15 +08:00
|
|
|
|
|
|
|
DescriptorParams();
|
2011-06-01 02:18:02 +08:00
|
|
|
DescriptorParams( double _magnification, bool /*_isNormalize*/, bool _recalculateAngles );
|
|
|
|
DescriptorParams( bool _recalculateAngles );
|
2010-05-12 01:44:00 +08:00
|
|
|
double magnification;
|
2011-06-01 02:18:02 +08:00
|
|
|
bool isNormalize; // it is not used now (true always)
|
2010-05-20 00:02:30 +08:00
|
|
|
bool recalculateAngles;
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
SIFT();
|
2010-06-01 00:47:13 +08:00
|
|
|
//! sift-detector constructor
|
2010-05-20 00:02:30 +08:00
|
|
|
SIFT( double _threshold, double _edgeThreshold,
|
2010-05-12 01:44:00 +08:00
|
|
|
int _nOctaves=CommonParams::DEFAULT_NOCTAVES,
|
|
|
|
int _nOctaveLayers=CommonParams::DEFAULT_NOCTAVE_LAYERS,
|
2010-05-20 00:02:30 +08:00
|
|
|
int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE,
|
|
|
|
int _angleMode=CommonParams::FIRST_ANGLE );
|
2010-06-01 00:47:13 +08:00
|
|
|
//! sift-descriptor constructor
|
2010-05-12 01:44:00 +08:00
|
|
|
SIFT( double _magnification, bool _isNormalize=true,
|
2010-05-20 00:02:30 +08:00
|
|
|
bool _recalculateAngles = true,
|
2010-05-12 01:44:00 +08:00
|
|
|
int _nOctaves=CommonParams::DEFAULT_NOCTAVES,
|
|
|
|
int _nOctaveLayers=CommonParams::DEFAULT_NOCTAVE_LAYERS,
|
2010-05-20 00:02:30 +08:00
|
|
|
int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE,
|
|
|
|
int _angleMode=CommonParams::FIRST_ANGLE );
|
2010-05-12 01:44:00 +08:00
|
|
|
SIFT( const CommonParams& _commParams,
|
|
|
|
const DetectorParams& _detectorParams = DetectorParams(),
|
|
|
|
const DescriptorParams& _descriptorParams = DescriptorParams() );
|
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
//! returns the descriptor size in floats (128)
|
2011-02-01 00:23:26 +08:00
|
|
|
int descriptorSize() const;
|
2010-06-01 00:47:13 +08:00
|
|
|
//! finds the keypoints using SIFT algorithm
|
2010-05-12 01:44:00 +08:00
|
|
|
void operator()(const Mat& img, const Mat& mask,
|
|
|
|
vector<KeyPoint>& keypoints) const;
|
2010-06-09 22:23:15 +08:00
|
|
|
//! finds the keypoints and computes descriptors for them using SIFT algorithm.
|
|
|
|
//! Optionally it can compute descriptors for the user-provided keypoints
|
2010-05-12 01:44:00 +08:00
|
|
|
void operator()(const Mat& img, const Mat& mask,
|
|
|
|
vector<KeyPoint>& keypoints,
|
|
|
|
Mat& descriptors,
|
|
|
|
bool useProvidedKeypoints=false) const;
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2011-02-01 00:23:26 +08:00
|
|
|
CommonParams getCommonParams () const;
|
|
|
|
DetectorParams getDetectorParams () const;
|
|
|
|
DescriptorParams getDescriptorParams () const;
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
protected:
|
|
|
|
CommonParams commParams;
|
|
|
|
DetectorParams detectorParams;
|
|
|
|
DescriptorParams descriptorParams;
|
|
|
|
};
|
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
|
|
|
|
/*!
|
|
|
|
SURF implementation.
|
|
|
|
|
|
|
|
The class implements SURF algorithm by H. Bay et al.
|
|
|
|
*/
|
2010-10-28 02:26:39 +08:00
|
|
|
class CV_EXPORTS_W SURF : public CvSURFParams
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-06-01 00:47:13 +08:00
|
|
|
//! the default constructor
|
2010-10-28 02:26:39 +08:00
|
|
|
CV_WRAP SURF();
|
2010-06-01 00:47:13 +08:00
|
|
|
//! the full constructor taking all the necessary parameters
|
2010-10-28 02:26:39 +08:00
|
|
|
CV_WRAP SURF(double _hessianThreshold, int _nOctaves=4,
|
2011-06-08 17:23:33 +08:00
|
|
|
int _nOctaveLayers=2, bool _extended=false, bool _upright=false);
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
//! returns the descriptor size in float's (64 or 128)
|
2010-10-28 02:26:39 +08:00
|
|
|
CV_WRAP int descriptorSize() const;
|
2010-06-01 00:47:13 +08:00
|
|
|
//! finds the keypoints using fast hessian detector used in SURF
|
2010-10-17 04:34:34 +08:00
|
|
|
CV_WRAP_AS(detect) void operator()(const Mat& img, const Mat& mask,
|
|
|
|
CV_OUT vector<KeyPoint>& keypoints) const;
|
2010-06-01 00:47:13 +08:00
|
|
|
//! finds the keypoints and computes their descriptors. Optionally it can compute descriptors for the user-provided keypoints
|
2010-10-17 04:34:34 +08:00
|
|
|
CV_WRAP_AS(detect) void operator()(const Mat& img, const Mat& mask,
|
|
|
|
CV_OUT vector<KeyPoint>& keypoints,
|
|
|
|
CV_OUT vector<float>& descriptors,
|
2010-05-12 01:44:00 +08:00
|
|
|
bool useProvidedKeypoints=false) const;
|
|
|
|
};
|
|
|
|
|
2011-05-21 06:25:53 +08:00
|
|
|
/*!
|
|
|
|
ORB implementation.
|
|
|
|
*/
|
|
|
|
class CV_EXPORTS ORB
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
/** the size of the signature in bytes */
|
2011-05-23 15:58:35 +08:00
|
|
|
enum { kBytes = 32 };
|
2011-05-21 06:25:53 +08:00
|
|
|
|
2011-05-23 15:58:35 +08:00
|
|
|
struct CV_EXPORTS CommonParams
|
2011-05-21 06:25:53 +08:00
|
|
|
{
|
2011-06-01 10:09:31 +08:00
|
|
|
enum { DEFAULT_N_LEVELS = 3, DEFAULT_FIRST_LEVEL = 0};
|
2011-05-21 06:25:53 +08:00
|
|
|
|
|
|
|
/** default constructor */
|
2011-06-01 10:09:31 +08:00
|
|
|
CommonParams(float scale_factor = 1.2f, unsigned int n_levels = DEFAULT_N_LEVELS, int edge_threshold = 31,
|
|
|
|
unsigned int first_level = DEFAULT_FIRST_LEVEL) :
|
2011-05-21 06:25:53 +08:00
|
|
|
scale_factor_(scale_factor), n_levels_(n_levels), first_level_(first_level >= n_levels ? 0 : first_level),
|
2011-06-01 10:09:31 +08:00
|
|
|
edge_threshold_(edge_threshold)
|
2011-05-21 06:25:53 +08:00
|
|
|
{
|
2011-06-01 10:09:31 +08:00
|
|
|
// No other patch size is supported right now
|
|
|
|
patch_size_ = 31;
|
2011-05-21 06:25:53 +08:00
|
|
|
}
|
|
|
|
void read(const FileNode& fn);
|
|
|
|
void write(FileStorage& fs) const;
|
|
|
|
|
|
|
|
/** Coefficient by which we divide the dimensions from one scale pyramid level to the next */
|
|
|
|
float scale_factor_;
|
|
|
|
/** The number of levels in the scale pyramid */
|
|
|
|
unsigned int n_levels_;
|
|
|
|
/** The level at which the image is given
|
|
|
|
* if 1, that means we will also look at the image scale_factor_ times bigger
|
|
|
|
*/
|
|
|
|
unsigned int first_level_;
|
2011-06-01 10:09:31 +08:00
|
|
|
/** How far from the boundary the points should be */
|
|
|
|
int edge_threshold_;
|
|
|
|
|
|
|
|
friend class ORB;
|
|
|
|
protected:
|
2011-05-21 06:25:53 +08:00
|
|
|
/** The size of the patch that will be used for orientation and comparisons */
|
2011-05-23 15:58:35 +08:00
|
|
|
int patch_size_;
|
2011-05-21 06:25:53 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/** Constructor
|
|
|
|
* @param n_features the number of desired features
|
|
|
|
* @param detector_params parameters to use
|
|
|
|
*/
|
2011-05-28 01:17:02 +08:00
|
|
|
ORB(size_t n_features = 500, const CommonParams & detector_params = CommonParams());
|
2011-05-21 06:25:53 +08:00
|
|
|
|
2011-06-02 02:24:53 +08:00
|
|
|
/** destructor to empty the patterns */
|
|
|
|
~ORB();
|
|
|
|
|
2011-05-21 06:25:53 +08:00
|
|
|
/** returns the descriptor size in bytes */
|
|
|
|
int descriptorSize() const;
|
|
|
|
|
|
|
|
/** Compute the ORB features and descriptors on an image
|
|
|
|
* @param img the image to compute the features and descriptors on
|
|
|
|
* @param mask the mask to apply
|
|
|
|
* @param keypoints the resulting keypoints
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
operator()(const cv::Mat &image, const cv::Mat &mask, std::vector<cv::KeyPoint> & keypoints);
|
|
|
|
|
|
|
|
/** Compute the ORB features and descriptors on an image
|
|
|
|
* @param img the image to compute the features and descriptors on
|
|
|
|
* @param mask the mask to apply
|
|
|
|
* @param keypoints the resulting keypoints
|
|
|
|
* @param descriptors the resulting descriptors
|
|
|
|
* @param useProvidedKeypoints if true, the keypoints are used as an input
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
operator()(const cv::Mat &image, const cv::Mat &mask, std::vector<cv::KeyPoint> & keypoints, cv::Mat & descriptors,
|
|
|
|
bool useProvidedKeypoints = false);
|
|
|
|
|
|
|
|
private:
|
|
|
|
/** The size of the patch used when comparing regions in the patterns */
|
|
|
|
static const int kKernelWidth = 5;
|
|
|
|
|
|
|
|
/** Compute the ORB features and descriptors on an image
|
|
|
|
* @param image the image to compute the features and descriptors on
|
|
|
|
* @param mask the mask to apply
|
|
|
|
* @param keypoints the resulting keypoints
|
|
|
|
* @param descriptors the resulting descriptors
|
|
|
|
* @param do_keypoints if true, the keypoints are computed, otherwise used as an input
|
|
|
|
* @param do_descriptors if true, also computes the descriptors
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
operator()(const cv::Mat &image, const cv::Mat &mask, std::vector<cv::KeyPoint> & keypoints, cv::Mat & descriptors,
|
|
|
|
bool do_keypoints, bool do_descriptors);
|
|
|
|
|
|
|
|
/** Compute the ORB keypoints on an image
|
|
|
|
* @param image_pyramid the image pyramid to compute the features and descriptors on
|
|
|
|
* @param mask_pyramid the masks to apply at every level
|
|
|
|
* @param keypoints the resulting keypoints, clustered per level
|
|
|
|
*/
|
|
|
|
void computeKeyPoints(const std::vector<cv::Mat>& image_pyramid, const std::vector<cv::Mat>& mask_pyramid,
|
|
|
|
std::vector<std::vector<cv::KeyPoint> >& keypoints) const;
|
|
|
|
|
|
|
|
/** Compute the ORB keypoint orientations
|
|
|
|
* @param image the image to compute the features and descriptors on
|
|
|
|
* @param integral_image the integral image of the image (can be empty, but the computation will be slower)
|
|
|
|
* @param level the scale at which we compute the orientation
|
|
|
|
* @param keypoints the resulting keypoints
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
computeOrientation(const cv::Mat& image, const cv::Mat& integral_image, unsigned int level,
|
|
|
|
std::vector<cv::KeyPoint>& keypoints) const;
|
|
|
|
|
|
|
|
/** Compute the ORB descriptors
|
|
|
|
* @param image the image to compute the features and descriptors on
|
|
|
|
* @param integral_image the integral image of the image (can be empty, but the computation will be slower)
|
|
|
|
* @param level the scale at which we compute the orientation
|
|
|
|
* @param keypoints the keypoints to use
|
|
|
|
* @param descriptors the resulting descriptors
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
computeDescriptors(const cv::Mat& image, const cv::Mat& integral_image, unsigned int level,
|
|
|
|
std::vector<cv::KeyPoint>& keypoints, cv::Mat & descriptors) const;
|
|
|
|
|
|
|
|
/** Compute the integral image and upadte the cached values
|
|
|
|
* @param image the image to compute the features and descriptors on
|
|
|
|
* @param level the scale at which we compute the orientation
|
|
|
|
* @param descriptors the resulting descriptors
|
|
|
|
*/
|
|
|
|
void computeIntegralImage(const cv::Mat & image, unsigned int level, cv::Mat &integral_image);
|
|
|
|
|
|
|
|
/** Parameters tuning ORB */
|
|
|
|
CommonParams params_;
|
|
|
|
|
|
|
|
/** size of the half patch used for orientation computation, see Rosin - 1999 - Measuring Corner Properties */
|
|
|
|
int half_patch_size_;
|
|
|
|
|
|
|
|
/** pre-computed offsets used for the Harris verification, one vector per scale */
|
|
|
|
std::vector<std::vector<int> > orientation_horizontal_offsets_;
|
|
|
|
std::vector<std::vector<int> > orientation_vertical_offsets_;
|
|
|
|
|
|
|
|
/** The steps of the integral images for each scale */
|
|
|
|
std::vector<size_t> integral_image_steps_;
|
|
|
|
|
|
|
|
/** The number of desired features per scale */
|
|
|
|
std::vector<size_t> n_features_per_level_;
|
|
|
|
|
|
|
|
/** The overall number of desired features */
|
|
|
|
size_t n_features_;
|
|
|
|
|
|
|
|
/** the end of a row in a circular patch */
|
|
|
|
std::vector<int> u_max_;
|
|
|
|
|
|
|
|
/** The patterns for each level (the patterns are the same, but not their offset */
|
|
|
|
class OrbPatterns;
|
|
|
|
std::vector<OrbPatterns*> patterns_;
|
|
|
|
};
|
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
/*!
|
|
|
|
Maximal Stable Extremal Regions class.
|
|
|
|
|
|
|
|
The class implements MSER algorithm introduced by J. Matas.
|
|
|
|
Unlike SIFT, SURF and many other detectors in OpenCV, this is salient region detector,
|
|
|
|
not the salient point detector.
|
|
|
|
|
|
|
|
It returns the regions, each of those is encoded as a contour.
|
|
|
|
*/
|
2010-10-28 02:26:39 +08:00
|
|
|
class CV_EXPORTS_W MSER : public CvMSERParams
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-06-01 00:47:13 +08:00
|
|
|
//! the default constructor
|
2010-10-28 02:26:39 +08:00
|
|
|
CV_WRAP MSER();
|
2010-06-01 00:47:13 +08:00
|
|
|
//! the full constructor
|
2010-10-28 02:26:39 +08:00
|
|
|
CV_WRAP MSER( int _delta, int _min_area, int _max_area,
|
2010-07-16 20:54:53 +08:00
|
|
|
double _max_variation, double _min_diversity,
|
2010-05-12 01:44:00 +08:00
|
|
|
int _max_evolution, double _area_threshold,
|
|
|
|
double _min_margin, int _edge_blur_size );
|
2010-06-01 00:47:13 +08:00
|
|
|
//! the operator that extracts the MSERs from the image or the specific part of it
|
2010-10-17 04:34:34 +08:00
|
|
|
CV_WRAP_AS(detect) void operator()( const Mat& image,
|
|
|
|
CV_OUT vector<vector<Point> >& msers, const Mat& mask ) const;
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
/*!
|
|
|
|
The "Star" Detector.
|
|
|
|
|
|
|
|
The class implements the keypoint detector introduced by K. Konolige.
|
|
|
|
*/
|
2010-10-28 02:26:39 +08:00
|
|
|
class CV_EXPORTS_W StarDetector : public CvStarDetectorParams
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-06-01 00:47:13 +08:00
|
|
|
//! the default constructor
|
2010-10-28 02:26:39 +08:00
|
|
|
CV_WRAP StarDetector();
|
2010-06-01 00:47:13 +08:00
|
|
|
//! the full constructor
|
2010-10-28 02:26:39 +08:00
|
|
|
CV_WRAP StarDetector(int _maxSize, int _responseThreshold,
|
2010-05-12 01:44:00 +08:00
|
|
|
int _lineThresholdProjected,
|
|
|
|
int _lineThresholdBinarized,
|
|
|
|
int _suppressNonmaxSize);
|
2010-06-01 00:47:13 +08:00
|
|
|
//! finds the keypoints in the image
|
2010-10-17 04:34:34 +08:00
|
|
|
CV_WRAP_AS(detect) void operator()(const Mat& image,
|
|
|
|
CV_OUT vector<KeyPoint>& keypoints) const;
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
//! detects corners using FAST algorithm by E. Rosten
|
2010-10-17 04:34:34 +08:00
|
|
|
CV_EXPORTS void FAST( const Mat& image, CV_OUT vector<KeyPoint>& keypoints,
|
|
|
|
int threshold, bool nonmaxSupression=true );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-06-01 00:47:13 +08:00
|
|
|
/*!
|
2010-07-26 16:58:46 +08:00
|
|
|
The Patch Generator class
|
2010-06-01 00:47:13 +08:00
|
|
|
*/
|
2010-05-12 01:44:00 +08:00
|
|
|
class CV_EXPORTS PatchGenerator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PatchGenerator();
|
|
|
|
PatchGenerator(double _backgroundMin, double _backgroundMax,
|
|
|
|
double _noiseRange, bool _randomBlur=true,
|
|
|
|
double _lambdaMin=0.6, double _lambdaMax=1.5,
|
|
|
|
double _thetaMin=-CV_PI, double _thetaMax=CV_PI,
|
|
|
|
double _phiMin=-CV_PI, double _phiMax=CV_PI );
|
2010-10-28 02:26:39 +08:00
|
|
|
void operator()(const Mat& image, Point2f pt, Mat& patch, Size patchSize, RNG& rng) const;
|
|
|
|
void operator()(const Mat& image, const Mat& transform, Mat& patch,
|
2010-05-12 01:44:00 +08:00
|
|
|
Size patchSize, RNG& rng) const;
|
|
|
|
void warpWholeImage(const Mat& image, Mat& matT, Mat& buf,
|
2010-10-17 04:34:34 +08:00
|
|
|
CV_OUT Mat& warped, int border, RNG& rng) const;
|
2010-05-12 01:44:00 +08:00
|
|
|
void generateRandomTransform(Point2f srcCenter, Point2f dstCenter,
|
2010-10-17 04:34:34 +08:00
|
|
|
CV_OUT Mat& transform, RNG& rng,
|
|
|
|
bool inverse=false) const;
|
2010-05-12 01:44:00 +08:00
|
|
|
void setAffineParam(double lambda, double theta, double phi);
|
|
|
|
|
|
|
|
double backgroundMin, backgroundMax;
|
|
|
|
double noiseRange;
|
|
|
|
bool randomBlur;
|
|
|
|
double lambdaMin, lambdaMax;
|
|
|
|
double thetaMin, thetaMax;
|
|
|
|
double phiMin, phiMax;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class CV_EXPORTS LDetector
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LDetector();
|
|
|
|
LDetector(int _radius, int _threshold, int _nOctaves,
|
|
|
|
int _nViews, double _baseFeatureSize, double _clusteringDistance);
|
2010-10-28 02:26:39 +08:00
|
|
|
void operator()(const Mat& image,
|
2010-10-17 04:34:34 +08:00
|
|
|
CV_OUT vector<KeyPoint>& keypoints,
|
|
|
|
int maxCount=0, bool scaleCoords=true) const;
|
2010-10-28 02:26:39 +08:00
|
|
|
void operator()(const vector<Mat>& pyr,
|
2010-10-17 04:34:34 +08:00
|
|
|
CV_OUT vector<KeyPoint>& keypoints,
|
|
|
|
int maxCount=0, bool scaleCoords=true) const;
|
|
|
|
void getMostStable2D(const Mat& image, CV_OUT vector<KeyPoint>& keypoints,
|
2010-05-12 01:44:00 +08:00
|
|
|
int maxCount, const PatchGenerator& patchGenerator) const;
|
|
|
|
void setVerbose(bool verbose);
|
|
|
|
|
|
|
|
void read(const FileNode& node);
|
|
|
|
void write(FileStorage& fs, const String& name=String()) const;
|
|
|
|
|
|
|
|
int radius;
|
|
|
|
int threshold;
|
|
|
|
int nOctaves;
|
|
|
|
int nViews;
|
|
|
|
bool verbose;
|
|
|
|
|
|
|
|
double baseFeatureSize;
|
|
|
|
double clusteringDistance;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef LDetector YAPE;
|
|
|
|
|
|
|
|
class CV_EXPORTS FernClassifier
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
FernClassifier();
|
|
|
|
FernClassifier(const FileNode& node);
|
2010-07-26 16:58:46 +08:00
|
|
|
FernClassifier(const vector<vector<Point2f> >& points,
|
|
|
|
const vector<Mat>& refimgs,
|
|
|
|
const vector<vector<int> >& labels=vector<vector<int> >(),
|
2010-05-12 01:44:00 +08:00
|
|
|
int _nclasses=0, int _patchSize=PATCH_SIZE,
|
|
|
|
int _signatureSize=DEFAULT_SIGNATURE_SIZE,
|
|
|
|
int _nstructs=DEFAULT_STRUCTS,
|
|
|
|
int _structSize=DEFAULT_STRUCT_SIZE,
|
|
|
|
int _nviews=DEFAULT_VIEWS,
|
|
|
|
int _compressionMethod=COMPRESSION_NONE,
|
|
|
|
const PatchGenerator& patchGenerator=PatchGenerator());
|
|
|
|
virtual ~FernClassifier();
|
|
|
|
virtual void read(const FileNode& n);
|
|
|
|
virtual void write(FileStorage& fs, const String& name=String()) const;
|
|
|
|
virtual void trainFromSingleView(const Mat& image,
|
|
|
|
const vector<KeyPoint>& keypoints,
|
|
|
|
int _patchSize=PATCH_SIZE,
|
|
|
|
int _signatureSize=DEFAULT_SIGNATURE_SIZE,
|
|
|
|
int _nstructs=DEFAULT_STRUCTS,
|
|
|
|
int _structSize=DEFAULT_STRUCT_SIZE,
|
|
|
|
int _nviews=DEFAULT_VIEWS,
|
|
|
|
int _compressionMethod=COMPRESSION_NONE,
|
|
|
|
const PatchGenerator& patchGenerator=PatchGenerator());
|
2010-07-26 16:58:46 +08:00
|
|
|
virtual void train(const vector<vector<Point2f> >& points,
|
|
|
|
const vector<Mat>& refimgs,
|
|
|
|
const vector<vector<int> >& labels=vector<vector<int> >(),
|
2010-05-12 01:44:00 +08:00
|
|
|
int _nclasses=0, int _patchSize=PATCH_SIZE,
|
|
|
|
int _signatureSize=DEFAULT_SIGNATURE_SIZE,
|
|
|
|
int _nstructs=DEFAULT_STRUCTS,
|
|
|
|
int _structSize=DEFAULT_STRUCT_SIZE,
|
|
|
|
int _nviews=DEFAULT_VIEWS,
|
|
|
|
int _compressionMethod=COMPRESSION_NONE,
|
|
|
|
const PatchGenerator& patchGenerator=PatchGenerator());
|
|
|
|
virtual int operator()(const Mat& img, Point2f kpt, vector<float>& signature) const;
|
|
|
|
virtual int operator()(const Mat& patch, vector<float>& signature) const;
|
|
|
|
virtual void clear();
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const;
|
2010-05-12 01:44:00 +08:00
|
|
|
void setVerbose(bool verbose);
|
|
|
|
|
|
|
|
int getClassCount() const;
|
|
|
|
int getStructCount() const;
|
|
|
|
int getStructSize() const;
|
|
|
|
int getSignatureSize() const;
|
|
|
|
int getCompressionMethod() const;
|
|
|
|
Size getPatchSize() const;
|
|
|
|
|
|
|
|
struct Feature
|
|
|
|
{
|
|
|
|
uchar x1, y1, x2, y2;
|
|
|
|
Feature() : x1(0), y1(0), x2(0), y2(0) {}
|
|
|
|
Feature(int _x1, int _y1, int _x2, int _y2)
|
|
|
|
: x1((uchar)_x1), y1((uchar)_y1), x2((uchar)_x2), y2((uchar)_y2)
|
|
|
|
{}
|
|
|
|
template<typename _Tp> bool operator ()(const Mat_<_Tp>& patch) const
|
|
|
|
{ return patch(y1,x1) > patch(y2, x2); }
|
|
|
|
};
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
PATCH_SIZE = 31,
|
|
|
|
DEFAULT_STRUCTS = 50,
|
|
|
|
DEFAULT_STRUCT_SIZE = 9,
|
|
|
|
DEFAULT_VIEWS = 5000,
|
|
|
|
DEFAULT_SIGNATURE_SIZE = 176,
|
|
|
|
COMPRESSION_NONE = 0,
|
|
|
|
COMPRESSION_RANDOM_PROJ = 1,
|
|
|
|
COMPRESSION_PCA = 2,
|
|
|
|
DEFAULT_COMPRESSION_METHOD = COMPRESSION_NONE
|
|
|
|
};
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual void prepare(int _nclasses, int _patchSize, int _signatureSize,
|
|
|
|
int _nstructs, int _structSize,
|
|
|
|
int _nviews, int _compressionMethod);
|
|
|
|
virtual void finalize(RNG& rng);
|
|
|
|
virtual int getLeaf(int fidx, const Mat& patch) const;
|
|
|
|
|
|
|
|
bool verbose;
|
|
|
|
int nstructs;
|
|
|
|
int structSize;
|
|
|
|
int nclasses;
|
|
|
|
int signatureSize;
|
|
|
|
int compressionMethod;
|
|
|
|
int leavesPerStruct;
|
|
|
|
Size patchSize;
|
|
|
|
vector<Feature> features;
|
|
|
|
vector<int> classCounters;
|
|
|
|
vector<float> posteriors;
|
|
|
|
};
|
|
|
|
|
2010-10-17 04:34:34 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
/****************************************************************************************\
|
2010-07-26 16:58:46 +08:00
|
|
|
* Calonder Classifier *
|
2010-05-12 01:44:00 +08:00
|
|
|
\****************************************************************************************/
|
2010-07-27 20:36:48 +08:00
|
|
|
|
|
|
|
struct RTreeNode;
|
|
|
|
|
|
|
|
struct CV_EXPORTS BaseKeypoint
|
|
|
|
{
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
IplImage* image;
|
|
|
|
|
|
|
|
BaseKeypoint()
|
|
|
|
: x(0), y(0), image(NULL)
|
|
|
|
{}
|
|
|
|
|
|
|
|
BaseKeypoint(int x, int y, IplImage* image)
|
|
|
|
: x(x), y(y), image(image)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CV_EXPORTS RandomizedTree
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
friend class RTreeClassifier;
|
|
|
|
|
2010-07-27 21:28:21 +08:00
|
|
|
static const uchar PATCH_SIZE = 32;
|
2010-07-27 20:36:48 +08:00
|
|
|
static const int DEFAULT_DEPTH = 9;
|
|
|
|
static const int DEFAULT_VIEWS = 5000;
|
|
|
|
static const size_t DEFAULT_REDUCED_NUM_DIM = 176;
|
2010-07-27 21:28:21 +08:00
|
|
|
static float GET_LOWER_QUANT_PERC() { return .03f; }
|
|
|
|
static float GET_UPPER_QUANT_PERC() { return .92f; }
|
2010-07-27 20:36:48 +08:00
|
|
|
|
|
|
|
RandomizedTree();
|
|
|
|
~RandomizedTree();
|
|
|
|
|
|
|
|
void train(std::vector<BaseKeypoint> const& base_set, RNG &rng,
|
|
|
|
int depth, int views, size_t reduced_num_dim, int num_quant_bits);
|
|
|
|
void train(std::vector<BaseKeypoint> const& base_set, RNG &rng,
|
|
|
|
PatchGenerator &make_patch, int depth, int views, size_t reduced_num_dim,
|
|
|
|
int num_quant_bits);
|
|
|
|
|
|
|
|
// following two funcs are EXPERIMENTAL (do not use unless you know exactly what you do)
|
|
|
|
static void quantizeVector(float *vec, int dim, int N, float bnds[2], int clamp_mode=0);
|
2010-07-27 21:28:21 +08:00
|
|
|
static void quantizeVector(float *src, int dim, int N, float bnds[2], uchar *dst);
|
2010-07-27 20:36:48 +08:00
|
|
|
|
|
|
|
// patch_data must be a 32x32 array (no row padding)
|
|
|
|
float* getPosterior(uchar* patch_data);
|
|
|
|
const float* getPosterior(uchar* patch_data) const;
|
2010-07-27 21:28:21 +08:00
|
|
|
uchar* getPosterior2(uchar* patch_data);
|
|
|
|
const uchar* getPosterior2(uchar* patch_data) const;
|
2010-07-27 20:36:48 +08:00
|
|
|
|
|
|
|
void read(const char* file_name, int num_quant_bits);
|
|
|
|
void read(std::istream &is, int num_quant_bits);
|
|
|
|
void write(const char* file_name) const;
|
|
|
|
void write(std::ostream &os) const;
|
|
|
|
|
|
|
|
int classes() { return classes_; }
|
|
|
|
int depth() { return depth_; }
|
|
|
|
|
|
|
|
//void setKeepFloatPosteriors(bool b) { keep_float_posteriors_ = b; }
|
|
|
|
void discardFloatPosteriors() { freePosteriors(1); }
|
|
|
|
|
|
|
|
inline void applyQuantization(int num_quant_bits) { makePosteriors2(num_quant_bits); }
|
|
|
|
|
|
|
|
// debug
|
|
|
|
void savePosteriors(std::string url, bool append=false);
|
|
|
|
void savePosteriors2(std::string url, bool append=false);
|
|
|
|
|
|
|
|
private:
|
|
|
|
int classes_;
|
|
|
|
int depth_;
|
|
|
|
int num_leaves_;
|
|
|
|
std::vector<RTreeNode> nodes_;
|
|
|
|
float **posteriors_; // 16-bytes aligned posteriors
|
2010-07-27 21:28:21 +08:00
|
|
|
uchar **posteriors2_; // 16-bytes aligned posteriors
|
2010-07-27 20:36:48 +08:00
|
|
|
std::vector<int> leaf_counts_;
|
|
|
|
|
|
|
|
void createNodes(int num_nodes, RNG &rng);
|
|
|
|
void allocPosteriorsAligned(int num_leaves, int num_classes);
|
|
|
|
void freePosteriors(int which); // which: 1=posteriors_, 2=posteriors2_, 3=both
|
|
|
|
void init(int classes, int depth, RNG &rng);
|
|
|
|
void addExample(int class_id, uchar* patch_data);
|
|
|
|
void finalize(size_t reduced_num_dim, int num_quant_bits);
|
|
|
|
int getIndex(uchar* patch_data) const;
|
|
|
|
inline float* getPosteriorByIndex(int index);
|
|
|
|
inline const float* getPosteriorByIndex(int index) const;
|
2010-07-27 21:28:21 +08:00
|
|
|
inline uchar* getPosteriorByIndex2(int index);
|
|
|
|
inline const uchar* getPosteriorByIndex2(int index) const;
|
2010-07-27 20:36:48 +08:00
|
|
|
//void makeRandomMeasMatrix(float *cs_phi, PHI_DISTR_TYPE dt, size_t reduced_num_dim);
|
|
|
|
void convertPosteriorsToChar();
|
|
|
|
void makePosteriors2(int num_quant_bits);
|
|
|
|
void compressLeaves(size_t reduced_num_dim);
|
|
|
|
void estimateQuantPercForPosteriors(float perc[2]);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
inline uchar* getData(IplImage* image)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<uchar*>(image->imageData);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline float* RandomizedTree::getPosteriorByIndex(int index)
|
|
|
|
{
|
|
|
|
return const_cast<float*>(const_cast<const RandomizedTree*>(this)->getPosteriorByIndex(index));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const float* RandomizedTree::getPosteriorByIndex(int index) const
|
|
|
|
{
|
|
|
|
return posteriors_[index];
|
|
|
|
}
|
|
|
|
|
2010-07-27 21:28:21 +08:00
|
|
|
inline uchar* RandomizedTree::getPosteriorByIndex2(int index)
|
2010-07-27 20:36:48 +08:00
|
|
|
{
|
2010-07-27 21:28:21 +08:00
|
|
|
return const_cast<uchar*>(const_cast<const RandomizedTree*>(this)->getPosteriorByIndex2(index));
|
2010-07-27 20:36:48 +08:00
|
|
|
}
|
|
|
|
|
2010-07-27 21:28:21 +08:00
|
|
|
inline const uchar* RandomizedTree::getPosteriorByIndex2(int index) const
|
2010-07-27 20:36:48 +08:00
|
|
|
{
|
|
|
|
return posteriors2_[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CV_EXPORTS RTreeNode
|
|
|
|
{
|
|
|
|
short offset1, offset2;
|
|
|
|
|
|
|
|
RTreeNode() {}
|
|
|
|
RTreeNode(uchar x1, uchar y1, uchar x2, uchar y2)
|
|
|
|
: offset1(y1*RandomizedTree::PATCH_SIZE + x1),
|
|
|
|
offset2(y2*RandomizedTree::PATCH_SIZE + x2)
|
|
|
|
{}
|
|
|
|
|
|
|
|
//! Left child on 0, right child on 1
|
|
|
|
inline bool operator() (uchar* patch_data) const
|
|
|
|
{
|
|
|
|
return patch_data[offset1] > patch_data[offset2];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CV_EXPORTS RTreeClassifier
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const int DEFAULT_TREES = 48;
|
|
|
|
static const size_t DEFAULT_NUM_QUANT_BITS = 4;
|
|
|
|
|
|
|
|
RTreeClassifier();
|
|
|
|
void train(std::vector<BaseKeypoint> const& base_set,
|
|
|
|
RNG &rng,
|
|
|
|
int num_trees = RTreeClassifier::DEFAULT_TREES,
|
|
|
|
int depth = RandomizedTree::DEFAULT_DEPTH,
|
|
|
|
int views = RandomizedTree::DEFAULT_VIEWS,
|
|
|
|
size_t reduced_num_dim = RandomizedTree::DEFAULT_REDUCED_NUM_DIM,
|
|
|
|
int num_quant_bits = DEFAULT_NUM_QUANT_BITS);
|
|
|
|
void train(std::vector<BaseKeypoint> const& base_set,
|
|
|
|
RNG &rng,
|
|
|
|
PatchGenerator &make_patch,
|
|
|
|
int num_trees = RTreeClassifier::DEFAULT_TREES,
|
|
|
|
int depth = RandomizedTree::DEFAULT_DEPTH,
|
|
|
|
int views = RandomizedTree::DEFAULT_VIEWS,
|
|
|
|
size_t reduced_num_dim = RandomizedTree::DEFAULT_REDUCED_NUM_DIM,
|
|
|
|
int num_quant_bits = DEFAULT_NUM_QUANT_BITS);
|
|
|
|
|
2010-07-27 21:28:21 +08:00
|
|
|
// sig must point to a memory block of at least classes()*sizeof(float|uchar) bytes
|
|
|
|
void getSignature(IplImage *patch, uchar *sig) const;
|
2010-07-27 20:36:48 +08:00
|
|
|
void getSignature(IplImage *patch, float *sig) const;
|
|
|
|
void getSparseSignature(IplImage *patch, float *sig, float thresh) const;
|
|
|
|
// TODO: deprecated in favor of getSignature overload, remove
|
|
|
|
void getFloatSignature(IplImage *patch, float *sig) const { getSignature(patch, sig); }
|
|
|
|
|
|
|
|
static int countNonZeroElements(float *vec, int n, double tol=1e-10);
|
2010-07-27 21:28:21 +08:00
|
|
|
static inline void safeSignatureAlloc(uchar **sig, int num_sig=1, int sig_len=176);
|
|
|
|
static inline uchar* safeSignatureAlloc(int num_sig=1, int sig_len=176);
|
2010-07-27 20:36:48 +08:00
|
|
|
|
|
|
|
inline int classes() const { return classes_; }
|
|
|
|
inline int original_num_classes() const { return original_num_classes_; }
|
|
|
|
|
|
|
|
void setQuantization(int num_quant_bits);
|
|
|
|
void discardFloatPosteriors();
|
|
|
|
|
|
|
|
void read(const char* file_name);
|
|
|
|
void read(std::istream &is);
|
|
|
|
void write(const char* file_name) const;
|
|
|
|
void write(std::ostream &os) const;
|
|
|
|
|
|
|
|
// experimental and debug
|
|
|
|
void saveAllFloatPosteriors(std::string file_url);
|
|
|
|
void saveAllBytePosteriors(std::string file_url);
|
|
|
|
void setFloatPosteriorsFromTextfile_176(std::string url);
|
|
|
|
float countZeroElements();
|
|
|
|
|
|
|
|
std::vector<RandomizedTree> trees_;
|
|
|
|
|
|
|
|
private:
|
|
|
|
int classes_;
|
|
|
|
int num_quant_bits_;
|
2010-07-27 21:28:21 +08:00
|
|
|
mutable uchar **posteriors_;
|
|
|
|
mutable unsigned short *ptemp_;
|
2010-07-27 20:36:48 +08:00
|
|
|
int original_num_classes_;
|
|
|
|
bool keep_floats_;
|
|
|
|
};
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
/****************************************************************************************\
|
|
|
|
* One-Way Descriptor *
|
|
|
|
\****************************************************************************************/
|
|
|
|
|
|
|
|
class CV_EXPORTS OneWayDescriptor
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
OneWayDescriptor();
|
|
|
|
~OneWayDescriptor();
|
|
|
|
|
|
|
|
// allocates memory for given descriptor parameters
|
|
|
|
void Allocate(int pose_count, CvSize size, int nChannels);
|
|
|
|
|
|
|
|
// GenerateSamples: generates affine transformed patches with averaging them over small transformation variations.
|
|
|
|
// If external poses and transforms were specified, uses them instead of generating random ones
|
|
|
|
// - pose_count: the number of poses to be generated
|
|
|
|
// - frontal: the input patch (can be a roi in a larger image)
|
|
|
|
// - norm: if nonzero, normalizes the output patch so that the sum of pixel intensities is 1
|
|
|
|
void GenerateSamples(int pose_count, IplImage* frontal, int norm = 0);
|
|
|
|
|
|
|
|
// GenerateSamplesFast: generates affine transformed patches with averaging them over small transformation variations.
|
|
|
|
// Uses precalculated transformed pca components.
|
|
|
|
// - frontal: the input patch (can be a roi in a larger image)
|
|
|
|
// - pca_hr_avg: pca average vector
|
|
|
|
// - pca_hr_eigenvectors: pca eigenvectors
|
|
|
|
// - pca_descriptors: an array of precomputed descriptors of pca components containing their affine transformations
|
|
|
|
// pca_descriptors[0] corresponds to the average, pca_descriptors[1]-pca_descriptors[pca_dim] correspond to eigenvectors
|
|
|
|
void GenerateSamplesFast(IplImage* frontal, CvMat* pca_hr_avg,
|
|
|
|
CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors);
|
|
|
|
|
|
|
|
// sets the poses and corresponding transforms
|
|
|
|
void SetTransforms(CvAffinePose* poses, CvMat** transforms);
|
|
|
|
|
|
|
|
// Initialize: builds a descriptor.
|
|
|
|
// - pose_count: the number of poses to build. If poses were set externally, uses them rather than generating random ones
|
|
|
|
// - frontal: input patch. Can be a roi in a larger image
|
|
|
|
// - feature_name: the feature name to be associated with the descriptor
|
|
|
|
// - norm: if 1, the affine transformed patches are normalized so that their sum is 1
|
|
|
|
void Initialize(int pose_count, IplImage* frontal, const char* feature_name = 0, int norm = 0);
|
|
|
|
|
|
|
|
// InitializeFast: builds a descriptor using precomputed descriptors of pca components
|
|
|
|
// - pose_count: the number of poses to build
|
|
|
|
// - frontal: input patch. Can be a roi in a larger image
|
|
|
|
// - feature_name: the feature name to be associated with the descriptor
|
|
|
|
// - pca_hr_avg: average vector for PCA
|
|
|
|
// - pca_hr_eigenvectors: PCA eigenvectors (one vector per row)
|
|
|
|
// - pca_descriptors: precomputed descriptors of PCA components, the first descriptor for the average vector
|
|
|
|
// followed by the descriptors for eigenvectors
|
|
|
|
void InitializeFast(int pose_count, IplImage* frontal, const char* feature_name,
|
|
|
|
CvMat* pca_hr_avg, CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors);
|
|
|
|
|
|
|
|
// ProjectPCASample: unwarps an image patch into a vector and projects it into PCA space
|
|
|
|
// - patch: input image patch
|
|
|
|
// - avg: PCA average vector
|
|
|
|
// - eigenvectors: PCA eigenvectors, one per row
|
|
|
|
// - pca_coeffs: output PCA coefficients
|
|
|
|
void ProjectPCASample(IplImage* patch, CvMat* avg, CvMat* eigenvectors, CvMat* pca_coeffs) const;
|
|
|
|
|
|
|
|
// InitializePCACoeffs: projects all warped patches into PCA space
|
|
|
|
// - avg: PCA average vector
|
|
|
|
// - eigenvectors: PCA eigenvectors, one per row
|
|
|
|
void InitializePCACoeffs(CvMat* avg, CvMat* eigenvectors);
|
|
|
|
|
|
|
|
// EstimatePose: finds the closest match between an input patch and a set of patches with different poses
|
|
|
|
// - patch: input image patch
|
|
|
|
// - pose_idx: the output index of the closest pose
|
|
|
|
// - distance: the distance to the closest pose (L2 distance)
|
|
|
|
void EstimatePose(IplImage* patch, int& pose_idx, float& distance) const;
|
|
|
|
|
|
|
|
// EstimatePosePCA: finds the closest match between an input patch and a set of patches with different poses.
|
|
|
|
// The distance between patches is computed in PCA space
|
|
|
|
// - patch: input image patch
|
|
|
|
// - pose_idx: the output index of the closest pose
|
|
|
|
// - distance: distance to the closest pose (L2 distance in PCA space)
|
|
|
|
// - avg: PCA average vector. If 0, matching without PCA is used
|
|
|
|
// - eigenvectors: PCA eigenvectors, one per row
|
|
|
|
void EstimatePosePCA(CvArr* patch, int& pose_idx, float& distance, CvMat* avg, CvMat* eigenvalues) const;
|
|
|
|
|
|
|
|
// GetPatchSize: returns the size of each image patch after warping (2 times smaller than the input patch)
|
|
|
|
CvSize GetPatchSize() const
|
|
|
|
{
|
|
|
|
return m_patch_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetInputPatchSize: returns the required size of the patch that the descriptor is built from
|
|
|
|
// (2 time larger than the patch after warping)
|
|
|
|
CvSize GetInputPatchSize() const
|
|
|
|
{
|
|
|
|
return cvSize(m_patch_size.width*2, m_patch_size.height*2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPatch: returns a patch corresponding to specified pose index
|
|
|
|
// - index: pose index
|
|
|
|
// - return value: the patch corresponding to specified pose index
|
|
|
|
IplImage* GetPatch(int index);
|
|
|
|
|
|
|
|
// GetPose: returns a pose corresponding to specified pose index
|
|
|
|
// - index: pose index
|
|
|
|
// - return value: the pose corresponding to specified pose index
|
|
|
|
CvAffinePose GetPose(int index) const;
|
|
|
|
|
|
|
|
// Save: saves all patches with different poses to a specified path
|
|
|
|
void Save(const char* path);
|
|
|
|
|
|
|
|
// ReadByName: reads a descriptor from a file storage
|
|
|
|
// - fs: file storage
|
|
|
|
// - parent: parent node
|
|
|
|
// - name: node name
|
|
|
|
// - return value: 1 if succeeded, 0 otherwise
|
|
|
|
int ReadByName(CvFileStorage* fs, CvFileNode* parent, const char* name);
|
|
|
|
|
2010-06-04 13:30:09 +08:00
|
|
|
// ReadByName: reads a descriptor from a file node
|
|
|
|
// - parent: parent node
|
|
|
|
// - name: node name
|
|
|
|
// - return value: 1 if succeeded, 0 otherwise
|
|
|
|
int ReadByName(const FileNode &parent, const char* name);
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// Write: writes a descriptor into a file storage
|
|
|
|
// - fs: file storage
|
|
|
|
// - name: node name
|
|
|
|
void Write(CvFileStorage* fs, const char* name);
|
|
|
|
|
|
|
|
// GetFeatureName: returns a name corresponding to a feature
|
|
|
|
const char* GetFeatureName() const;
|
|
|
|
|
|
|
|
// GetCenter: returns the center of the feature
|
|
|
|
CvPoint GetCenter() const;
|
|
|
|
|
|
|
|
void SetPCADimHigh(int pca_dim_high) {m_pca_dim_high = pca_dim_high;};
|
|
|
|
void SetPCADimLow(int pca_dim_low) {m_pca_dim_low = pca_dim_low;};
|
|
|
|
|
|
|
|
int GetPCADimLow() const;
|
|
|
|
int GetPCADimHigh() const;
|
|
|
|
|
|
|
|
CvMat** GetPCACoeffs() const {return m_pca_coeffs;}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
int m_pose_count; // the number of poses
|
|
|
|
CvSize m_patch_size; // size of each image
|
|
|
|
IplImage** m_samples; // an array of length m_pose_count containing the patch in different poses
|
|
|
|
IplImage* m_input_patch;
|
|
|
|
IplImage* m_train_patch;
|
|
|
|
CvMat** m_pca_coeffs; // an array of length m_pose_count containing pca decomposition of the patch in different poses
|
|
|
|
CvAffinePose* m_affine_poses; // an array of poses
|
|
|
|
CvMat** m_transforms; // an array of affine transforms corresponding to poses
|
|
|
|
|
2010-07-26 16:58:46 +08:00
|
|
|
string m_feature_name; // the name of the feature associated with the descriptor
|
2010-05-12 01:44:00 +08:00
|
|
|
CvPoint m_center; // the coordinates of the feature (the center of the input image ROI)
|
|
|
|
|
|
|
|
int m_pca_dim_high; // the number of descriptor pca components to use for generating affine poses
|
|
|
|
int m_pca_dim_low; // the number of pca components to use for comparison
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// OneWayDescriptorBase: encapsulates functionality for training/loading a set of one way descriptors
|
|
|
|
// and finding the nearest closest descriptor to an input feature
|
|
|
|
class CV_EXPORTS OneWayDescriptorBase
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
// creates an instance of OneWayDescriptor from a set of training files
|
|
|
|
// - patch_size: size of the input (large) patch
|
|
|
|
// - pose_count: the number of poses to generate for each descriptor
|
|
|
|
// - train_path: path to training files
|
|
|
|
// - pca_config: the name of the file that contains PCA for small patches (2 times smaller
|
|
|
|
// than patch_size each dimension
|
|
|
|
// - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size)
|
|
|
|
// - pca_desc_config: the name of the file that contains descriptors of PCA components
|
|
|
|
OneWayDescriptorBase(CvSize patch_size, int pose_count, const char* train_path = 0, const char* pca_config = 0,
|
|
|
|
const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1,
|
|
|
|
int pca_dim_high = 100, int pca_dim_low = 100);
|
|
|
|
|
2010-06-02 13:19:09 +08:00
|
|
|
OneWayDescriptorBase(CvSize patch_size, int pose_count, const string &pca_filename, const string &train_path = string(), const string &images_list = string(),
|
2010-06-02 14:55:03 +08:00
|
|
|
float _scale_min = 0.7f, float _scale_max=1.5f, float _scale_step=1.2f, int pyr_levels = 1,
|
2010-06-02 13:19:09 +08:00
|
|
|
int pca_dim_high = 100, int pca_dim_low = 100);
|
|
|
|
|
|
|
|
|
2010-06-02 13:39:29 +08:00
|
|
|
virtual ~OneWayDescriptorBase();
|
2010-06-02 14:55:03 +08:00
|
|
|
void clear ();
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
// Allocate: allocates memory for a given number of descriptors
|
|
|
|
void Allocate(int train_feature_count);
|
|
|
|
|
|
|
|
// AllocatePCADescriptors: allocates memory for pca descriptors
|
|
|
|
void AllocatePCADescriptors();
|
|
|
|
|
|
|
|
// returns patch size
|
|
|
|
CvSize GetPatchSize() const {return m_patch_size;};
|
|
|
|
// returns the number of poses for each descriptor
|
|
|
|
int GetPoseCount() const {return m_pose_count;};
|
|
|
|
|
|
|
|
// returns the number of pyramid levels
|
|
|
|
int GetPyrLevels() const {return m_pyr_levels;};
|
|
|
|
|
|
|
|
// returns the number of descriptors
|
|
|
|
int GetDescriptorCount() const {return m_train_feature_count;};
|
|
|
|
|
|
|
|
// CreateDescriptorsFromImage: creates descriptors for each of the input features
|
|
|
|
// - src: input image
|
|
|
|
// - features: input features
|
|
|
|
// - pyr_levels: the number of pyramid levels
|
|
|
|
void CreateDescriptorsFromImage(IplImage* src, const std::vector<cv::KeyPoint>& features);
|
|
|
|
|
|
|
|
// CreatePCADescriptors: generates descriptors for PCA components, needed for fast generation of feature descriptors
|
|
|
|
void CreatePCADescriptors();
|
|
|
|
|
|
|
|
// returns a feature descriptor by feature index
|
|
|
|
const OneWayDescriptor* GetDescriptor(int desc_idx) const {return &m_descriptors[desc_idx];};
|
|
|
|
|
|
|
|
// FindDescriptor: finds the closest descriptor
|
|
|
|
// - patch: input image patch
|
|
|
|
// - desc_idx: output index of the closest descriptor to the input patch
|
|
|
|
// - pose_idx: output index of the closest pose of the closest descriptor to the input patch
|
|
|
|
// - distance: distance from the input patch to the closest feature pose
|
|
|
|
// - _scales: scales of the input patch for each descriptor
|
|
|
|
// - scale_ranges: input scales variation (float[2])
|
|
|
|
void FindDescriptor(IplImage* patch, int& desc_idx, int& pose_idx, float& distance, float* _scale = 0, float* scale_ranges = 0) const;
|
|
|
|
|
|
|
|
// - patch: input image patch
|
|
|
|
// - n: number of the closest indexes
|
|
|
|
// - desc_idxs: output indexes of the closest descriptor to the input patch (n)
|
|
|
|
// - pose_idx: output indexes of the closest pose of the closest descriptor to the input patch (n)
|
|
|
|
// - distances: distance from the input patch to the closest feature pose (n)
|
|
|
|
// - _scales: scales of the input patch
|
|
|
|
// - scale_ranges: input scales variation (float[2])
|
|
|
|
void FindDescriptor(IplImage* patch, int n, std::vector<int>& desc_idxs, std::vector<int>& pose_idxs,
|
|
|
|
std::vector<float>& distances, std::vector<float>& _scales, float* scale_ranges = 0) const;
|
|
|
|
|
|
|
|
// FindDescriptor: finds the closest descriptor
|
|
|
|
// - src: input image
|
|
|
|
// - pt: center of the feature
|
|
|
|
// - desc_idx: output index of the closest descriptor to the input patch
|
|
|
|
// - pose_idx: output index of the closest pose of the closest descriptor to the input patch
|
|
|
|
// - distance: distance from the input patch to the closest feature pose
|
|
|
|
void FindDescriptor(IplImage* src, cv::Point2f pt, int& desc_idx, int& pose_idx, float& distance) const;
|
|
|
|
|
|
|
|
// InitializePoses: generates random poses
|
|
|
|
void InitializePoses();
|
|
|
|
|
|
|
|
// InitializeTransformsFromPoses: generates 2x3 affine matrices from poses (initializes m_transforms)
|
|
|
|
void InitializeTransformsFromPoses();
|
|
|
|
|
|
|
|
// InitializePoseTransforms: subsequently calls InitializePoses and InitializeTransformsFromPoses
|
|
|
|
void InitializePoseTransforms();
|
|
|
|
|
|
|
|
// InitializeDescriptor: initializes a descriptor
|
|
|
|
// - desc_idx: descriptor index
|
|
|
|
// - train_image: image patch (ROI is supported)
|
|
|
|
// - feature_label: feature textual label
|
|
|
|
void InitializeDescriptor(int desc_idx, IplImage* train_image, const char* feature_label);
|
|
|
|
|
|
|
|
void InitializeDescriptor(int desc_idx, IplImage* train_image, const cv::KeyPoint& keypoint, const char* feature_label);
|
|
|
|
|
|
|
|
// InitializeDescriptors: load features from an image and create descriptors for each of them
|
|
|
|
void InitializeDescriptors(IplImage* train_image, const vector<cv::KeyPoint>& features,
|
|
|
|
const char* feature_label = "", int desc_start_idx = 0);
|
|
|
|
|
2010-06-08 14:56:35 +08:00
|
|
|
// Write: writes this object to a file storage
|
|
|
|
// - fs: output filestorage
|
|
|
|
void Write (FileStorage &fs) const;
|
|
|
|
|
|
|
|
// Read: reads OneWayDescriptorBase object from a file node
|
|
|
|
// - fn: input file node
|
|
|
|
void Read (const FileNode &fn);
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// LoadPCADescriptors: loads PCA descriptors from a file
|
|
|
|
// - filename: input filename
|
|
|
|
int LoadPCADescriptors(const char* filename);
|
|
|
|
|
2010-06-04 13:30:09 +08:00
|
|
|
// LoadPCADescriptors: loads PCA descriptors from a file node
|
|
|
|
// - fn: input file node
|
|
|
|
int LoadPCADescriptors(const FileNode &fn);
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// SavePCADescriptors: saves PCA descriptors to a file
|
|
|
|
// - filename: output filename
|
|
|
|
void SavePCADescriptors(const char* filename);
|
|
|
|
|
2010-06-02 13:19:09 +08:00
|
|
|
// SavePCADescriptors: saves PCA descriptors to a file storage
|
|
|
|
// - fs: output file storage
|
2010-06-04 13:30:09 +08:00
|
|
|
void SavePCADescriptors(CvFileStorage* fs) const;
|
2010-06-02 13:19:09 +08:00
|
|
|
|
|
|
|
// GeneratePCA: calculate and save PCA components and descriptors
|
|
|
|
// - img_path: path to training PCA images directory
|
|
|
|
// - images_list: filename with filenames of training PCA images
|
2010-06-02 14:55:03 +08:00
|
|
|
void GeneratePCA(const char* img_path, const char* images_list, int pose_count=500);
|
2010-06-02 13:19:09 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// SetPCAHigh: sets the high resolution pca matrices (copied to internal structures)
|
|
|
|
void SetPCAHigh(CvMat* avg, CvMat* eigenvectors);
|
|
|
|
|
|
|
|
// SetPCALow: sets the low resolution pca matrices (copied to internal structures)
|
|
|
|
void SetPCALow(CvMat* avg, CvMat* eigenvectors);
|
|
|
|
|
|
|
|
int GetLowPCA(CvMat** avg, CvMat** eigenvectors)
|
|
|
|
{
|
|
|
|
*avg = m_pca_avg;
|
|
|
|
*eigenvectors = m_pca_eigenvectors;
|
|
|
|
return m_pca_dim_low;
|
|
|
|
};
|
|
|
|
|
|
|
|
int GetPCADimLow() const {return m_pca_dim_low;};
|
|
|
|
int GetPCADimHigh() const {return m_pca_dim_high;};
|
|
|
|
|
|
|
|
void ConvertDescriptorsArrayToTree(); // Converting pca_descriptors array to KD tree
|
|
|
|
|
2010-06-02 13:19:09 +08:00
|
|
|
// GetPCAFilename: get default PCA filename
|
|
|
|
static string GetPCAFilename () { return "pca.yml"; }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const { return m_train_feature_count <= 0 ? true : false; }
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
protected:
|
|
|
|
CvSize m_patch_size; // patch size
|
|
|
|
int m_pose_count; // the number of poses for each descriptor
|
|
|
|
int m_train_feature_count; // the number of the training features
|
|
|
|
OneWayDescriptor* m_descriptors; // array of train feature descriptors
|
|
|
|
CvMat* m_pca_avg; // PCA average Vector for small patches
|
|
|
|
CvMat* m_pca_eigenvectors; // PCA eigenvectors for small patches
|
|
|
|
CvMat* m_pca_hr_avg; // PCA average Vector for large patches
|
|
|
|
CvMat* m_pca_hr_eigenvectors; // PCA eigenvectors for large patches
|
|
|
|
OneWayDescriptor* m_pca_descriptors; // an array of PCA descriptors
|
|
|
|
|
2010-05-27 03:50:20 +08:00
|
|
|
cv::flann::Index* m_pca_descriptors_tree;
|
2010-05-12 01:44:00 +08:00
|
|
|
CvMat* m_pca_descriptors_matrix;
|
|
|
|
|
|
|
|
CvAffinePose* m_poses; // array of poses
|
|
|
|
CvMat** m_transforms; // array of affine transformations corresponding to poses
|
|
|
|
|
|
|
|
int m_pca_dim_high;
|
|
|
|
int m_pca_dim_low;
|
|
|
|
|
|
|
|
int m_pyr_levels;
|
2010-06-08 14:56:35 +08:00
|
|
|
float scale_min;
|
|
|
|
float scale_max;
|
|
|
|
float scale_step;
|
|
|
|
|
|
|
|
// SavePCAall: saves PCA components and descriptors to a file storage
|
|
|
|
// - fs: output file storage
|
|
|
|
void SavePCAall (FileStorage &fs) const;
|
|
|
|
|
|
|
|
// LoadPCAall: loads PCA components and descriptors from a file node
|
|
|
|
// - fn: input file node
|
|
|
|
void LoadPCAall (const FileNode &fn);
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class CV_EXPORTS OneWayDescriptorObject : public OneWayDescriptorBase
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// creates an instance of OneWayDescriptorObject from a set of training files
|
|
|
|
// - patch_size: size of the input (large) patch
|
|
|
|
// - pose_count: the number of poses to generate for each descriptor
|
|
|
|
// - train_path: path to training files
|
|
|
|
// - pca_config: the name of the file that contains PCA for small patches (2 times smaller
|
|
|
|
// than patch_size each dimension
|
|
|
|
// - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size)
|
|
|
|
// - pca_desc_config: the name of the file that contains descriptors of PCA components
|
|
|
|
OneWayDescriptorObject(CvSize patch_size, int pose_count, const char* train_path, const char* pca_config,
|
|
|
|
const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1);
|
|
|
|
|
2010-06-02 13:19:09 +08:00
|
|
|
OneWayDescriptorObject(CvSize patch_size, int pose_count, const string &pca_filename,
|
2010-06-02 14:55:03 +08:00
|
|
|
const string &train_path = string (), const string &images_list = string (),
|
|
|
|
float _scale_min = 0.7f, float _scale_max=1.5f, float _scale_step=1.2f, int pyr_levels = 1);
|
2010-06-02 13:19:09 +08:00
|
|
|
|
|
|
|
|
2010-06-02 13:39:29 +08:00
|
|
|
virtual ~OneWayDescriptorObject();
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
// Allocate: allocates memory for a given number of features
|
|
|
|
// - train_feature_count: the total number of features
|
|
|
|
// - object_feature_count: the number of features extracted from the object
|
|
|
|
void Allocate(int train_feature_count, int object_feature_count);
|
|
|
|
|
|
|
|
|
|
|
|
void SetLabeledFeatures(const vector<cv::KeyPoint>& features) {m_train_features = features;};
|
|
|
|
vector<cv::KeyPoint>& GetLabeledFeatures() {return m_train_features;};
|
|
|
|
const vector<cv::KeyPoint>& GetLabeledFeatures() const {return m_train_features;};
|
|
|
|
vector<cv::KeyPoint> _GetLabeledFeatures() const;
|
|
|
|
|
|
|
|
// IsDescriptorObject: returns 1 if descriptor with specified index is positive, otherwise 0
|
|
|
|
int IsDescriptorObject(int desc_idx) const;
|
|
|
|
|
|
|
|
// MatchPointToPart: returns the part number of a feature if it matches one of the object parts, otherwise -1
|
|
|
|
int MatchPointToPart(CvPoint pt) const;
|
|
|
|
|
|
|
|
// GetDescriptorPart: returns the part number of the feature corresponding to a specified descriptor
|
|
|
|
// - desc_idx: descriptor index
|
|
|
|
int GetDescriptorPart(int desc_idx) const;
|
|
|
|
|
|
|
|
|
|
|
|
void InitializeObjectDescriptors(IplImage* train_image, const vector<cv::KeyPoint>& features,
|
|
|
|
const char* feature_label, int desc_start_idx = 0, float scale = 1.0f,
|
|
|
|
int is_background = 0);
|
|
|
|
|
|
|
|
// GetObjectFeatureCount: returns the number of object features
|
|
|
|
int GetObjectFeatureCount() const {return m_object_feature_count;};
|
|
|
|
|
|
|
|
protected:
|
|
|
|
int* m_part_id; // contains part id for each of object descriptors
|
|
|
|
vector<cv::KeyPoint> m_train_features; // train features
|
|
|
|
int m_object_feature_count; // the number of the positive features
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************************\
|
|
|
|
* FeatureDetector *
|
|
|
|
\****************************************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Abstract base class for 2D image feature detectors.
|
|
|
|
*/
|
|
|
|
class CV_EXPORTS FeatureDetector
|
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual ~FeatureDetector();
|
2010-07-09 05:15:09 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
/*
|
2010-11-23 02:27:08 +08:00
|
|
|
* Detect keypoints in an image.
|
2010-05-12 01:44:00 +08:00
|
|
|
* image The image.
|
|
|
|
* keypoints The detected keypoints.
|
2010-07-26 16:58:46 +08:00
|
|
|
* mask Mask specifying where to look for keypoints (optional). Must be a char
|
|
|
|
* matrix with non-zero values in the region of interest.
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
2010-11-23 02:27:08 +08:00
|
|
|
void detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
2010-07-09 05:15:09 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
/*
|
|
|
|
* Detect keypoints in an image set.
|
2010-11-23 02:27:08 +08:00
|
|
|
* images Image collection.
|
|
|
|
* keypoints Collection of keypoints detected in an input images. keypoints[i] is a set of keypoints detected in an images[i].
|
|
|
|
* masks Masks for image set. masks[i] is a mask for images[i].
|
2010-10-29 16:44:42 +08:00
|
|
|
*/
|
2010-11-23 02:27:08 +08:00
|
|
|
void detect( const vector<Mat>& images, vector<vector<KeyPoint> >& keypoints, const vector<Mat>& masks=vector<Mat>() ) const;
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-25 23:59:37 +08:00
|
|
|
// Read detector object from a file node.
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void read( const FileNode& );
|
2010-11-25 23:59:37 +08:00
|
|
|
// Read detector object from a file node.
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void write( FileStorage& ) const;
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2011-01-31 22:18:50 +08:00
|
|
|
// Return true if detector object is empty
|
|
|
|
virtual bool empty() const;
|
|
|
|
|
2010-11-25 23:59:37 +08:00
|
|
|
// Create feature detector by detector name.
|
|
|
|
static Ptr<FeatureDetector> create( const string& detectorType );
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
protected:
|
2011-05-05 18:10:46 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const = 0;
|
2011-05-11 20:59:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove keypoints that are not in the mask.
|
|
|
|
* Helper function, useful when wrapping a library call for keypoint detection that
|
|
|
|
* does not support a mask argument.
|
|
|
|
*/
|
|
|
|
static void removeInvalidPoints( const Mat& mask, vector<KeyPoint>& keypoints );
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class CV_EXPORTS FastFeatureDetector : public FeatureDetector
|
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
FastFeatureDetector( int threshold=10, bool nonmaxSuppression=true );
|
2010-11-03 18:00:24 +08:00
|
|
|
virtual void read( const FileNode& fn );
|
|
|
|
virtual void write( FileStorage& fs ) const;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
protected:
|
2011-05-11 20:59:36 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
int threshold;
|
|
|
|
bool nonmaxSuppression;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class CV_EXPORTS GoodFeaturesToTrackDetector : public FeatureDetector
|
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
class CV_EXPORTS Params
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Params( int maxCorners=1000, double qualityLevel=0.01, double minDistance=1.,
|
|
|
|
int blockSize=3, bool useHarrisDetector=false, double k=0.04 );
|
|
|
|
void read( const FileNode& fn );
|
|
|
|
void write( FileStorage& fs ) const;
|
|
|
|
|
|
|
|
int maxCorners;
|
|
|
|
double qualityLevel;
|
|
|
|
double minDistance;
|
|
|
|
int blockSize;
|
|
|
|
bool useHarrisDetector;
|
|
|
|
double k;
|
|
|
|
};
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
GoodFeaturesToTrackDetector( const GoodFeaturesToTrackDetector::Params& params=GoodFeaturesToTrackDetector::Params() );
|
|
|
|
GoodFeaturesToTrackDetector( int maxCorners, double qualityLevel, double minDistance,
|
|
|
|
int blockSize=3, bool useHarrisDetector=false, double k=0.04 );
|
2010-11-03 18:00:24 +08:00
|
|
|
virtual void read( const FileNode& fn );
|
|
|
|
virtual void write( FileStorage& fs ) const;
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
protected:
|
2011-05-11 20:59:36 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
|
|
|
|
|
|
|
Params params;
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class CV_EXPORTS MserFeatureDetector : public FeatureDetector
|
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
MserFeatureDetector( CvMSERParams params=cvMSERParams() );
|
2010-07-16 20:54:53 +08:00
|
|
|
MserFeatureDetector( int delta, int minArea, int maxArea, double maxVariation, double minDiversity,
|
2010-05-12 01:44:00 +08:00
|
|
|
int maxEvolution, double areaThreshold, double minMargin, int edgeBlurSize );
|
2010-11-03 18:00:24 +08:00
|
|
|
virtual void read( const FileNode& fn );
|
|
|
|
virtual void write( FileStorage& fs ) const;
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
protected:
|
2011-05-11 20:59:36 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
MSER mser;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CV_EXPORTS StarFeatureDetector : public FeatureDetector
|
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
StarFeatureDetector( const CvStarDetectorParams& params=cvStarDetectorParams() );
|
|
|
|
StarFeatureDetector( int maxSize, int responseThreshold=30, int lineThresholdProjected = 10,
|
2010-05-12 01:44:00 +08:00
|
|
|
int lineThresholdBinarized=8, int suppressNonmaxSize=5 );
|
2010-11-03 18:00:24 +08:00
|
|
|
virtual void read( const FileNode& fn );
|
|
|
|
virtual void write( FileStorage& fs ) const;
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
protected:
|
2011-05-11 20:59:36 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
StarDetector star;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CV_EXPORTS SiftFeatureDetector : public FeatureDetector
|
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
SiftFeatureDetector( const SIFT::DetectorParams& detectorParams=SIFT::DetectorParams(),
|
|
|
|
const SIFT::CommonParams& commonParams=SIFT::CommonParams() );
|
|
|
|
SiftFeatureDetector( double threshold, double edgeThreshold,
|
2010-05-12 01:44:00 +08:00
|
|
|
int nOctaves=SIFT::CommonParams::DEFAULT_NOCTAVES,
|
|
|
|
int nOctaveLayers=SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS,
|
2010-05-20 00:02:30 +08:00
|
|
|
int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
|
|
|
|
int angleMode=SIFT::CommonParams::FIRST_ANGLE );
|
2010-11-03 18:00:24 +08:00
|
|
|
virtual void read( const FileNode& fn );
|
|
|
|
virtual void write( FileStorage& fs ) const;
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
protected:
|
2011-05-11 20:59:36 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
SIFT sift;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CV_EXPORTS SurfFeatureDetector : public FeatureDetector
|
|
|
|
{
|
|
|
|
public:
|
2011-06-08 17:23:33 +08:00
|
|
|
SurfFeatureDetector( double hessianThreshold=400., int octaves=3, int octaveLayers=4, bool upright=false );
|
2010-11-03 18:00:24 +08:00
|
|
|
virtual void read( const FileNode& fn );
|
|
|
|
virtual void write( FileStorage& fs ) const;
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
protected:
|
2011-05-11 20:59:36 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
SURF surf;
|
|
|
|
};
|
|
|
|
|
2011-05-21 06:25:53 +08:00
|
|
|
/** Feature detector for the ORB feature
|
|
|
|
* Basically fast followed by a Harris check
|
|
|
|
*/
|
|
|
|
class CV_EXPORTS OrbFeatureDetector : public cv::FeatureDetector
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Default constructor
|
|
|
|
* @param n_features the number of desired features
|
|
|
|
* @param params parameters to use
|
|
|
|
*/
|
|
|
|
OrbFeatureDetector(size_t n_features = 700, ORB::CommonParams params = ORB::CommonParams());
|
|
|
|
|
|
|
|
virtual void read(const cv::FileNode&);
|
|
|
|
virtual void write(cv::FileStorage&) const;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual void
|
|
|
|
detectImpl(const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask = cv::Mat()) const;
|
|
|
|
private:
|
|
|
|
/** the ORB object we use for the computations */
|
|
|
|
mutable ORB orb_;
|
|
|
|
/** The parameters used */
|
|
|
|
ORB::CommonParams params_;
|
|
|
|
/** the number of features that need to be retrieved */
|
|
|
|
unsigned int n_features_;
|
|
|
|
};
|
|
|
|
|
2010-12-27 17:15:08 +08:00
|
|
|
class CV_EXPORTS SimpleBlobDetector : public cv::FeatureDetector
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct CV_EXPORTS Params
|
|
|
|
{
|
|
|
|
Params();
|
|
|
|
float thresholdStep;
|
|
|
|
float minThreshold;
|
|
|
|
float maxThreshold;
|
|
|
|
size_t minRepeatability;
|
2011-06-09 19:07:08 +08:00
|
|
|
float minDistBetweenBlobs;
|
|
|
|
|
|
|
|
bool filterByColor;
|
2010-12-27 17:15:08 +08:00
|
|
|
uchar blobColor;
|
2011-06-09 19:07:08 +08:00
|
|
|
|
|
|
|
bool filterByArea;
|
|
|
|
float minArea, maxArea;
|
|
|
|
|
|
|
|
bool filterByCircularity;
|
|
|
|
float minCircularity, maxCircularity;
|
|
|
|
|
|
|
|
bool filterByInertia;
|
|
|
|
float minInertiaRatio, maxInertiaRatio;
|
|
|
|
|
|
|
|
bool filterByConvexity;
|
|
|
|
float minConvexity, maxConvexity;
|
2010-12-27 17:15:08 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
SimpleBlobDetector(const SimpleBlobDetector::Params ¶meters = SimpleBlobDetector::Params());
|
2011-01-31 22:18:50 +08:00
|
|
|
|
2010-12-27 17:15:08 +08:00
|
|
|
protected:
|
|
|
|
struct CV_EXPORTS Center
|
|
|
|
{
|
2011-01-31 22:18:50 +08:00
|
|
|
Point2d location;
|
|
|
|
double radius;
|
|
|
|
double confidence;
|
2010-12-27 17:15:08 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
|
|
|
virtual void findBlobs(const cv::Mat &image, const cv::Mat &binaryImage, std::vector<Center> ¢ers) const;
|
|
|
|
|
|
|
|
Params params;
|
|
|
|
};
|
|
|
|
|
2010-09-30 22:21:22 +08:00
|
|
|
class CV_EXPORTS DenseFeatureDetector : public FeatureDetector
|
2010-09-25 00:55:12 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
class CV_EXPORTS Params
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Params( float initFeatureScale=1.f, int featureScaleLevels=1, float featureScaleMul=0.1f,
|
|
|
|
int initXyStep=6, int initImgBound=0, bool varyXyStepWithScale=true, bool varyImgBoundWithScale=false );
|
|
|
|
float initFeatureScale;
|
|
|
|
int featureScaleLevels;
|
|
|
|
float featureScaleMul;
|
|
|
|
|
|
|
|
int initXyStep;
|
|
|
|
int initImgBound;
|
|
|
|
|
|
|
|
bool varyXyStepWithScale;
|
|
|
|
bool varyImgBoundWithScale;
|
|
|
|
};
|
|
|
|
|
|
|
|
DenseFeatureDetector( const DenseFeatureDetector::Params& params=DenseFeatureDetector::Params() );
|
|
|
|
|
|
|
|
// TODO implement read/write
|
2010-09-25 00:55:12 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
protected:
|
2011-05-11 20:59:36 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
2010-09-25 00:55:12 +08:00
|
|
|
|
2011-05-11 20:59:36 +08:00
|
|
|
Params params;
|
2010-09-25 00:55:12 +08:00
|
|
|
};
|
|
|
|
|
2010-08-04 00:28:52 +08:00
|
|
|
/*
|
|
|
|
* Adapts a detector to partition the source image into a grid and detect
|
|
|
|
* points in each cell.
|
|
|
|
*/
|
|
|
|
class CV_EXPORTS GridAdaptedFeatureDetector : public FeatureDetector
|
|
|
|
{
|
|
|
|
public:
|
2010-11-03 18:00:24 +08:00
|
|
|
/*
|
|
|
|
* detector Detector that will be adapted.
|
|
|
|
* maxTotalKeypoints Maximum count of keypoints detected on the image. Only the strongest keypoints
|
|
|
|
* will be keeped.
|
|
|
|
* gridRows Grid rows count.
|
|
|
|
* gridCols Grid column count.
|
|
|
|
*/
|
2010-11-25 23:59:37 +08:00
|
|
|
GridAdaptedFeatureDetector( const Ptr<FeatureDetector>& detector, int maxTotalKeypoints=1000,
|
2010-11-03 18:00:24 +08:00
|
|
|
int gridRows=4, int gridCols=4 );
|
2010-11-23 02:27:08 +08:00
|
|
|
|
|
|
|
// TODO implement read/write
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const;
|
2010-08-04 00:28:52 +08:00
|
|
|
|
|
|
|
protected:
|
2011-05-11 20:59:36 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
|
2010-08-04 00:28:52 +08:00
|
|
|
Ptr<FeatureDetector> detector;
|
|
|
|
int maxTotalKeypoints;
|
|
|
|
int gridRows;
|
|
|
|
int gridCols;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adapts a detector to detect points over multiple levels of a Gaussian
|
|
|
|
* pyramid. Useful for detectors that are not inherently scaled.
|
|
|
|
*/
|
2010-11-12 16:20:51 +08:00
|
|
|
class CV_EXPORTS PyramidAdaptedFeatureDetector : public FeatureDetector
|
2010-08-04 00:28:52 +08:00
|
|
|
{
|
|
|
|
public:
|
2011-05-15 17:19:05 +08:00
|
|
|
// maxLevel - The 0-based index of the last pyramid layer
|
|
|
|
PyramidAdaptedFeatureDetector( const Ptr<FeatureDetector>& detector, int maxLevel=2 );
|
2010-11-23 02:27:08 +08:00
|
|
|
|
|
|
|
// TODO implement read/write
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const;
|
2010-08-04 00:28:52 +08:00
|
|
|
|
|
|
|
protected:
|
2011-05-11 20:59:36 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
|
2010-08-04 00:28:52 +08:00
|
|
|
Ptr<FeatureDetector> detector;
|
2011-05-15 17:19:05 +08:00
|
|
|
int maxLevel;
|
2010-08-04 00:28:52 +08:00
|
|
|
};
|
|
|
|
|
2010-11-25 23:59:37 +08:00
|
|
|
/** \brief A feature detector parameter adjuster, this is used by the DynamicAdaptedFeatureDetector
|
2010-11-24 06:26:36 +08:00
|
|
|
* and is a wrapper for FeatureDetector that allow them to be adjusted after a detection
|
|
|
|
*/
|
2010-11-25 23:59:37 +08:00
|
|
|
class CV_EXPORTS AdjusterAdapter: public FeatureDetector
|
|
|
|
{
|
|
|
|
public:
|
2010-11-24 06:26:36 +08:00
|
|
|
/** pure virtual interface
|
|
|
|
*/
|
2010-11-25 23:59:37 +08:00
|
|
|
virtual ~AdjusterAdapter() {}
|
2011-05-11 19:53:53 +08:00
|
|
|
/** too few features were detected so, adjust the detector params accordingly
|
|
|
|
* \param min the minimum number of desired features
|
|
|
|
* \param n_detected the number previously detected
|
|
|
|
*/
|
|
|
|
virtual void tooFew(int min, int n_detected) = 0;
|
|
|
|
/** too many features were detected so, adjust the detector params accordingly
|
|
|
|
* \param max the maximum number of desired features
|
|
|
|
* \param n_detected the number previously detected
|
|
|
|
*/
|
|
|
|
virtual void tooMany(int max, int n_detected) = 0;
|
|
|
|
/** are params maxed out or still valid?
|
|
|
|
* \return false if the parameters can't be adjusted any more
|
|
|
|
*/
|
|
|
|
virtual bool good() const = 0;
|
|
|
|
|
|
|
|
virtual Ptr<AdjusterAdapter> clone() const = 0;
|
2010-11-25 23:59:37 +08:00
|
|
|
|
|
|
|
static Ptr<AdjusterAdapter> create( const string& detectorType );
|
2010-11-24 06:26:36 +08:00
|
|
|
};
|
2010-11-23 07:59:25 +08:00
|
|
|
/** \brief an adaptively adjusting detector that iteratively detects until the desired number
|
|
|
|
* of features are detected.
|
|
|
|
* Beware that this is not thread safe - as the adjustment of parameters breaks the const
|
|
|
|
* of the detection routine...
|
|
|
|
* /TODO Make this const correct and thread safe
|
2010-11-24 06:45:49 +08:00
|
|
|
*
|
|
|
|
* sample usage:
|
|
|
|
//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
|
2010-11-25 23:59:37 +08:00
|
|
|
Ptr<FeatureDetector> detector(new DynamicAdaptedFeatureDetector(new FastAdjuster(20,true),100, 110, 10));
|
2010-11-24 06:45:49 +08:00
|
|
|
|
2010-11-23 07:59:25 +08:00
|
|
|
*/
|
2010-11-25 23:59:37 +08:00
|
|
|
class CV_EXPORTS DynamicAdaptedFeatureDetector: public FeatureDetector
|
|
|
|
{
|
2010-11-23 07:59:25 +08:00
|
|
|
public:
|
|
|
|
|
2010-11-25 23:59:37 +08:00
|
|
|
/** \param adjaster an AdjusterAdapter that will do the detection and parameter adjustment
|
2011-05-11 19:53:53 +08:00
|
|
|
* \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
|
|
|
|
* for the FastAdjuster this can be high, but with Star or Surf this can get time consuming
|
|
|
|
* \param min_features the minimum desired features
|
|
|
|
*/
|
2010-11-25 23:59:37 +08:00
|
|
|
DynamicAdaptedFeatureDetector( const Ptr<AdjusterAdapter>& adjaster, int min_features=400, int max_features=500, int max_iters=5 );
|
|
|
|
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const;
|
|
|
|
|
2010-11-23 07:59:25 +08:00
|
|
|
protected:
|
2010-11-25 23:59:37 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
|
|
|
|
2010-11-23 07:59:25 +08:00
|
|
|
private:
|
2011-05-11 21:37:20 +08:00
|
|
|
DynamicAdaptedFeatureDetector& operator=(const DynamicAdaptedFeatureDetector&);
|
|
|
|
DynamicAdaptedFeatureDetector(const DynamicAdaptedFeatureDetector&);
|
|
|
|
|
2011-05-11 19:53:53 +08:00
|
|
|
int escape_iters_;
|
|
|
|
int min_features_, max_features_;
|
|
|
|
const Ptr<AdjusterAdapter> adjuster_;
|
2010-11-23 07:59:25 +08:00
|
|
|
};
|
|
|
|
|
2010-11-24 06:45:49 +08:00
|
|
|
/**\brief an adjust for the FAST detector. This will basically decrement or increment the
|
2011-05-11 19:53:53 +08:00
|
|
|
* threshold by 1
|
2010-11-24 06:45:49 +08:00
|
|
|
*/
|
2010-11-25 23:59:37 +08:00
|
|
|
class CV_EXPORTS FastAdjuster: public AdjusterAdapter
|
|
|
|
{
|
2010-11-24 06:26:36 +08:00
|
|
|
public:
|
2011-05-11 19:53:53 +08:00
|
|
|
/**\param init_thresh the initial threshold to start with, default = 20
|
|
|
|
* \param nonmax whether to use non max or not for fast feature detection
|
|
|
|
*/
|
2011-05-11 20:13:58 +08:00
|
|
|
FastAdjuster(int init_thresh=20, bool nonmax=true, int min_thresh=1, int max_thresh=200);
|
2011-05-11 19:53:53 +08:00
|
|
|
|
|
|
|
virtual void tooFew(int min, int n_detected);
|
|
|
|
virtual void tooMany(int max, int n_detected);
|
|
|
|
virtual bool good() const;
|
|
|
|
|
|
|
|
virtual Ptr<AdjusterAdapter> clone() const;
|
2010-11-25 23:59:37 +08:00
|
|
|
|
2010-11-24 06:26:36 +08:00
|
|
|
protected:
|
2010-11-25 23:59:37 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
|
|
|
|
2011-05-11 19:53:53 +08:00
|
|
|
int thresh_;
|
|
|
|
bool nonmax_;
|
2011-05-11 20:13:58 +08:00
|
|
|
int init_thresh_, min_thresh_, max_thresh_;
|
2010-11-24 06:26:36 +08:00
|
|
|
};
|
2010-11-23 07:59:25 +08:00
|
|
|
|
2010-11-24 06:45:49 +08:00
|
|
|
|
|
|
|
/** An adjuster for StarFeatureDetector, this one adjusts the responseThreshold for now
|
|
|
|
* TODO find a faster way to converge the parameters for Star - use CvStarDetectorParams
|
|
|
|
*/
|
2010-11-25 23:59:37 +08:00
|
|
|
class CV_EXPORTS StarAdjuster: public AdjusterAdapter
|
|
|
|
{
|
|
|
|
public:
|
2011-05-11 20:13:58 +08:00
|
|
|
StarAdjuster(double initial_thresh=30.0, double min_thresh=2., double max_thresh=200.);
|
2011-05-11 19:53:53 +08:00
|
|
|
|
|
|
|
virtual void tooFew(int min, int n_detected);
|
|
|
|
virtual void tooMany(int max, int n_detected);
|
|
|
|
virtual bool good() const;
|
|
|
|
|
|
|
|
virtual Ptr<AdjusterAdapter> clone() const;
|
2010-11-25 23:59:37 +08:00
|
|
|
|
2010-11-24 06:26:36 +08:00
|
|
|
protected:
|
2010-11-25 23:59:37 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
|
|
|
|
2011-05-11 20:13:58 +08:00
|
|
|
double thresh_, init_thresh_, min_thresh_, max_thresh_;
|
2011-05-11 19:53:53 +08:00
|
|
|
CvStarDetectorParams params_; //todo use these instead of thresh_
|
2010-11-23 07:59:25 +08:00
|
|
|
};
|
|
|
|
|
2010-11-25 23:59:37 +08:00
|
|
|
class CV_EXPORTS SurfAdjuster: public AdjusterAdapter
|
|
|
|
{
|
|
|
|
public:
|
2011-05-11 20:13:58 +08:00
|
|
|
SurfAdjuster( double initial_thresh=400.f, double min_thresh=2, double max_thresh=1000 );
|
2011-05-11 19:53:53 +08:00
|
|
|
|
|
|
|
virtual void tooFew(int min, int n_detected);
|
|
|
|
virtual void tooMany(int max, int n_detected);
|
|
|
|
virtual bool good() const;
|
|
|
|
|
|
|
|
virtual Ptr<AdjusterAdapter> clone() const;
|
2010-11-25 23:59:37 +08:00
|
|
|
|
2010-11-24 06:26:36 +08:00
|
|
|
protected:
|
2010-11-25 23:59:37 +08:00
|
|
|
virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
|
|
|
|
|
2011-05-11 20:13:58 +08:00
|
|
|
double thresh_, init_thresh_, min_thresh_, max_thresh_;
|
2010-11-23 07:59:25 +08:00
|
|
|
};
|
|
|
|
|
2010-08-05 20:19:26 +08:00
|
|
|
CV_EXPORTS Mat windowedMatchingMask( const vector<KeyPoint>& keypoints1, const vector<KeyPoint>& keypoints2,
|
|
|
|
float maxDeltaX, float maxDeltaY );
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
/****************************************************************************************\
|
|
|
|
* DescriptorExtractor *
|
|
|
|
\****************************************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Abstract base class for computing descriptors for image keypoints.
|
|
|
|
*
|
|
|
|
* 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 cv::Mat, where each row is one keypoint descriptor.
|
|
|
|
*/
|
|
|
|
class CV_EXPORTS DescriptorExtractor
|
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual ~DescriptorExtractor();
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
/*
|
|
|
|
* Compute the descriptors for a set of keypoints in an image.
|
|
|
|
* image The image.
|
2010-11-23 02:27:08 +08:00
|
|
|
* keypoints The input keypoints. Keypoints for which a descriptor cannot be computed are removed.
|
|
|
|
* descriptors Copmputed descriptors. Row i is the descriptor for keypoint i.
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
2010-11-23 02:27:08 +08:00
|
|
|
void compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
/*
|
|
|
|
* Compute the descriptors for a keypoints collection detected in image collection.
|
2010-11-23 02:27:08 +08:00
|
|
|
* images Image collection.
|
|
|
|
* keypoints Input keypoints collection. keypoints[i] is keypoints detected in images[i].
|
|
|
|
* Keypoints for which a descriptor cannot be computed are removed.
|
2010-11-24 01:00:55 +08:00
|
|
|
* descriptors Descriptor collection. descriptors[i] are descriptors computed for set keypoints[i].
|
2010-10-29 16:44:42 +08:00
|
|
|
*/
|
2010-11-23 02:27:08 +08:00
|
|
|
void compute( const vector<Mat>& images, vector<vector<KeyPoint> >& keypoints, vector<Mat>& descriptors ) const;
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void read( const FileNode& );
|
|
|
|
virtual void write( FileStorage& ) const;
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2010-09-23 18:53:36 +08:00
|
|
|
virtual int descriptorSize() const = 0;
|
|
|
|
virtual int descriptorType() const = 0;
|
|
|
|
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const;
|
|
|
|
|
2010-11-25 23:59:37 +08:00
|
|
|
static Ptr<DescriptorExtractor> create( const string& descriptorExtractorType );
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
protected:
|
2011-05-02 01:38:52 +08:00
|
|
|
virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const = 0;
|
2011-05-11 20:59:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove keypoints within borderPixels of an image edge.
|
|
|
|
*/
|
|
|
|
static void removeBorderKeypoints( vector<KeyPoint>& keypoints,
|
|
|
|
Size imageSize, int borderSize );
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
2010-11-15 18:24:38 +08:00
|
|
|
/*
|
|
|
|
* SiftDescriptorExtractor
|
|
|
|
*/
|
2010-05-12 01:44:00 +08:00
|
|
|
class CV_EXPORTS SiftDescriptorExtractor : public DescriptorExtractor
|
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
SiftDescriptorExtractor( const SIFT::DescriptorParams& descriptorParams=SIFT::DescriptorParams(),
|
|
|
|
const SIFT::CommonParams& commonParams=SIFT::CommonParams() );
|
|
|
|
SiftDescriptorExtractor( double magnification, bool isNormalize=true, bool recalculateAngles=true,
|
2010-05-12 01:44:00 +08:00
|
|
|
int nOctaves=SIFT::CommonParams::DEFAULT_NOCTAVES,
|
|
|
|
int nOctaveLayers=SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS,
|
2010-05-20 00:02:30 +08:00
|
|
|
int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
|
|
|
|
int angleMode=SIFT::CommonParams::FIRST_ANGLE );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-07-26 16:58:46 +08:00
|
|
|
virtual void read( const FileNode &fn );
|
|
|
|
virtual void write( FileStorage &fs ) const;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual int descriptorSize() const;
|
|
|
|
virtual int descriptorType() const;
|
2010-09-23 18:53:36 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
protected:
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
SIFT sift;
|
|
|
|
};
|
|
|
|
|
2010-11-15 18:24:38 +08:00
|
|
|
/*
|
|
|
|
* SurfDescriptorExtractor
|
|
|
|
*/
|
2010-05-12 01:44:00 +08:00
|
|
|
class CV_EXPORTS SurfDescriptorExtractor : public DescriptorExtractor
|
|
|
|
{
|
|
|
|
public:
|
2011-06-08 17:23:33 +08:00
|
|
|
SurfDescriptorExtractor( int nOctaves=4, int nOctaveLayers=2, bool extended=false, bool upright=false );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-07-26 16:58:46 +08:00
|
|
|
virtual void read( const FileNode &fn );
|
|
|
|
virtual void write( FileStorage &fs ) const;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual int descriptorSize() const;
|
|
|
|
virtual int descriptorType() const;
|
2010-09-23 18:53:36 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
protected:
|
2011-06-08 17:23:33 +08:00
|
|
|
virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
SURF surf;
|
|
|
|
};
|
|
|
|
|
2011-05-21 06:25:53 +08:00
|
|
|
/** The descriptor extractor for the ORB descriptor
|
|
|
|
* There are two ways to speed up its computation:
|
|
|
|
* - if you know the step size of the integral image, use setStepSize so that offsets are precomputed and cached
|
|
|
|
* - if you know the integral image, use setIntegralImage so that it is not recomputed. This calls
|
|
|
|
* setStepSize automatically
|
|
|
|
*/
|
2011-08-04 14:19:52 +08:00
|
|
|
class CV_EXPORTS OrbDescriptorExtractor : public cv::DescriptorExtractor
|
2011-05-21 06:25:53 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** default constructor
|
|
|
|
* @param params parameters to use
|
|
|
|
*/
|
|
|
|
OrbDescriptorExtractor(ORB::CommonParams params = ORB::CommonParams());
|
|
|
|
|
|
|
|
/** destructor */
|
|
|
|
~OrbDescriptorExtractor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual int descriptorSize() const;
|
|
|
|
virtual int descriptorType() const;
|
|
|
|
|
|
|
|
virtual void read(const cv::FileNode&);
|
|
|
|
virtual void write(cv::FileStorage&) const;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void computeImpl(const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, cv::Mat& descriptors) const;
|
|
|
|
private:
|
|
|
|
/** the ORB object we use for the computations */
|
|
|
|
mutable ORB orb_;
|
|
|
|
/** The parameters used */
|
|
|
|
ORB::CommonParams params_;
|
|
|
|
};
|
|
|
|
|
2010-11-15 18:24:38 +08:00
|
|
|
/*
|
|
|
|
* CalonderDescriptorExtractor
|
|
|
|
*/
|
2010-07-26 16:58:46 +08:00
|
|
|
template<typename T>
|
2010-07-27 20:36:48 +08:00
|
|
|
class CV_EXPORTS CalonderDescriptorExtractor : public DescriptorExtractor
|
2010-07-26 16:58:46 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
CalonderDescriptorExtractor( const string& classifierFile );
|
|
|
|
|
|
|
|
virtual void read( const FileNode &fn );
|
|
|
|
virtual void write( FileStorage &fs ) const;
|
|
|
|
|
2010-09-23 18:53:36 +08:00
|
|
|
virtual int descriptorSize() const { return classifier_.classes(); }
|
|
|
|
virtual int descriptorType() const { return DataType<T>::type; }
|
|
|
|
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const;
|
|
|
|
|
2010-07-26 16:58:46 +08:00
|
|
|
protected:
|
2011-06-17 14:31:54 +08:00
|
|
|
virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
|
2010-07-26 16:58:46 +08:00
|
|
|
RTreeClassifier classifier_;
|
|
|
|
static const int BORDER_SIZE = 16;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
CalonderDescriptorExtractor<T>::CalonderDescriptorExtractor(const std::string& classifier_file)
|
|
|
|
{
|
|
|
|
classifier_.read( classifier_file.c_str() );
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2010-11-23 02:27:08 +08:00
|
|
|
void CalonderDescriptorExtractor<T>::computeImpl( const cv::Mat& image,
|
2010-07-26 16:58:46 +08:00
|
|
|
std::vector<cv::KeyPoint>& keypoints,
|
|
|
|
cv::Mat& descriptors) const
|
|
|
|
{
|
2010-11-23 02:27:08 +08:00
|
|
|
// Cannot compute descriptors for keypoints on the image border.
|
2011-05-02 01:38:52 +08:00
|
|
|
KeyPointsFilter::runByImageBorder(keypoints, image.size(), BORDER_SIZE);
|
2010-07-26 16:58:46 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
/// @todo Check 16-byte aligned
|
|
|
|
descriptors.create(keypoints.size(), classifier_.classes(), cv::DataType<T>::type);
|
2010-07-26 16:58:46 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
int patchSize = RandomizedTree::PATCH_SIZE;
|
|
|
|
int offset = patchSize / 2;
|
|
|
|
for (size_t i = 0; i < keypoints.size(); ++i)
|
|
|
|
{
|
|
|
|
cv::Point2f pt = keypoints[i].pt;
|
|
|
|
IplImage ipl = image( Rect((int)(pt.x - offset), (int)(pt.y - offset), patchSize, patchSize) );
|
|
|
|
classifier_.getSignature( &ipl, descriptors.ptr<T>(i));
|
|
|
|
}
|
2010-07-26 16:58:46 +08:00
|
|
|
}
|
2010-07-27 20:36:48 +08:00
|
|
|
|
|
|
|
template<typename T>
|
2010-07-27 21:28:21 +08:00
|
|
|
void CalonderDescriptorExtractor<T>::read( const FileNode& )
|
2010-07-27 20:36:48 +08:00
|
|
|
{}
|
|
|
|
|
|
|
|
template<typename T>
|
2010-08-05 21:29:43 +08:00
|
|
|
void CalonderDescriptorExtractor<T>::write( FileStorage& ) const
|
2010-07-27 20:36:48 +08:00
|
|
|
{}
|
2010-07-26 16:58:46 +08:00
|
|
|
|
2011-01-31 22:18:50 +08:00
|
|
|
template<typename T>
|
|
|
|
bool CalonderDescriptorExtractor<T>::empty() const
|
|
|
|
{
|
|
|
|
return classifier_.trees_.empty();
|
|
|
|
}
|
|
|
|
|
2010-09-23 18:53:36 +08:00
|
|
|
/*
|
2010-11-15 18:24:38 +08:00
|
|
|
* OpponentColorDescriptorExtractor
|
|
|
|
*
|
2010-09-23 18:53:36 +08:00
|
|
|
* Adapts a descriptor extractor to compute descripors in Opponent Color Space
|
|
|
|
* (refer to van de Sande et al., CGIV 2008 "Color Descriptors for Object Category Recognition").
|
|
|
|
* Input RGB image is transformed in Opponent Color Space. Then unadapted descriptor extractor
|
|
|
|
* (set in constructor) computes descriptors on each of the three channel and concatenate
|
|
|
|
* them into a single color descriptor.
|
|
|
|
*/
|
2010-11-12 16:20:51 +08:00
|
|
|
class CV_EXPORTS OpponentColorDescriptorExtractor : public DescriptorExtractor
|
2010-09-23 18:53:36 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
OpponentColorDescriptorExtractor( const Ptr<DescriptorExtractor>& descriptorExtractor );
|
2010-09-23 18:53:36 +08:00
|
|
|
|
|
|
|
virtual void read( const FileNode& );
|
|
|
|
virtual void write( FileStorage& ) const;
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual int descriptorSize() const;
|
|
|
|
virtual int descriptorType() const;
|
2010-09-23 18:53:36 +08:00
|
|
|
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const;
|
|
|
|
|
2010-09-23 18:53:36 +08:00
|
|
|
protected:
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
|
|
|
|
|
|
|
|
Ptr<DescriptorExtractor> descriptorExtractor;
|
2010-09-23 18:53:36 +08:00
|
|
|
};
|
|
|
|
|
2010-11-15 18:24:38 +08:00
|
|
|
/*
|
|
|
|
* BRIEF Descriptor
|
|
|
|
*/
|
|
|
|
class CV_EXPORTS BriefDescriptorExtractor : public DescriptorExtractor
|
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
static const int PATCH_SIZE = 48;
|
|
|
|
static const int KERNEL_SIZE = 9;
|
2010-11-15 18:24:38 +08:00
|
|
|
|
2010-11-24 01:00:55 +08:00
|
|
|
// bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.
|
|
|
|
BriefDescriptorExtractor( int bytes = 32 );
|
2010-11-15 18:24:38 +08:00
|
|
|
|
2011-08-04 17:56:10 +08:00
|
|
|
virtual void read( const FileNode& );
|
|
|
|
virtual void write( FileStorage& ) const;
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual int descriptorSize() const;
|
|
|
|
virtual int descriptorType() const;
|
2010-11-15 18:24:38 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
/// @todo read and write for brief
|
2010-11-15 18:24:38 +08:00
|
|
|
|
|
|
|
protected:
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual void computeImpl(const Mat& image, std::vector<KeyPoint>& keypoints, Mat& descriptors) const;
|
2010-11-15 18:24:38 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
typedef void(*PixelTestFn)(const Mat&, const std::vector<KeyPoint>&, Mat&);
|
2010-11-15 18:24:38 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
int bytes_;
|
|
|
|
PixelTestFn test_fn_;
|
2010-11-15 18:24:38 +08:00
|
|
|
};
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
/****************************************************************************************\
|
|
|
|
* Distance *
|
|
|
|
\****************************************************************************************/
|
|
|
|
template<typename T>
|
|
|
|
struct CV_EXPORTS Accumulator
|
|
|
|
{
|
|
|
|
typedef T Type;
|
|
|
|
};
|
|
|
|
|
2010-11-25 18:05:03 +08:00
|
|
|
template<> struct Accumulator<unsigned char> { typedef float Type; };
|
|
|
|
template<> struct Accumulator<unsigned short> { typedef float Type; };
|
|
|
|
template<> struct Accumulator<char> { typedef float Type; };
|
|
|
|
template<> struct Accumulator<short> { typedef float Type; };
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Squared Euclidean distance functor
|
|
|
|
*/
|
|
|
|
template<class T>
|
|
|
|
struct CV_EXPORTS 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++ )
|
|
|
|
{
|
2010-11-27 02:25:30 +08:00
|
|
|
ResultType diff = (ResultType)(a[i] - b[i]);
|
2010-05-12 01:44:00 +08:00
|
|
|
result += diff*diff;
|
|
|
|
}
|
2010-11-25 17:22:22 +08:00
|
|
|
return (ResultType)sqrt((double)result);
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-06-28 21:06:24 +08:00
|
|
|
/*
|
|
|
|
* Manhattan distance (city block distance) functor
|
|
|
|
*/
|
|
|
|
template<class T>
|
|
|
|
struct CV_EXPORTS L1
|
|
|
|
{
|
|
|
|
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];
|
2010-11-25 18:05:03 +08:00
|
|
|
result += (ResultType)fabs( diff );
|
2010-06-28 21:06:24 +08:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
/*
|
2010-11-23 07:59:25 +08:00
|
|
|
* Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor
|
2010-11-24 06:26:36 +08:00
|
|
|
* bit count of A exclusive XOR'ed with B
|
2010-11-23 02:27:08 +08:00
|
|
|
*/
|
|
|
|
struct CV_EXPORTS HammingLUT
|
|
|
|
{
|
|
|
|
typedef unsigned char ValueType;
|
|
|
|
typedef int ResultType;
|
|
|
|
|
2010-11-24 06:45:49 +08:00
|
|
|
/** this will count the bits in a ^ b
|
|
|
|
*/
|
2010-11-24 06:26:36 +08:00
|
|
|
ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const;
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
/** \brief given a byte, count the bits using a compile time generated look up table
|
|
|
|
* \param b the byte to count bits. The look up table has an entry for all
|
|
|
|
* values of b, where that entry is the number of bits.
|
|
|
|
* \return the number of bits in byte b
|
|
|
|
*/
|
|
|
|
static unsigned char byteBitsLookUp(unsigned char b);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-11-24 06:26:36 +08:00
|
|
|
/// Hamming distance functor, this one will try to use gcc's __builtin_popcountl
|
|
|
|
/// but will fall back on HammingLUT if not available
|
|
|
|
/// bit count of A exclusive XOR'ed with B
|
2010-11-24 01:00:55 +08:00
|
|
|
struct CV_EXPORTS Hamming
|
2010-11-23 02:27:08 +08:00
|
|
|
{
|
|
|
|
typedef unsigned char ValueType;
|
2010-11-24 06:45:49 +08:00
|
|
|
|
|
|
|
//! important that this is signed as weird behavior happens
|
|
|
|
// in BruteForce if not
|
2010-11-23 02:27:08 +08:00
|
|
|
typedef int ResultType;
|
2010-11-24 06:45:49 +08:00
|
|
|
|
|
|
|
/** this will count the bits in a ^ b, using __builtin_popcountl try compiling with sse4
|
|
|
|
*/
|
2010-11-24 06:26:36 +08:00
|
|
|
ResultType operator()(const unsigned char* a, const unsigned char* b, int size) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
};
|
2010-11-24 06:26:36 +08:00
|
|
|
|
2010-06-11 17:38:39 +08:00
|
|
|
|
|
|
|
/****************************************************************************************\
|
2010-07-26 16:58:46 +08:00
|
|
|
* DMatch *
|
2010-06-11 17:38:39 +08:00
|
|
|
\****************************************************************************************/
|
|
|
|
/*
|
2010-10-29 16:44:42 +08:00
|
|
|
* Struct for matching: query descriptor index, train descriptor index, train image index and distance between descriptors.
|
2010-06-11 17:38:39 +08:00
|
|
|
*/
|
2010-08-16 17:15:15 +08:00
|
|
|
struct CV_EXPORTS DMatch
|
2010-06-11 17:38:39 +08:00
|
|
|
{
|
2010-10-29 16:44:42 +08:00
|
|
|
DMatch() : queryIdx(-1), trainIdx(-1), imgIdx(-1), distance(std::numeric_limits<float>::max()) {}
|
|
|
|
DMatch( int _queryIdx, int _trainIdx, float _distance ) :
|
|
|
|
queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(-1), distance(_distance) {}
|
|
|
|
DMatch( int _queryIdx, int _trainIdx, int _imgIdx, float _distance ) :
|
|
|
|
queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(_imgIdx), distance(_distance) {}
|
|
|
|
|
|
|
|
int queryIdx; // query descriptor index
|
|
|
|
int trainIdx; // train descriptor index
|
2010-11-23 02:27:08 +08:00
|
|
|
int imgIdx; // train image index
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-06-11 17:38:39 +08:00
|
|
|
float distance;
|
|
|
|
|
2010-11-03 18:00:24 +08:00
|
|
|
// less is better
|
2010-11-24 01:00:55 +08:00
|
|
|
bool operator<( const DMatch &m ) const
|
2010-06-11 17:38:39 +08:00
|
|
|
{
|
|
|
|
return distance < m.distance;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
/****************************************************************************************\
|
|
|
|
* DescriptorMatcher *
|
|
|
|
\****************************************************************************************/
|
|
|
|
/*
|
|
|
|
* Abstract base class for matching two sets of descriptors.
|
|
|
|
*/
|
|
|
|
class CV_EXPORTS DescriptorMatcher
|
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual ~DescriptorMatcher();
|
|
|
|
|
|
|
|
/*
|
2010-10-29 16:44:42 +08:00
|
|
|
* Add descriptors to train descriptor collection.
|
2010-11-23 02:27:08 +08:00
|
|
|
* descriptors Descriptors to add. Each descriptors[i] is a descriptors set from one image.
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void add( const vector<Mat>& descriptors );
|
2010-05-12 01:44:00 +08:00
|
|
|
/*
|
2010-11-23 02:27:08 +08:00
|
|
|
* Get train descriptors collection.
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
2010-11-23 02:27:08 +08:00
|
|
|
const vector<Mat>& getTrainDescriptors() const;
|
2010-05-12 01:44:00 +08:00
|
|
|
/*
|
2010-11-23 02:27:08 +08:00
|
|
|
* Clear train descriptors collection.
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual void clear();
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
/*
|
|
|
|
* Return true if there are not train descriptors in collection.
|
|
|
|
*/
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const;
|
2010-11-23 02:27:08 +08:00
|
|
|
/*
|
|
|
|
* Return true if the matcher supports mask in match methods.
|
|
|
|
*/
|
|
|
|
virtual bool isMaskSupported() const = 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
/*
|
2010-11-23 02:27:08 +08:00
|
|
|
* Train matcher (e.g. train flann index).
|
|
|
|
* In all methods to match the method train() is run every time before matching.
|
|
|
|
* Some descriptor matchers (e.g. BruteForceMatcher) have empty implementation
|
2011-05-22 04:17:45 +08:00
|
|
|
* of this method, other matchers really train their inner structures
|
2010-11-23 02:27:08 +08:00
|
|
|
* (e.g. FlannBasedMatcher trains flann::Index). So nonempty implementation
|
|
|
|
* of train() should check the class object state and do traing/retraining
|
|
|
|
* only if the state requires that (e.g. FlannBasedMatcher trains flann::Index
|
|
|
|
* if it has not trained yet or if new descriptors have been added to the train
|
|
|
|
* collection).
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void train();
|
2010-06-11 17:38:39 +08:00
|
|
|
/*
|
2010-10-29 16:44:42 +08:00
|
|
|
* Group of methods to match descriptors from image pair.
|
2010-11-23 02:27:08 +08:00
|
|
|
* Method train() is run in this methods.
|
2010-06-11 17:38:39 +08:00
|
|
|
*/
|
2010-10-29 16:44:42 +08:00
|
|
|
// Find one best match for each query descriptor (if mask is empty).
|
2010-11-23 02:27:08 +08:00
|
|
|
void match( const Mat& queryDescriptors, const Mat& trainDescriptors,
|
|
|
|
vector<DMatch>& matches, const Mat& mask=Mat() ) const;
|
|
|
|
// Find k best matches for each query descriptor (in increasing order of distances).
|
|
|
|
// compactResult is used when mask is not empty. If compactResult is false matches
|
|
|
|
// vector will have the same size as queryDescriptors rows. If compactResult is true
|
|
|
|
// matches vector will not contain matches for fully masked out query descriptors.
|
|
|
|
void knnMatch( const Mat& queryDescriptors, const Mat& trainDescriptors,
|
|
|
|
vector<vector<DMatch> >& matches, int k,
|
2010-10-29 16:44:42 +08:00
|
|
|
const Mat& mask=Mat(), bool compactResult=false ) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
// Find best matches for each query descriptor which have distance less than
|
|
|
|
// maxDistance (in increasing order of distances).
|
|
|
|
void radiusMatch( const Mat& queryDescriptors, const Mat& trainDescriptors,
|
|
|
|
vector<vector<DMatch> >& matches, float maxDistance,
|
2010-10-29 16:44:42 +08:00
|
|
|
const Mat& mask=Mat(), bool compactResult=false ) const;
|
2010-06-11 17:38:39 +08:00
|
|
|
/*
|
2010-10-29 16:44:42 +08:00
|
|
|
* Group of methods to match descriptors from one image to image set.
|
|
|
|
* See description of similar methods for matching image pair above.
|
2010-06-11 17:38:39 +08:00
|
|
|
*/
|
2010-11-23 02:27:08 +08:00
|
|
|
void match( const Mat& queryDescriptors, vector<DMatch>& matches,
|
2010-10-29 16:44:42 +08:00
|
|
|
const vector<Mat>& masks=vector<Mat>() );
|
2010-11-23 02:27:08 +08:00
|
|
|
void knnMatch( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
|
|
|
|
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
|
|
|
|
void radiusMatch( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
|
2010-10-29 16:44:42 +08:00
|
|
|
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
|
2010-06-16 16:56:53 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
// Reads matcher object from a file node
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void read( const FileNode& );
|
2010-10-29 16:44:42 +08:00
|
|
|
// Writes matcher object to a file storage
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void write( FileStorage& ) const;
|
|
|
|
|
|
|
|
// Clone the matcher. If emptyTrainData is false the method create deep copy of the object, i.e. copies
|
|
|
|
// both parameters and train data. If emptyTrainData is true the method create object copy with current parameters
|
|
|
|
// but with empty train data.
|
|
|
|
virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const = 0;
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-25 23:59:37 +08:00
|
|
|
static Ptr<DescriptorMatcher> create( const string& descriptorMatcherType );
|
2010-10-29 16:44:42 +08:00
|
|
|
protected:
|
2010-06-16 16:56:53 +08:00
|
|
|
/*
|
2010-10-29 16:44:42 +08:00
|
|
|
* Class to work with descriptors from several images as with one merged matrix.
|
2010-11-23 02:27:08 +08:00
|
|
|
* It is used e.g. in FlannBasedMatcher.
|
2010-06-16 16:56:53 +08:00
|
|
|
*/
|
2010-10-29 22:39:23 +08:00
|
|
|
class CV_EXPORTS DescriptorCollection
|
2010-10-29 16:44:42 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
DescriptorCollection();
|
|
|
|
DescriptorCollection( const DescriptorCollection& collection );
|
|
|
|
virtual ~DescriptorCollection();
|
2010-06-16 16:56:53 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
// Vector of matrices "descriptors" will be merged to one matrix "mergedDescriptors" here.
|
|
|
|
void set( const vector<Mat>& descriptors );
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual void clear();
|
2010-06-16 16:56:53 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
const Mat& getDescriptors() const;
|
2010-10-29 16:44:42 +08:00
|
|
|
const Mat getDescriptor( int imgIdx, int localDescIdx ) const;
|
|
|
|
const Mat getDescriptor( int globalDescIdx ) const;
|
|
|
|
void getLocalIdx( int globalDescIdx, int& imgIdx, int& localDescIdx ) const;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
int size() const;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
protected:
|
2010-11-23 02:27:08 +08:00
|
|
|
Mat mergedDescriptors;
|
2010-10-29 16:44:42 +08:00
|
|
|
vector<int> startIdxs;
|
|
|
|
};
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
// 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
|
|
|
|
// after calling train().
|
|
|
|
virtual void knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
|
|
|
|
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false ) = 0;
|
|
|
|
virtual void radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
|
|
|
|
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false ) = 0;
|
2010-06-16 16:56:53 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
static bool isPossibleMatch( const Mat& mask, int queryIdx, int trainIdx );
|
|
|
|
static bool isMaskedOut( const vector<Mat>& masks, int queryIdx );
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
static Mat clone_op( Mat m ) { return m.clone(); }
|
|
|
|
void checkMasks( const vector<Mat>& masks, int queryDescriptorsCount ) const;
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
// Collection of descriptors from train images.
|
2010-10-29 16:44:42 +08:00
|
|
|
vector<Mat> trainDescCollection;
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2010-11-03 18:00:24 +08:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* For efficiency, BruteForceMatcher is templated on the distance metric.
|
|
|
|
* For float descriptors, a common choice would be cv::L2<float>.
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
|
|
|
template<class Distance>
|
2010-11-03 18:00:24 +08:00
|
|
|
class CV_EXPORTS BruteForceMatcher : public DescriptorMatcher
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
BruteForceMatcher( Distance d = Distance() ) : distance(d) {}
|
|
|
|
virtual ~BruteForceMatcher() {}
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual bool isMaskSupported() const { return true; }
|
|
|
|
|
|
|
|
virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const;
|
2010-11-03 18:00:24 +08:00
|
|
|
|
|
|
|
protected:
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
|
|
|
|
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
|
|
|
|
virtual void radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
|
|
|
|
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
|
2010-11-03 18:00:24 +08:00
|
|
|
|
|
|
|
Distance distance;
|
|
|
|
|
|
|
|
private:
|
|
|
|
/*
|
2010-11-23 02:27:08 +08:00
|
|
|
* Next two methods are used to implement specialization.
|
2010-11-03 18:00:24 +08:00
|
|
|
*/
|
2010-11-23 02:27:08 +08:00
|
|
|
static void commonKnnMatchImpl( BruteForceMatcher<Distance>& matcher,
|
|
|
|
const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
|
|
|
|
const vector<Mat>& masks, bool compactResult );
|
|
|
|
static void commonRadiusMatchImpl( BruteForceMatcher<Distance>& matcher,
|
|
|
|
const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
|
|
|
|
const vector<Mat>& masks, bool compactResult );
|
2010-11-03 18:00:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
template<class Distance>
|
2010-11-23 02:27:08 +08:00
|
|
|
Ptr<DescriptorMatcher> BruteForceMatcher<Distance>::clone( bool emptyTrainData ) const
|
|
|
|
{
|
|
|
|
BruteForceMatcher* matcher = new BruteForceMatcher(distance);
|
|
|
|
if( !emptyTrainData )
|
|
|
|
{
|
2011-08-03 19:30:09 +08:00
|
|
|
matcher->trainDescCollection.resize(trainDescCollection.size());
|
2011-01-12 14:39:08 +08:00
|
|
|
std::transform( trainDescCollection.begin(), trainDescCollection.end(),
|
|
|
|
matcher->trainDescCollection.begin(), clone_op );
|
2010-11-23 02:27:08 +08:00
|
|
|
}
|
|
|
|
return matcher;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class Distance>
|
|
|
|
void BruteForceMatcher<Distance>::knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
|
2010-11-03 18:00:24 +08:00
|
|
|
const vector<Mat>& masks, bool compactResult )
|
|
|
|
{
|
2010-11-23 02:27:08 +08:00
|
|
|
commonKnnMatchImpl( *this, queryDescriptors, matches, k, masks, compactResult );
|
2010-11-03 18:00:24 +08:00
|
|
|
}
|
2010-06-16 16:56:53 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
template<class Distance>
|
2010-11-23 02:27:08 +08:00
|
|
|
void BruteForceMatcher<Distance>::radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches,
|
|
|
|
float maxDistance, const vector<Mat>& masks, bool compactResult )
|
2010-11-03 18:00:24 +08:00
|
|
|
{
|
2010-11-23 02:27:08 +08:00
|
|
|
commonRadiusMatchImpl( *this, queryDescriptors, matches, maxDistance, masks, compactResult );
|
2010-11-03 18:00:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class Distance>
|
2010-11-23 02:27:08 +08:00
|
|
|
inline void BruteForceMatcher<Distance>::commonKnnMatchImpl( BruteForceMatcher<Distance>& matcher,
|
|
|
|
const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int knn,
|
2010-10-29 16:44:42 +08:00
|
|
|
const vector<Mat>& masks, bool compactResult )
|
|
|
|
{
|
|
|
|
typedef typename Distance::ValueType ValueType;
|
|
|
|
typedef typename Distance::ResultType DistanceType;
|
2010-11-23 02:27:08 +08:00
|
|
|
CV_DbgAssert( !queryDescriptors.empty() );
|
|
|
|
CV_Assert( DataType<ValueType>::type == queryDescriptors.type() );
|
|
|
|
|
|
|
|
int dimension = queryDescriptors.cols;
|
|
|
|
matches.reserve(queryDescriptors.rows);
|
2010-10-29 16:44:42 +08:00
|
|
|
|
|
|
|
size_t imgCount = matcher.trainDescCollection.size();
|
|
|
|
vector<Mat> allDists( imgCount ); // distances between one query descriptor and all train descriptors
|
|
|
|
for( size_t i = 0; i < imgCount; i++ )
|
2010-11-25 00:03:11 +08:00
|
|
|
allDists[i] = Mat( 1, matcher.trainDescCollection[i].rows, DataType<DistanceType>::type );
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
|
2010-10-29 16:44:42 +08:00
|
|
|
{
|
2010-11-23 02:27:08 +08:00
|
|
|
if( matcher.isMaskedOut( masks, qIdx ) )
|
2010-10-29 16:44:42 +08:00
|
|
|
{
|
|
|
|
if( !compactResult ) // push empty vector
|
|
|
|
matches.push_back( vector<DMatch>() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// 1. compute distances between i-th query descriptor and all train descriptors
|
|
|
|
for( size_t iIdx = 0; iIdx < imgCount; iIdx++ )
|
|
|
|
{
|
|
|
|
CV_Assert( DataType<ValueType>::type == matcher.trainDescCollection[iIdx].type() || matcher.trainDescCollection[iIdx].empty() );
|
2010-11-23 02:27:08 +08:00
|
|
|
CV_Assert( queryDescriptors.cols == matcher.trainDescCollection[iIdx].cols ||
|
|
|
|
matcher.trainDescCollection[iIdx].empty() );
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
const ValueType* d1 = (const ValueType*)(queryDescriptors.data + queryDescriptors.step*qIdx);
|
2010-10-29 16:44:42 +08:00
|
|
|
allDists[iIdx].setTo( Scalar::all(std::numeric_limits<DistanceType>::max()) );
|
|
|
|
for( int tIdx = 0; tIdx < matcher.trainDescCollection[iIdx].rows; tIdx++ )
|
|
|
|
{
|
2010-11-23 02:27:08 +08:00
|
|
|
if( masks.empty() || matcher.isPossibleMatch(masks[iIdx], qIdx, tIdx) )
|
2010-10-29 16:44:42 +08:00
|
|
|
{
|
|
|
|
const ValueType* d2 = (const ValueType*)(matcher.trainDescCollection[iIdx].data +
|
|
|
|
matcher.trainDescCollection[iIdx].step*tIdx);
|
2010-11-01 13:34:51 +08:00
|
|
|
allDists[iIdx].at<DistanceType>(0, tIdx) = matcher.distance(d1, d2, dimension);
|
2010-10-29 16:44:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
// 2. choose k nearest matches for query[i]
|
2010-10-29 16:44:42 +08:00
|
|
|
matches.push_back( vector<DMatch>() );
|
|
|
|
vector<vector<DMatch> >::reverse_iterator curMatches = matches.rbegin();
|
|
|
|
for( int k = 0; k < knn; k++ )
|
|
|
|
{
|
|
|
|
DMatch bestMatch;
|
2010-11-23 02:27:08 +08:00
|
|
|
bestMatch.distance = std::numeric_limits<float>::max();
|
2010-10-29 16:44:42 +08:00
|
|
|
for( size_t iIdx = 0; iIdx < imgCount; iIdx++ )
|
|
|
|
{
|
2011-01-12 20:03:03 +08:00
|
|
|
if( !allDists[iIdx].empty() )
|
|
|
|
{
|
|
|
|
double minVal;
|
|
|
|
Point minLoc;
|
|
|
|
minMaxLoc( allDists[iIdx], &minVal, 0, &minLoc, 0 );
|
|
|
|
if( minVal < bestMatch.distance )
|
|
|
|
bestMatch = DMatch( qIdx, minLoc.x, (int)iIdx, (float)minVal );
|
|
|
|
}
|
2010-10-29 16:44:42 +08:00
|
|
|
}
|
|
|
|
if( bestMatch.trainIdx == -1 )
|
|
|
|
break;
|
|
|
|
|
2010-11-01 13:34:51 +08:00
|
|
|
allDists[bestMatch.imgIdx].at<DistanceType>(0, bestMatch.trainIdx) = std::numeric_limits<DistanceType>::max();
|
2010-10-29 16:44:42 +08:00
|
|
|
curMatches->push_back( bestMatch );
|
|
|
|
}
|
2010-11-01 13:34:51 +08:00
|
|
|
//TODO should already be sorted at this point?
|
2010-10-29 16:44:42 +08:00
|
|
|
std::sort( curMatches->begin(), curMatches->end() );
|
|
|
|
}
|
|
|
|
}
|
2010-06-11 17:38:39 +08:00
|
|
|
}
|
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
template<class Distance>
|
2010-11-23 02:27:08 +08:00
|
|
|
inline void BruteForceMatcher<Distance>::commonRadiusMatchImpl( BruteForceMatcher<Distance>& matcher,
|
|
|
|
const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
|
2010-10-29 16:44:42 +08:00
|
|
|
const vector<Mat>& masks, bool compactResult )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
typedef typename Distance::ValueType ValueType;
|
|
|
|
typedef typename Distance::ResultType DistanceType;
|
2010-11-23 02:27:08 +08:00
|
|
|
CV_DbgAssert( !queryDescriptors.empty() );
|
|
|
|
CV_Assert( DataType<ValueType>::type == queryDescriptors.type() );
|
|
|
|
|
|
|
|
int dimension = queryDescriptors.cols;
|
|
|
|
matches.reserve(queryDescriptors.rows);
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
size_t imgCount = matcher.trainDescCollection.size();
|
2010-11-23 02:27:08 +08:00
|
|
|
for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-11-23 02:27:08 +08:00
|
|
|
if( matcher.isMaskedOut( masks, qIdx ) )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-29 16:44:42 +08:00
|
|
|
if( !compactResult ) // push empty vector
|
|
|
|
matches.push_back( vector<DMatch>() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
matches.push_back( vector<DMatch>() );
|
|
|
|
vector<vector<DMatch> >::reverse_iterator curMatches = matches.rbegin();
|
|
|
|
for( size_t iIdx = 0; iIdx < imgCount; iIdx++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-10-29 16:44:42 +08:00
|
|
|
CV_Assert( DataType<ValueType>::type == matcher.trainDescCollection[iIdx].type() ||
|
|
|
|
matcher.trainDescCollection[iIdx].empty() );
|
2010-11-23 02:27:08 +08:00
|
|
|
CV_Assert( queryDescriptors.cols == matcher.trainDescCollection[iIdx].cols ||
|
|
|
|
matcher.trainDescCollection[iIdx].empty() );
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
const ValueType* d1 = (const ValueType*)(queryDescriptors.data + queryDescriptors.step*qIdx);
|
2010-10-29 16:44:42 +08:00
|
|
|
for( int tIdx = 0; tIdx < matcher.trainDescCollection[iIdx].rows; tIdx++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2010-11-23 02:27:08 +08:00
|
|
|
if( masks.empty() || matcher.isPossibleMatch(masks[iIdx], qIdx, tIdx) )
|
2010-10-29 16:44:42 +08:00
|
|
|
{
|
|
|
|
const ValueType* d2 = (const ValueType*)(matcher.trainDescCollection[iIdx].data +
|
|
|
|
matcher.trainDescCollection[iIdx].step*tIdx);
|
|
|
|
DistanceType d = matcher.distance(d1, d2, dimension);
|
|
|
|
if( d < maxDistance )
|
2010-11-26 00:55:46 +08:00
|
|
|
curMatches->push_back( DMatch( qIdx, tIdx, (int)iIdx, (float)d ) );
|
2010-10-29 16:44:42 +08:00
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2010-10-29 16:44:42 +08:00
|
|
|
std::sort( curMatches->begin(), curMatches->end() );
|
2010-06-11 17:38:39 +08:00
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
/*
|
|
|
|
* BruteForceMatcher L2 specialization
|
|
|
|
*/
|
|
|
|
template<>
|
2010-11-23 02:27:08 +08:00
|
|
|
void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
|
2010-10-29 16:44:42 +08:00
|
|
|
const vector<Mat>& masks, bool compactResult );
|
|
|
|
template<>
|
2010-11-23 02:27:08 +08:00
|
|
|
void BruteForceMatcher<L2<float> >::radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches,
|
|
|
|
float maxDistance, const vector<Mat>& masks, bool compactResult );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
/*
|
2010-10-29 16:44:42 +08:00
|
|
|
* Flann based matcher
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
2010-10-29 16:44:42 +08:00
|
|
|
class CV_EXPORTS FlannBasedMatcher : public DescriptorMatcher
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
FlannBasedMatcher( const Ptr<flann::IndexParams>& indexParams=new flann::KDTreeIndexParams(),
|
|
|
|
const Ptr<flann::SearchParams>& searchParams=new flann::SearchParams() );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void add( const vector<Mat>& descriptors );
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual void clear();
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual void train();
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual bool isMaskSupported() const;
|
|
|
|
|
|
|
|
virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const;
|
2010-05-26 19:27:56 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
protected:
|
|
|
|
static void convertToDMatches( const DescriptorCollection& descriptors,
|
|
|
|
const Mat& indices, const Mat& distances,
|
2010-10-29 16:44:42 +08:00
|
|
|
vector<vector<DMatch> >& matches );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
|
|
|
|
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
|
|
|
|
virtual void radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
|
|
|
|
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
|
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
Ptr<flann::IndexParams> indexParams;
|
|
|
|
Ptr<flann::SearchParams> searchParams;
|
2011-02-02 23:47:08 +08:00
|
|
|
Ptr<flann::Index> flannIndex;
|
2010-10-29 16:44:42 +08:00
|
|
|
|
|
|
|
DescriptorCollection mergedDescriptors;
|
|
|
|
int addedDescCount;
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
/****************************************************************************************\
|
|
|
|
* GenericDescriptorMatcher *
|
|
|
|
\****************************************************************************************/
|
2010-05-12 01:44:00 +08:00
|
|
|
/*
|
2010-11-16 23:42:31 +08:00
|
|
|
* Abstract interface for a keypoint descriptor and matcher
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
2010-10-29 16:44:42 +08:00
|
|
|
class GenericDescriptorMatcher;
|
|
|
|
typedef GenericDescriptorMatcher GenericDescriptorMatch;
|
|
|
|
|
|
|
|
class CV_EXPORTS GenericDescriptorMatcher
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
GenericDescriptorMatcher();
|
|
|
|
virtual ~GenericDescriptorMatcher();
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
/*
|
2010-11-23 02:27:08 +08:00
|
|
|
* Add train collection: images and keypoints from them.
|
|
|
|
* images A set of train images.
|
|
|
|
* ketpoints Keypoint collection that have been detected on train images.
|
|
|
|
*
|
|
|
|
* Keypoints for which a descriptor cannot be computed are removed. Such keypoints
|
|
|
|
* must be filtered in this method befor adding keypoints to train collection "trainPointCollection".
|
|
|
|
* If inheritor class need perform such prefiltering the method add() must be overloaded.
|
|
|
|
* In the other class methods programmer has access to the train keypoints by a constant link.
|
2010-10-29 16:44:42 +08:00
|
|
|
*/
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void add( const vector<Mat>& images,
|
|
|
|
vector<vector<KeyPoint> >& keypoints );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
const vector<Mat>& getTrainImages() const;
|
|
|
|
const vector<vector<KeyPoint> >& getTrainKeypoints() const;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
/*
|
|
|
|
* Clear images and keypoints storing in train collection.
|
|
|
|
*/
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual void clear();
|
2010-11-23 02:27:08 +08:00
|
|
|
/*
|
|
|
|
* Returns true if matcher supports mask to match descriptors.
|
|
|
|
*/
|
|
|
|
virtual bool isMaskSupported() = 0;
|
|
|
|
/*
|
|
|
|
* Train some inner structures (e.g. flann index or decision trees).
|
|
|
|
* train() methods is run every time in matching methods. So the method implementation
|
|
|
|
* should has a check whether these inner structures need be trained/retrained or not.
|
|
|
|
*/
|
|
|
|
virtual void train();
|
2010-11-04 00:39:58 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
/*
|
|
|
|
* Classifies query keypoints.
|
|
|
|
* queryImage The query image
|
2010-11-23 02:27:08 +08:00
|
|
|
* queryKeypoints Keypoints from the query image
|
2010-10-29 16:44:42 +08:00
|
|
|
* trainImage The train image
|
2010-11-23 02:27:08 +08:00
|
|
|
* trainKeypoints Keypoints from the train image
|
2010-10-29 16:44:42 +08:00
|
|
|
*/
|
|
|
|
// Classify keypoints from query image under one train image.
|
2010-11-24 01:00:55 +08:00
|
|
|
void classify( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
2010-11-23 02:27:08 +08:00
|
|
|
const Mat& trainImage, vector<KeyPoint>& trainKeypoints ) const;
|
2010-10-29 16:44:42 +08:00
|
|
|
// Classify keypoints from query image under train image collection.
|
2010-11-24 01:00:55 +08:00
|
|
|
void classify( const Mat& queryImage, vector<KeyPoint>& queryKeypoints );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
/*
|
|
|
|
* Group of methods to match keypoints from image pair.
|
2010-11-23 02:27:08 +08:00
|
|
|
* Keypoints for which a descriptor cannot be computed are removed.
|
|
|
|
* train() method is called here.
|
2010-10-29 16:44:42 +08:00
|
|
|
*/
|
|
|
|
// Find one best match for each query descriptor (if mask is empty).
|
2010-11-23 02:27:08 +08:00
|
|
|
void match( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
|
|
|
const Mat& trainImage, vector<KeyPoint>& trainKeypoints,
|
2010-10-29 16:44:42 +08:00
|
|
|
vector<DMatch>& matches, const Mat& mask=Mat() ) const;
|
2010-11-23 02:27:08 +08:00
|
|
|
// Find k best matches for each query keypoint (in increasing order of distances).
|
|
|
|
// compactResult is used when mask is not empty. If compactResult is false matches
|
|
|
|
// vector will have the same size as queryDescriptors rows.
|
2010-10-29 16:44:42 +08:00
|
|
|
// If compactResult is true matches vector will not contain matches for fully masked out query descriptors.
|
2010-11-23 02:27:08 +08:00
|
|
|
void knnMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
|
|
|
const Mat& trainImage, vector<KeyPoint>& trainKeypoints,
|
|
|
|
vector<vector<DMatch> >& matches, int k,
|
|
|
|
const Mat& mask=Mat(), bool compactResult=false ) const;
|
2010-10-29 16:44:42 +08:00
|
|
|
// Find best matches for each query descriptor which have distance less than maxDistance (in increasing order of distances).
|
2010-11-23 02:27:08 +08:00
|
|
|
void radiusMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
|
|
|
const Mat& trainImage, vector<KeyPoint>& trainKeypoints,
|
|
|
|
vector<vector<DMatch> >& matches, float maxDistance,
|
|
|
|
const Mat& mask=Mat(), bool compactResult=false ) const;
|
2010-10-29 16:44:42 +08:00
|
|
|
/*
|
|
|
|
* Group of methods to match keypoints from one image to image set.
|
|
|
|
* See description of similar methods for matching image pair above.
|
|
|
|
*/
|
2010-11-23 02:27:08 +08:00
|
|
|
void match( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
2010-10-29 16:44:42 +08:00
|
|
|
vector<DMatch>& matches, const vector<Mat>& masks=vector<Mat>() );
|
2010-11-23 02:27:08 +08:00
|
|
|
void knnMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
|
|
|
vector<vector<DMatch> >& matches, int k,
|
|
|
|
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
|
|
|
|
void radiusMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
|
|
|
vector<vector<DMatch> >& matches, float maxDistance,
|
|
|
|
const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
|
2010-10-29 16:44:42 +08:00
|
|
|
|
|
|
|
// Reads matcher object from a file node
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void read( const FileNode& );
|
2010-10-29 16:44:42 +08:00
|
|
|
// Writes matcher object to a file storage
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void write( FileStorage& ) const;
|
2010-06-11 17:38:39 +08:00
|
|
|
|
2011-01-31 22:18:50 +08:00
|
|
|
// Return true if matching object is empty (e.g. feature detector or descriptor matcher are empty)
|
|
|
|
virtual bool empty() const;
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
// Clone the matcher. If emptyTrainData is false the method create deep copy of the object, i.e. copies
|
|
|
|
// both parameters and train data. If emptyTrainData is true the method create object copy with current parameters
|
|
|
|
// but with empty train data.
|
|
|
|
virtual Ptr<GenericDescriptorMatcher> clone( bool emptyTrainData=false ) const = 0;
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-25 23:59:37 +08:00
|
|
|
static Ptr<GenericDescriptorMatcher> create( const string& genericDescritptorMatcherType,
|
|
|
|
const string ¶msFilename=string() );
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
protected:
|
|
|
|
// 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
|
|
|
|
// after calling train().
|
|
|
|
virtual void knnMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
|
|
|
vector<vector<DMatch> >& matches, int k,
|
2010-10-29 16:44:42 +08:00
|
|
|
const vector<Mat>& masks, bool compactResult ) = 0;
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void radiusMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
2010-10-29 16:44:42 +08:00
|
|
|
vector<vector<DMatch> >& matches, float maxDistance,
|
|
|
|
const vector<Mat>& masks, bool compactResult ) = 0;
|
|
|
|
/*
|
|
|
|
* A storage for sets of keypoints together with corresponding images and class IDs
|
|
|
|
*/
|
|
|
|
class CV_EXPORTS KeyPointCollection
|
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
KeyPointCollection();
|
|
|
|
KeyPointCollection( const KeyPointCollection& collection );
|
|
|
|
void add( const vector<Mat>& images, const vector<vector<KeyPoint> >& keypoints );
|
2010-10-29 16:44:42 +08:00
|
|
|
void clear();
|
2010-06-16 16:56:53 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
// Returns the total number of keypoints in the collection
|
2010-11-23 02:27:08 +08:00
|
|
|
size_t keypointCount() const;
|
|
|
|
size_t imageCount() const;
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
const vector<vector<KeyPoint> >& getKeypoints() const;
|
|
|
|
const vector<KeyPoint>& getKeypoints( int imgIdx ) const;
|
2010-10-29 16:44:42 +08:00
|
|
|
const KeyPoint& getKeyPoint( int imgIdx, int localPointIdx ) const;
|
|
|
|
const KeyPoint& getKeyPoint( int globalPointIdx ) const;
|
|
|
|
void getLocalIdx( int globalPointIdx, int& imgIdx, int& localPointIdx ) const;
|
2010-06-10 15:59:18 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
const vector<Mat>& getImages() const;
|
|
|
|
const Mat& getImage( int imgIdx ) const;
|
2010-10-29 16:44:42 +08:00
|
|
|
|
|
|
|
protected:
|
2010-11-23 02:27:08 +08:00
|
|
|
int pointCount;
|
2010-10-29 16:44:42 +08:00
|
|
|
|
|
|
|
vector<Mat> images;
|
2010-11-23 02:27:08 +08:00
|
|
|
vector<vector<KeyPoint> > keypoints;
|
|
|
|
// global indices of the first points in each image, startIndices.size() = keypoints.size()
|
2010-10-29 16:44:42 +08:00
|
|
|
vector<int> startIndices;
|
2010-11-23 02:27:08 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
static Mat clone_op( Mat m ) { return m.clone(); }
|
2010-10-29 16:44:42 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
KeyPointCollection trainPointCollection;
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2010-10-29 16:44:42 +08:00
|
|
|
* OneWayDescriptorMatcher
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
2010-10-29 16:44:42 +08:00
|
|
|
class OneWayDescriptorMatcher;
|
|
|
|
typedef OneWayDescriptorMatcher OneWayDescriptorMatch;
|
|
|
|
|
|
|
|
class CV_EXPORTS OneWayDescriptorMatcher : public GenericDescriptorMatcher
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
class CV_EXPORTS Params
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const int POSE_COUNT = 500;
|
|
|
|
static const int PATCH_WIDTH = 24;
|
|
|
|
static const int PATCH_HEIGHT = 24;
|
2010-06-02 14:55:03 +08:00
|
|
|
static float GET_MIN_SCALE() { return 0.7f; }
|
|
|
|
static float GET_MAX_SCALE() { return 1.5f; }
|
|
|
|
static float GET_STEP_SCALE() { return 1.2f; }
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
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() );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
int poseCount;
|
|
|
|
Size patchSize;
|
2010-06-02 13:19:09 +08:00
|
|
|
string pcaFilename;
|
2010-05-12 01:44:00 +08:00
|
|
|
string trainPath;
|
2010-06-02 13:19:09 +08:00
|
|
|
string trainImagesList;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
float minScale, maxScale, stepScale;
|
|
|
|
};
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
OneWayDescriptorMatcher( const Params& params=Params() );
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual ~OneWayDescriptorMatcher();
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
void initialize( const Params& params, const Ptr<OneWayDescriptorBase>& base=Ptr<OneWayDescriptorBase>() );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-06-08 14:56:35 +08:00
|
|
|
// Clears keypoints storing in collection and OneWayDescriptorBase
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void clear();
|
2010-06-08 14:56:35 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual void train();
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual bool isMaskSupported();
|
2010-11-04 00:39:58 +08:00
|
|
|
|
2010-07-26 16:58:46 +08:00
|
|
|
virtual void read( const FileNode &fn );
|
|
|
|
virtual void write( FileStorage& fs ) const;
|
2010-06-02 14:55:03 +08:00
|
|
|
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const;
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual Ptr<GenericDescriptorMatcher> clone( bool emptyTrainData=false ) const;
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
protected:
|
2010-10-29 16:44:42 +08:00
|
|
|
// 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.
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void knnMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
|
|
|
vector<vector<DMatch> >& matches, int k,
|
2010-10-29 16:44:42 +08:00
|
|
|
const vector<Mat>& masks, bool compactResult );
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void radiusMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
2010-10-29 16:44:42 +08:00
|
|
|
vector<vector<DMatch> >& matches, float maxDistance,
|
|
|
|
const vector<Mat>& masks, bool compactResult );
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
Ptr<OneWayDescriptorBase> base;
|
|
|
|
Params params;
|
2010-10-29 16:44:42 +08:00
|
|
|
int prevTrainCount;
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2010-10-29 16:44:42 +08:00
|
|
|
* FernDescriptorMatcher
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
2010-10-29 16:44:42 +08:00
|
|
|
class FernDescriptorMatcher;
|
|
|
|
typedef FernDescriptorMatcher FernDescriptorMatch;
|
|
|
|
|
|
|
|
class CV_EXPORTS FernDescriptorMatcher : public GenericDescriptorMatcher
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-10-29 22:39:23 +08:00
|
|
|
class CV_EXPORTS Params
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
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,
|
2010-05-12 01:44:00 +08:00
|
|
|
const PatchGenerator& patchGenerator=PatchGenerator() );
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
Params( const string& filename );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
int nclasses;
|
|
|
|
int patchSize;
|
|
|
|
int signatureSize;
|
|
|
|
int nstructs;
|
|
|
|
int structSize;
|
|
|
|
int nviews;
|
|
|
|
int compressionMethod;
|
|
|
|
PatchGenerator patchGenerator;
|
|
|
|
|
|
|
|
string filename;
|
|
|
|
};
|
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
FernDescriptorMatcher( const Params& params=Params() );
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual ~FernDescriptorMatcher();
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-08-16 17:15:15 +08:00
|
|
|
virtual void clear();
|
2010-06-08 14:56:35 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual void train();
|
2010-06-08 14:56:35 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual bool isMaskSupported();
|
2010-11-04 00:39:58 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual void read( const FileNode &fn );
|
2010-06-08 14:56:35 +08:00
|
|
|
virtual void write( FileStorage& fs ) const;
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const;
|
2010-06-08 14:56:35 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual Ptr<GenericDescriptorMatcher> clone( bool emptyTrainData=false ) const;
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
protected:
|
|
|
|
virtual void knnMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
|
|
|
vector<vector<DMatch> >& matches, int k,
|
2010-10-29 16:44:42 +08:00
|
|
|
const vector<Mat>& masks, bool compactResult );
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void radiusMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
2010-10-29 16:44:42 +08:00
|
|
|
vector<vector<DMatch> >& matches, float maxDistance,
|
|
|
|
const vector<Mat>& masks, bool compactResult );
|
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
void trainFernClassifier();
|
|
|
|
void calcBestProbAndMatchIdx( const Mat& image, const Point2f& pt,
|
|
|
|
float& bestProb, int& bestMatchIdx, vector<float>& signature );
|
|
|
|
Ptr<FernClassifier> classifier;
|
|
|
|
Params params;
|
2010-10-29 16:44:42 +08:00
|
|
|
int prevTrainCount;
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/****************************************************************************************\
|
2010-10-29 16:44:42 +08:00
|
|
|
* VectorDescriptorMatcher *
|
2010-05-12 01:44:00 +08:00
|
|
|
\****************************************************************************************/
|
|
|
|
|
|
|
|
/*
|
2010-05-21 00:16:28 +08:00
|
|
|
* A class used for matching descriptors that can be described as vectors in a finite-dimensional space
|
2010-05-12 01:44:00 +08:00
|
|
|
*/
|
2010-10-29 16:44:42 +08:00
|
|
|
class VectorDescriptorMatcher;
|
|
|
|
typedef VectorDescriptorMatcher VectorDescriptorMatch;
|
|
|
|
|
|
|
|
class CV_EXPORTS VectorDescriptorMatcher : public GenericDescriptorMatcher
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
VectorDescriptorMatcher( const Ptr<DescriptorExtractor>& extractor, const Ptr<DescriptorMatcher>& matcher );
|
|
|
|
virtual ~VectorDescriptorMatcher();
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual void add( const vector<Mat>& imgCollection,
|
|
|
|
vector<vector<KeyPoint> >& pointCollection );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual void clear();
|
2010-06-16 16:56:53 +08:00
|
|
|
|
2010-10-29 16:44:42 +08:00
|
|
|
virtual void train();
|
2010-05-26 23:00:03 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual bool isMaskSupported();
|
2010-11-04 00:39:58 +08:00
|
|
|
|
2010-07-26 16:58:46 +08:00
|
|
|
virtual void read( const FileNode& fn );
|
|
|
|
virtual void write( FileStorage& fs ) const;
|
2011-01-31 22:18:50 +08:00
|
|
|
virtual bool empty() const;
|
2010-06-04 13:30:09 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual Ptr<GenericDescriptorMatcher> clone( bool emptyTrainData=false ) const;
|
2010-10-29 16:44:42 +08:00
|
|
|
|
2010-11-23 02:27:08 +08:00
|
|
|
protected:
|
|
|
|
virtual void knnMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
|
|
|
vector<vector<DMatch> >& matches, int k,
|
2010-10-29 16:44:42 +08:00
|
|
|
const vector<Mat>& masks, bool compactResult );
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual void radiusMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
|
2010-10-29 16:44:42 +08:00
|
|
|
vector<vector<DMatch> >& matches, float maxDistance,
|
|
|
|
const vector<Mat>& masks, bool compactResult );
|
|
|
|
|
2010-07-12 19:56:11 +08:00
|
|
|
Ptr<DescriptorExtractor> extractor;
|
|
|
|
Ptr<DescriptorMatcher> matcher;
|
2010-05-12 01:44:00 +08:00
|
|
|
};
|
|
|
|
|
2010-08-05 20:19:26 +08:00
|
|
|
/****************************************************************************************\
|
|
|
|
* Drawing functions *
|
|
|
|
\****************************************************************************************/
|
2010-06-12 01:15:43 +08:00
|
|
|
struct CV_EXPORTS DrawMatchesFlags
|
|
|
|
{
|
|
|
|
enum{ DEFAULT = 0, // Output image matrix will be created (Mat::create),
|
2010-06-12 18:11:57 +08:00
|
|
|
// i.e. existing memory of output image may be reused.
|
2010-06-12 01:15:43 +08:00
|
|
|
// Two source image, matches and single keypoints will be drawn.
|
2010-08-04 00:28:52 +08:00
|
|
|
// For each keypoint only the center point will be drawn (without
|
|
|
|
// the circle around keypoint with keypoint size and orientation).
|
2010-06-12 01:15:43 +08:00
|
|
|
DRAW_OVER_OUTIMG = 1, // Output image matrix will not be created (Mat::create).
|
|
|
|
// Matches will be drawn on existing content of output image.
|
2010-08-04 00:28:52 +08:00
|
|
|
NOT_DRAW_SINGLE_POINTS = 2, // Single keypoints will not be drawn.
|
|
|
|
DRAW_RICH_KEYPOINTS = 4 // For each keypoint the circle around keypoint with keypoint size and
|
2010-08-05 20:19:26 +08:00
|
|
|
// orientation will be drawn.
|
2010-06-12 01:15:43 +08:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2010-08-04 00:28:52 +08:00
|
|
|
// Draw keypoints.
|
2011-01-31 17:51:17 +08:00
|
|
|
CV_EXPORTS void drawKeypoints( const Mat& image, const vector<KeyPoint>& keypoints, Mat& outImage,
|
2010-08-04 00:28:52 +08:00
|
|
|
const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );
|
|
|
|
|
2010-06-12 01:15:43 +08:00
|
|
|
// Draws matches of keypints from two images on output image.
|
2010-08-04 00:28:52 +08:00
|
|
|
CV_EXPORTS void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
|
|
|
|
const Mat& img2, const vector<KeyPoint>& keypoints2,
|
|
|
|
const vector<DMatch>& matches1to2, Mat& outImg,
|
|
|
|
const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
|
|
|
|
const vector<char>& matchesMask=vector<char>(), int flags=DrawMatchesFlags::DEFAULT );
|
|
|
|
|
|
|
|
CV_EXPORTS void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
|
|
|
|
const Mat& img2, const vector<KeyPoint>& keypoints2,
|
|
|
|
const vector<vector<DMatch> >& matches1to2, Mat& outImg,
|
|
|
|
const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
|
|
|
|
const vector<vector<char> >& matchesMask=vector<vector<char> >(), int flags=DrawMatchesFlags::DEFAULT );
|
2010-06-12 01:15:43 +08:00
|
|
|
|
2010-08-05 20:19:26 +08:00
|
|
|
/****************************************************************************************\
|
2010-09-24 00:17:48 +08:00
|
|
|
* Functions to evaluate the feature detectors and [generic] descriptor extractors *
|
2010-08-05 20:19:26 +08:00
|
|
|
\****************************************************************************************/
|
|
|
|
|
|
|
|
CV_EXPORTS void evaluateFeatureDetector( const Mat& img1, const Mat& img2, const Mat& H1to2,
|
|
|
|
vector<KeyPoint>* keypoints1, vector<KeyPoint>* keypoints2,
|
|
|
|
float& repeatability, int& correspCount,
|
|
|
|
const Ptr<FeatureDetector>& fdetector=Ptr<FeatureDetector>() );
|
|
|
|
|
|
|
|
CV_EXPORTS void computeRecallPrecisionCurve( const vector<vector<DMatch> >& matches1to2,
|
|
|
|
const vector<vector<uchar> >& correctMatches1to2Mask,
|
|
|
|
vector<Point2f>& recallPrecisionCurve );
|
2011-05-20 20:14:35 +08:00
|
|
|
|
2010-08-05 20:19:26 +08:00
|
|
|
CV_EXPORTS float getRecall( const vector<Point2f>& recallPrecisionCurve, float l_precision );
|
2011-05-20 20:14:35 +08:00
|
|
|
CV_EXPORTS int getNearestPoint( const vector<Point2f>& recallPrecisionCurve, float l_precision );
|
2010-08-05 20:19:26 +08:00
|
|
|
|
2010-09-24 00:17:48 +08:00
|
|
|
CV_EXPORTS void evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, const Mat& H1to2,
|
|
|
|
vector<KeyPoint>& keypoints1, vector<KeyPoint>& keypoints2,
|
|
|
|
vector<vector<DMatch> >* matches1to2, vector<vector<uchar> >* correctMatches1to2Mask,
|
|
|
|
vector<Point2f>& recallPrecisionCurve,
|
2010-10-29 16:44:42 +08:00
|
|
|
const Ptr<GenericDescriptorMatcher>& dmatch=Ptr<GenericDescriptorMatcher>() );
|
2010-08-05 20:19:26 +08:00
|
|
|
|
|
|
|
|
2010-09-24 00:17:48 +08:00
|
|
|
/****************************************************************************************\
|
|
|
|
* Bag of visual words *
|
|
|
|
\****************************************************************************************/
|
|
|
|
/*
|
|
|
|
* Abstract base class for training of a 'bag of visual words' vocabulary from a set of descriptors
|
|
|
|
*/
|
2010-09-30 22:21:22 +08:00
|
|
|
class CV_EXPORTS BOWTrainer
|
2010-09-24 00:17:48 +08:00
|
|
|
{
|
|
|
|
public:
|
2010-11-23 02:27:08 +08:00
|
|
|
BOWTrainer();
|
|
|
|
virtual ~BOWTrainer();
|
2010-10-08 21:17:34 +08:00
|
|
|
|
2010-09-30 22:21:22 +08:00
|
|
|
void add( const Mat& descriptors );
|
2010-11-23 02:27:08 +08:00
|
|
|
const vector<Mat>& getDescriptors() const;
|
|
|
|
int descripotorsCount() const;
|
2010-09-30 22:21:22 +08:00
|
|
|
|
|
|
|
virtual void clear();
|
|
|
|
|
2010-09-24 00:17:48 +08:00
|
|
|
/*
|
|
|
|
* Train visual words vocabulary, that is cluster training descriptors and
|
|
|
|
* compute cluster centers.
|
2010-09-30 22:21:22 +08:00
|
|
|
* Returns cluster centers.
|
2010-09-24 00:17:48 +08:00
|
|
|
*
|
|
|
|
* descriptors Training descriptors computed on images keypoints.
|
|
|
|
*/
|
2010-09-30 22:21:22 +08:00
|
|
|
virtual Mat cluster() const = 0;
|
|
|
|
virtual Mat cluster( const Mat& descriptors ) const = 0;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
vector<Mat> descriptors;
|
|
|
|
int size;
|
2010-09-24 00:17:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is BOWTrainer using cv::kmeans to get vocabulary.
|
|
|
|
*/
|
2010-09-30 22:21:22 +08:00
|
|
|
class CV_EXPORTS BOWKMeansTrainer : public BOWTrainer
|
2010-09-24 00:17:48 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
BOWKMeansTrainer( int clusterCount, const TermCriteria& termcrit=TermCriteria(),
|
|
|
|
int attempts=3, int flags=KMEANS_PP_CENTERS );
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual ~BOWKMeansTrainer();
|
2010-09-30 22:21:22 +08:00
|
|
|
|
|
|
|
// Returns trained vocabulary (i.e. cluster centers).
|
|
|
|
virtual Mat cluster() const;
|
|
|
|
virtual Mat cluster( const Mat& descriptors ) const;
|
2010-09-24 00:17:48 +08:00
|
|
|
|
|
|
|
protected:
|
2010-09-30 22:21:22 +08:00
|
|
|
|
2010-09-24 00:17:48 +08:00
|
|
|
int clusterCount;
|
|
|
|
TermCriteria termcrit;
|
|
|
|
int attempts;
|
|
|
|
int flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2010-11-14 14:27:48 +08:00
|
|
|
* Class to compute image descriptor using bag of visual words.
|
2010-09-24 00:17:48 +08:00
|
|
|
*/
|
2010-09-30 22:21:22 +08:00
|
|
|
class CV_EXPORTS BOWImgDescriptorExtractor
|
2010-09-24 00:17:48 +08:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
BOWImgDescriptorExtractor( const Ptr<DescriptorExtractor>& dextractor,
|
|
|
|
const Ptr<DescriptorMatcher>& dmatcher );
|
2010-11-23 02:27:08 +08:00
|
|
|
virtual ~BOWImgDescriptorExtractor();
|
2010-10-08 21:17:34 +08:00
|
|
|
|
2010-09-30 22:21:22 +08:00
|
|
|
void setVocabulary( const Mat& vocabulary );
|
2010-11-23 02:27:08 +08:00
|
|
|
const Mat& getVocabulary() const;
|
2010-09-24 00:17:48 +08:00
|
|
|
void compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& imgDescriptor,
|
2010-11-23 02:27:08 +08:00
|
|
|
vector<vector<int> >* pointIdxsOfClusters=0, Mat* descriptors=0 );
|
|
|
|
// compute() is not constant because DescriptorMatcher::match is not constant
|
|
|
|
|
|
|
|
int descriptorSize() const;
|
|
|
|
int descriptorType() const;
|
2010-09-24 00:17:48 +08:00
|
|
|
|
|
|
|
protected:
|
|
|
|
Mat vocabulary;
|
|
|
|
Ptr<DescriptorExtractor> dextractor;
|
|
|
|
Ptr<DescriptorMatcher> dmatcher;
|
|
|
|
};
|
|
|
|
|
2010-08-05 20:19:26 +08:00
|
|
|
} /* namespace cv */
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
#endif /* __cplusplus */
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* End of file. */
|