include/opencv2/features2d/features2d.hpp
Go to the documentation of this file.
00001 /*M///////////////////////////////////////////////////////////////////////////////////////
00002 //
00003 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00004 //
00005 //  By downloading, copying, installing or using the software you agree to this license.
00006 //  If you do not agree to this license, do not download, install,
00007 //  copy or use the software.
00008 //
00009 //
00010 //                           License Agreement
00011 //                For Open Source Computer Vision Library
00012 //
00013 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
00014 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
00015 // Third party copyrights are property of their respective owners.
00016 //
00017 // Redistribution and use in source and binary forms, with or without modification,
00018 // are permitted provided that the following conditions are met:
00019 //
00020 //   * Redistribution's of source code must retain the above copyright notice,
00021 //     this list of conditions and the following disclaimer.
00022 //
00023 //   * Redistribution's in binary form must reproduce the above copyright notice,
00024 //     this list of conditions and the following disclaimer in the documentation
00025 //     and/or other materials provided with the distribution.
00026 //
00027 //   * The name of the copyright holders may not be used to endorse or promote products
00028 //     derived from this software without specific prior written permission.
00029 //
00030 // This software is provided by the copyright holders and contributors "as is" and
00031 // any express or implied warranties, including, but not limited to, the implied
00032 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00033 // In no event shall the Intel Corporation or contributors be liable for any direct,
00034 // indirect, incidental, special, exemplary, or consequential damages
00035 // (including, but not limited to, procurement of substitute goods or services;
00036 // loss of use, data, or profits; or business interruption) however caused
00037 // and on any theory of liability, whether in contract, strict liability,
00038 // or tort (including negligence or otherwise) arising in any way out of
00039 // the use of this software, even if advised of the possibility of such damage.
00040 //
00041 //M*/
00042 
00043 #ifndef __OPENCV_FEATURES_2D_HPP__
00044 #define __OPENCV_FEATURES_2D_HPP__
00045 
00046 #include "opencv2/core/core.hpp"
00047 #include "opencv2/flann/flann.hpp"
00048 
00049 #ifdef __cplusplus
00050 #include <limits>
00051 
00052 extern "C" {
00053 #endif
00054 
00055 typedef struct CvSURFPoint
00056 {
00057     CvPoint2D32f pt;
00058 
00059     int          laplacian;
00060     int          size;
00061     float        dir;
00062     float        hessian;
00063 
00064 } CvSURFPoint;
00065 
00066 CV_INLINE CvSURFPoint cvSURFPoint( CvPoint2D32f pt, int laplacian,
00067                                    int size, float dir CV_DEFAULT(0),
00068                                    float hessian CV_DEFAULT(0))
00069 {
00070     CvSURFPoint kp;
00071 
00072     kp.pt        = pt;
00073     kp.laplacian = laplacian;
00074     kp.size      = size;
00075     kp.dir       = dir;
00076     kp.hessian   = hessian;
00077 
00078     return kp;
00079 }
00080 
00081 typedef struct CvSURFParams
00082 {
00083     int    extended;
00084     int    upright;
00085     double hessianThreshold;
00086 
00087     int    nOctaves;
00088     int    nOctaveLayers;
00089 
00090 } CvSURFParams;
00091 
00092 CVAPI(CvSURFParams) cvSURFParams( double hessianThreshold, int extended CV_DEFAULT(0) );
00093 
00094 // If useProvidedKeyPts!=0, keypoints are not detected, but descriptors are computed
00095 //  at the locations provided in keypoints (a CvSeq of CvSURFPoint).
00096 CVAPI(void) cvExtractSURF( const CvArr* img, const CvArr* mask,
00097                            CvSeq** keypoints, CvSeq** descriptors,
00098                            CvMemStorage* storage, CvSURFParams params, int useProvidedKeyPts CV_DEFAULT(0)  );
00099 
00103 typedef struct CvMSERParams
00104 {
00106     int delta;
00108     int maxArea;
00110     int minArea;
00112     float maxVariation;
00114     float minDiversity;
00115     
00117     
00119     int maxEvolution;
00121     double areaThreshold;
00123     double minMargin;
00125     int edgeBlurSize;
00126 } CvMSERParams;
00127 
00128 CVAPI(CvMSERParams) cvMSERParams( int delta CV_DEFAULT(5), int min_area CV_DEFAULT(60),
00129                            int max_area CV_DEFAULT(14400), float max_variation CV_DEFAULT(.25f),
00130                            float min_diversity CV_DEFAULT(.2f), int max_evolution CV_DEFAULT(200),
00131                            double area_threshold CV_DEFAULT(1.01),
00132                            double min_margin CV_DEFAULT(.003),
00133                            int edge_blur_size CV_DEFAULT(5) );
00134 
00135 // Extracts the contours of Maximally Stable Extremal Regions
00136 CVAPI(void) cvExtractMSER( CvArr* _img, CvArr* _mask, CvSeq** contours, CvMemStorage* storage, CvMSERParams params );
00137 
00138 
00139 typedef struct CvStarKeypoint
00140 {
00141     CvPoint pt;
00142     int size;
00143     float response;
00144 } CvStarKeypoint;
00145 
00146 CV_INLINE CvStarKeypoint cvStarKeypoint(CvPoint pt, int size, float response)
00147 {
00148     CvStarKeypoint kpt;
00149     kpt.pt = pt;
00150     kpt.size = size;
00151     kpt.response = response;
00152     return kpt;
00153 }
00154 
00155 typedef struct CvStarDetectorParams
00156 {
00157     int maxSize;
00158     int responseThreshold;
00159     int lineThresholdProjected;
00160     int lineThresholdBinarized;
00161     int suppressNonmaxSize;
00162 } CvStarDetectorParams;
00163 
00164 CV_INLINE CvStarDetectorParams cvStarDetectorParams(
00165     int maxSize CV_DEFAULT(45),
00166     int responseThreshold CV_DEFAULT(30),
00167     int lineThresholdProjected CV_DEFAULT(10),
00168     int lineThresholdBinarized CV_DEFAULT(8),
00169     int suppressNonmaxSize CV_DEFAULT(5))
00170 {
00171     CvStarDetectorParams params;
00172     params.maxSize = maxSize;
00173     params.responseThreshold = responseThreshold;
00174     params.lineThresholdProjected = lineThresholdProjected;
00175     params.lineThresholdBinarized = lineThresholdBinarized;
00176     params.suppressNonmaxSize = suppressNonmaxSize;
00177 
00178     return params;
00179 }
00180 
00181 CVAPI(CvSeq*) cvGetStarKeypoints( const CvArr* img, CvMemStorage* storage,
00182         CvStarDetectorParams params CV_DEFAULT(cvStarDetectorParams()));
00183 
00184 #ifdef __cplusplus
00185 }
00186 
00187 namespace cv
00188 {
00189     struct CV_EXPORTS DefaultRngAuto
00190     {
00191         const uint64 old_state;
00192 
00193         DefaultRngAuto() : old_state(theRNG().state) { theRNG().state = (uint64)-1; }
00194         ~DefaultRngAuto() { theRNG().state = old_state; }
00195 
00196         DefaultRngAuto& operator=(const DefaultRngAuto&);
00197     };
00198 
00199 
00200 // CvAffinePose: defines a parameterized affine transformation of an image patch.
00201 // An image patch is rotated on angle phi (in degrees), then scaled lambda1 times
00202 // along horizontal and lambda2 times along vertical direction, and then rotated again
00203 // on angle (theta - phi).
00204 class CV_EXPORTS CvAffinePose
00205 {
00206 public:
00207     float phi;
00208     float theta;
00209     float lambda1;
00210     float lambda2;
00211 };
00212 
00225 class CV_EXPORTS_W_SIMPLE KeyPoint
00226 {
00227 public:
00229     CV_WRAP KeyPoint() : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {}
00231     KeyPoint(Point2f _pt, float _size, float _angle=-1,
00232             float _response=0, int _octave=0, int _class_id=-1)
00233             : pt(_pt), size(_size), angle(_angle),
00234             response(_response), octave(_octave), class_id(_class_id) {}
00236     CV_WRAP KeyPoint(float x, float y, float _size, float _angle=-1,
00237             float _response=0, int _octave=0, int _class_id=-1)
00238             : pt(x, y), size(_size), angle(_angle),
00239             response(_response), octave(_octave), class_id(_class_id) {}
00240     
00241     size_t hash() const;
00242     
00244     static void convert(const std::vector<KeyPoint>& keypoints,
00245                         CV_OUT std::vector<Point2f>& points2f,
00246                         const std::vector<int>& keypointIndexes=std::vector<int>());
00248     static void convert(const std::vector<Point2f>& points2f,
00249                         CV_OUT std::vector<KeyPoint>& keypoints,
00250                         float size=1, float response=1, int octave=0, int class_id=-1);
00251 
00255     static float overlap(const KeyPoint& kp1, const KeyPoint& kp2);
00256 
00257     CV_PROP_RW Point2f pt; 
00258     CV_PROP_RW float size; 
00259     CV_PROP_RW float angle; 
00260     CV_PROP_RW float response; 
00261     CV_PROP_RW int octave; 
00262     CV_PROP_RW int class_id; 
00263 };
00264     
00266 CV_EXPORTS void write(FileStorage& fs, const string& name, const vector<KeyPoint>& keypoints);
00268 CV_EXPORTS void read(const FileNode& node, CV_OUT vector<KeyPoint>& keypoints);    
00269 
00270 /*
00271  * A class filters a vector of keypoints.
00272  * Because now it is difficult to provide a convenient interface for all usage scenarios of the keypoints filter class,
00273  * it has only 4 needed by now static methods.
00274  */
00275 class CV_EXPORTS KeyPointsFilter
00276 {
00277 public:
00278     KeyPointsFilter(){}
00279 
00280     /*
00281      * Remove keypoints within borderPixels of an image edge.
00282      */
00283     static void runByImageBorder( vector<KeyPoint>& keypoints, Size imageSize, int borderSize );
00284     /*
00285      * Remove keypoints of sizes out of range.
00286      */
00287     static void runByKeypointSize( vector<KeyPoint>& keypoints, float minSize, float maxSize=std::numeric_limits<float>::max() );
00288     /*
00289      * Remove keypoints from some image by mask for pixels of this image.
00290      */
00291     static void runByPixelsMask( vector<KeyPoint>& keypoints, const Mat& mask );
00292     /*
00293      * Remove duplicated keypoints.
00294      */
00295     static void removeDuplicated( vector<KeyPoint>& keypoints );
00296 };
00297 
00304 class CV_EXPORTS SIFT
00305 {
00306 public:
00307     struct CV_EXPORTS CommonParams
00308     {
00309         static const int DEFAULT_NOCTAVES = 4;
00310         static const int DEFAULT_NOCTAVE_LAYERS = 3;
00311         static const int DEFAULT_FIRST_OCTAVE = -1;
00312         enum { FIRST_ANGLE = 0, AVERAGE_ANGLE = 1 };
00313 
00314         CommonParams();
00315         CommonParams( int _nOctaves, int _nOctaveLayers, int /*_firstOctave*/, int /*_angleMode*/ );
00316         CommonParams( int _nOctaves, int _nOctaveLayers );
00317         int nOctaves, nOctaveLayers;
00318         int firstOctave; // it is not used now (firstOctave == 0 always)
00319         int angleMode;   // it is not used now
00320     };
00321 
00322     struct CV_EXPORTS DetectorParams
00323     {
00324         static double GET_DEFAULT_THRESHOLD() { return 0.04; }
00325         static double GET_DEFAULT_EDGE_THRESHOLD() { return 10.0; }
00326 
00327         DetectorParams();
00328         DetectorParams( double _threshold, double _edgeThreshold );
00329         double threshold, edgeThreshold;
00330     };
00331 
00332     struct CV_EXPORTS DescriptorParams
00333     {
00334         static double GET_DEFAULT_MAGNIFICATION() { return 3.0; }
00335         static const bool DEFAULT_IS_NORMALIZE = true;
00336         static const int DESCRIPTOR_SIZE = 128;
00337 
00338         DescriptorParams();
00339         DescriptorParams( double _magnification, bool /*_isNormalize*/, bool _recalculateAngles );
00340         DescriptorParams( bool _recalculateAngles );
00341         double magnification;
00342         bool isNormalize; // it is not used now (true always)
00343         bool recalculateAngles;
00344     };
00345 
00346     SIFT();
00348     SIFT( double _threshold, double _edgeThreshold,
00349           int _nOctaves=CommonParams::DEFAULT_NOCTAVES,
00350           int _nOctaveLayers=CommonParams::DEFAULT_NOCTAVE_LAYERS,
00351           int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE,
00352           int _angleMode=CommonParams::FIRST_ANGLE );
00354     SIFT( double _magnification, bool _isNormalize=true,
00355           bool _recalculateAngles = true,
00356           int _nOctaves=CommonParams::DEFAULT_NOCTAVES,
00357           int _nOctaveLayers=CommonParams::DEFAULT_NOCTAVE_LAYERS,
00358           int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE,
00359           int _angleMode=CommonParams::FIRST_ANGLE );
00360     SIFT( const CommonParams& _commParams,
00361           const DetectorParams& _detectorParams = DetectorParams(),
00362           const DescriptorParams& _descriptorParams = DescriptorParams() );
00363 
00365     int descriptorSize() const;
00367     void operator()(const Mat& img, const Mat& mask,
00368                     vector<KeyPoint>& keypoints) const;
00371     void operator()(const Mat& img, const Mat& mask,
00372                     vector<KeyPoint>& keypoints,
00373                     Mat& descriptors,
00374                     bool useProvidedKeypoints=false) const;
00375 
00376     CommonParams getCommonParams () const;
00377     DetectorParams getDetectorParams () const;
00378     DescriptorParams getDescriptorParams () const;
00379 
00380 protected:
00381     CommonParams commParams;
00382     DetectorParams detectorParams;
00383     DescriptorParams descriptorParams;
00384 };
00385 
00386     
00392 class CV_EXPORTS_W SURF : public CvSURFParams
00393 {
00394 public:
00396     CV_WRAP SURF();
00398     CV_WRAP SURF(double _hessianThreshold, int _nOctaves=4,
00399          int _nOctaveLayers=2, bool _extended=false, bool _upright=false);
00400 
00402     CV_WRAP int descriptorSize() const;
00404     CV_WRAP_AS(detect) void operator()(const Mat& img, const Mat& mask,
00405                     CV_OUT vector<KeyPoint>& keypoints) const;
00407     CV_WRAP_AS(detect) void operator()(const Mat& img, const Mat& mask,
00408                     CV_OUT vector<KeyPoint>& keypoints,
00409                     CV_OUT vector<float>& descriptors,
00410                     bool useProvidedKeypoints=false) const;
00411 };
00412 
00416 class CV_EXPORTS ORB
00417 {
00418 public:
00419 
00421   enum { kBytes = 32 };
00422 
00423   struct CV_EXPORTS CommonParams
00424   {
00425     enum { DEFAULT_N_LEVELS = 3, DEFAULT_FIRST_LEVEL = 0};
00426 
00428     CommonParams(float scale_factor = 1.2f, unsigned int n_levels = DEFAULT_N_LEVELS, int edge_threshold = 31,
00429                  unsigned int first_level = DEFAULT_FIRST_LEVEL) :
00430       scale_factor_(scale_factor), n_levels_(n_levels), first_level_(first_level >= n_levels ? 0 : first_level),
00431       edge_threshold_(edge_threshold)
00432     {
00433       // No other patch size is supported right now
00434       patch_size_ = 31;
00435     }
00436     void read(const FileNode& fn);
00437     void write(FileStorage& fs) const;
00438 
00440     float scale_factor_;
00442     unsigned int n_levels_;
00446     unsigned int first_level_;
00448     int edge_threshold_;
00449 
00450     friend class ORB;
00451   protected:
00453     int patch_size_;
00454   };
00455 
00460   ORB(size_t n_features = 500, const CommonParams & detector_params = CommonParams());
00461 
00463   ~ORB();
00464 
00466   int descriptorSize() const;
00467 
00473   void
00474   operator()(const cv::Mat &image, const cv::Mat &mask, std::vector<cv::KeyPoint> & keypoints);
00475 
00483   void
00484   operator()(const cv::Mat &image, const cv::Mat &mask, std::vector<cv::KeyPoint> & keypoints, cv::Mat & descriptors,
00485              bool useProvidedKeypoints = false);
00486 
00487 private:
00489   static const int kKernelWidth = 5;
00490 
00499   void
00500   operator()(const cv::Mat &image, const cv::Mat &mask, std::vector<cv::KeyPoint> & keypoints, cv::Mat & descriptors,
00501              bool do_keypoints, bool do_descriptors);
00502 
00508   void computeKeyPoints(const std::vector<cv::Mat>& image_pyramid, const std::vector<cv::Mat>& mask_pyramid,
00509                         std::vector<std::vector<cv::KeyPoint> >& keypoints) const;
00510 
00517   void
00518   computeOrientation(const cv::Mat& image, const cv::Mat& integral_image, unsigned int level,
00519                      std::vector<cv::KeyPoint>& keypoints) const;
00520 
00528   void
00529   computeDescriptors(const cv::Mat& image, const cv::Mat& integral_image, unsigned int level,
00530                      std::vector<cv::KeyPoint>& keypoints, cv::Mat & descriptors) const;
00531 
00537   void computeIntegralImage(const cv::Mat & image, unsigned int level, cv::Mat &integral_image);
00538 
00540   CommonParams params_;
00541 
00543   int half_patch_size_;
00544 
00546   std::vector<std::vector<int> > orientation_horizontal_offsets_;
00547   std::vector<std::vector<int> > orientation_vertical_offsets_;
00548 
00550   std::vector<size_t> integral_image_steps_;
00551 
00553   std::vector<size_t> n_features_per_level_;
00554 
00556   size_t n_features_;
00557 
00559   std::vector<int> u_max_;
00560 
00562   class OrbPatterns;
00563   std::vector<OrbPatterns*> patterns_;
00564 };
00565 
00575 class CV_EXPORTS_W MSER : public CvMSERParams
00576 {
00577 public:
00579     CV_WRAP MSER();
00581     CV_WRAP MSER( int _delta, int _min_area, int _max_area,
00582           double _max_variation, double _min_diversity,
00583           int _max_evolution, double _area_threshold,
00584           double _min_margin, int _edge_blur_size );
00586     CV_WRAP_AS(detect) void operator()( const Mat& image,
00587         CV_OUT vector<vector<Point> >& msers, const Mat& mask ) const;
00588 };
00589 
00595 class CV_EXPORTS_W StarDetector : public CvStarDetectorParams
00596 {
00597 public:
00599     CV_WRAP StarDetector();
00601     CV_WRAP StarDetector(int _maxSize, int _responseThreshold,
00602                  int _lineThresholdProjected,
00603                  int _lineThresholdBinarized,
00604                  int _suppressNonmaxSize);
00606     CV_WRAP_AS(detect) void operator()(const Mat& image,
00607                 CV_OUT vector<KeyPoint>& keypoints) const;
00608 };
00609 
00611 CV_EXPORTS void FAST( const Mat& image, CV_OUT vector<KeyPoint>& keypoints,
00612                       int threshold, bool nonmaxSupression=true );
00613 
00617 class CV_EXPORTS PatchGenerator
00618 {
00619 public:
00620     PatchGenerator();
00621     PatchGenerator(double _backgroundMin, double _backgroundMax,
00622                    double _noiseRange, bool _randomBlur=true,
00623                    double _lambdaMin=0.6, double _lambdaMax=1.5,
00624                    double _thetaMin=-CV_PI, double _thetaMax=CV_PI,
00625                    double _phiMin=-CV_PI, double _phiMax=CV_PI );
00626     void operator()(const Mat& image, Point2f pt, Mat& patch, Size patchSize, RNG& rng) const;
00627     void operator()(const Mat& image, const Mat& transform, Mat& patch,
00628                     Size patchSize, RNG& rng) const;
00629     void warpWholeImage(const Mat& image, Mat& matT, Mat& buf,
00630                         CV_OUT Mat& warped, int border, RNG& rng) const;
00631     void generateRandomTransform(Point2f srcCenter, Point2f dstCenter,
00632                                  CV_OUT Mat& transform, RNG& rng,
00633                                  bool inverse=false) const;
00634     void setAffineParam(double lambda, double theta, double phi);
00635     
00636     double backgroundMin, backgroundMax;
00637     double noiseRange;
00638     bool randomBlur;
00639     double lambdaMin, lambdaMax;
00640     double thetaMin, thetaMax;
00641     double phiMin, phiMax;
00642 };
00643 
00644 
00645 class CV_EXPORTS LDetector
00646 {
00647 public:
00648     LDetector();
00649     LDetector(int _radius, int _threshold, int _nOctaves,
00650               int _nViews, double _baseFeatureSize, double _clusteringDistance);
00651     void operator()(const Mat& image,
00652                     CV_OUT vector<KeyPoint>& keypoints,
00653                     int maxCount=0, bool scaleCoords=true) const;
00654     void operator()(const vector<Mat>& pyr,
00655                     CV_OUT vector<KeyPoint>& keypoints,
00656                     int maxCount=0, bool scaleCoords=true) const;
00657     void getMostStable2D(const Mat& image, CV_OUT vector<KeyPoint>& keypoints,
00658                          int maxCount, const PatchGenerator& patchGenerator) const;
00659     void setVerbose(bool verbose);
00660     
00661     void read(const FileNode& node);
00662     void write(FileStorage& fs, const String& name=String()) const;
00663     
00664     int radius;
00665     int threshold;
00666     int nOctaves;
00667     int nViews;
00668     bool verbose;
00669     
00670     double baseFeatureSize;
00671     double clusteringDistance;
00672 };
00673 
00674 typedef LDetector YAPE;
00675 
00676 class CV_EXPORTS FernClassifier
00677 {
00678 public:
00679     FernClassifier();
00680     FernClassifier(const FileNode& node);
00681     FernClassifier(const vector<vector<Point2f> >& points,
00682                    const vector<Mat>& refimgs,
00683                    const vector<vector<int> >& labels=vector<vector<int> >(),
00684                    int _nclasses=0, int _patchSize=PATCH_SIZE,
00685                    int _signatureSize=DEFAULT_SIGNATURE_SIZE,
00686                    int _nstructs=DEFAULT_STRUCTS,
00687                    int _structSize=DEFAULT_STRUCT_SIZE,
00688                    int _nviews=DEFAULT_VIEWS,
00689                    int _compressionMethod=COMPRESSION_NONE,
00690                    const PatchGenerator& patchGenerator=PatchGenerator());
00691     virtual ~FernClassifier();
00692     virtual void read(const FileNode& n);
00693     virtual void write(FileStorage& fs, const String& name=String()) const;
00694     virtual void trainFromSingleView(const Mat& image,
00695                                      const vector<KeyPoint>& keypoints,
00696                                      int _patchSize=PATCH_SIZE,
00697                                      int _signatureSize=DEFAULT_SIGNATURE_SIZE,
00698                                      int _nstructs=DEFAULT_STRUCTS,
00699                                      int _structSize=DEFAULT_STRUCT_SIZE,
00700                                      int _nviews=DEFAULT_VIEWS,
00701                                      int _compressionMethod=COMPRESSION_NONE,
00702                                      const PatchGenerator& patchGenerator=PatchGenerator());
00703     virtual void train(const vector<vector<Point2f> >& points,
00704                        const vector<Mat>& refimgs,
00705                        const vector<vector<int> >& labels=vector<vector<int> >(),
00706                        int _nclasses=0, int _patchSize=PATCH_SIZE,
00707                        int _signatureSize=DEFAULT_SIGNATURE_SIZE,
00708                        int _nstructs=DEFAULT_STRUCTS,
00709                        int _structSize=DEFAULT_STRUCT_SIZE,
00710                        int _nviews=DEFAULT_VIEWS,
00711                        int _compressionMethod=COMPRESSION_NONE,
00712                        const PatchGenerator& patchGenerator=PatchGenerator());
00713     virtual int operator()(const Mat& img, Point2f kpt, vector<float>& signature) const;
00714     virtual int operator()(const Mat& patch, vector<float>& signature) const;
00715     virtual void clear();
00716     virtual bool empty() const;
00717     void setVerbose(bool verbose);
00718     
00719     int getClassCount() const;
00720     int getStructCount() const;
00721     int getStructSize() const;
00722     int getSignatureSize() const;
00723     int getCompressionMethod() const;
00724     Size getPatchSize() const;
00725     
00726     struct Feature
00727     {
00728         uchar x1, y1, x2, y2;
00729         Feature() : x1(0), y1(0), x2(0), y2(0) {}
00730         Feature(int _x1, int _y1, int _x2, int _y2)
00731         : x1((uchar)_x1), y1((uchar)_y1), x2((uchar)_x2), y2((uchar)_y2)
00732         {}
00733         template<typename _Tp> bool operator ()(const Mat_<_Tp>& patch) const
00734         { return patch(y1,x1) > patch(y2, x2); }
00735     };
00736     
00737     enum
00738     {
00739         PATCH_SIZE = 31,
00740         DEFAULT_STRUCTS = 50,
00741         DEFAULT_STRUCT_SIZE = 9,
00742         DEFAULT_VIEWS = 5000,
00743         DEFAULT_SIGNATURE_SIZE = 176,
00744         COMPRESSION_NONE = 0,
00745         COMPRESSION_RANDOM_PROJ = 1,
00746         COMPRESSION_PCA = 2,
00747         DEFAULT_COMPRESSION_METHOD = COMPRESSION_NONE
00748     };
00749     
00750 protected:
00751     virtual void prepare(int _nclasses, int _patchSize, int _signatureSize,
00752                          int _nstructs, int _structSize,
00753                          int _nviews, int _compressionMethod);
00754     virtual void finalize(RNG& rng);
00755     virtual int getLeaf(int fidx, const Mat& patch) const;
00756     
00757     bool verbose;
00758     int nstructs;
00759     int structSize;
00760     int nclasses;
00761     int signatureSize;
00762     int compressionMethod;
00763     int leavesPerStruct;
00764     Size patchSize;
00765     vector<Feature> features;
00766     vector<int> classCounters;
00767     vector<float> posteriors;
00768 };
00769 
00770 
00771 /****************************************************************************************\
00772 *                                 Calonder Classifier                                    *
00773 \****************************************************************************************/
00774 
00775 struct RTreeNode;
00776 
00777 struct CV_EXPORTS BaseKeypoint
00778 {
00779   int x;
00780   int y;
00781   IplImage* image;
00782 
00783   BaseKeypoint()
00784     : x(0), y(0), image(NULL)
00785   {}
00786 
00787   BaseKeypoint(int x, int y, IplImage* image)
00788     : x(x), y(y), image(image)
00789   {}
00790 };
00791 
00792 class CV_EXPORTS RandomizedTree
00793 {
00794 public:
00795   friend class RTreeClassifier;
00796 
00797   static const uchar PATCH_SIZE = 32;
00798   static const int DEFAULT_DEPTH = 9;
00799   static const int DEFAULT_VIEWS = 5000;
00800   static const size_t DEFAULT_REDUCED_NUM_DIM = 176;
00801   static float GET_LOWER_QUANT_PERC() { return .03f; }
00802   static float GET_UPPER_QUANT_PERC() { return .92f; }
00803 
00804   RandomizedTree();
00805   ~RandomizedTree();
00806 
00807   void train(std::vector<BaseKeypoint> const& base_set, RNG &rng,
00808              int depth, int views, size_t reduced_num_dim, int num_quant_bits);
00809   void train(std::vector<BaseKeypoint> const& base_set, RNG &rng,
00810              PatchGenerator &make_patch, int depth, int views, size_t reduced_num_dim,
00811              int num_quant_bits);
00812 
00813   // following two funcs are EXPERIMENTAL (do not use unless you know exactly what you do)
00814   static void quantizeVector(float *vec, int dim, int N, float bnds[2], int clamp_mode=0);
00815   static void quantizeVector(float *src, int dim, int N, float bnds[2], uchar *dst);
00816 
00817   // patch_data must be a 32x32 array (no row padding)
00818   float* getPosterior(uchar* patch_data);
00819   const float* getPosterior(uchar* patch_data) const;
00820   uchar* getPosterior2(uchar* patch_data);
00821   const uchar* getPosterior2(uchar* patch_data) const;
00822 
00823   void read(const char* file_name, int num_quant_bits);
00824   void read(std::istream &is, int num_quant_bits);
00825   void write(const char* file_name) const;
00826   void write(std::ostream &os) const;
00827 
00828   int classes() { return classes_; }
00829   int depth() { return depth_; }
00830 
00831   //void setKeepFloatPosteriors(bool b) { keep_float_posteriors_ = b; }
00832   void discardFloatPosteriors() { freePosteriors(1); }
00833 
00834   inline void applyQuantization(int num_quant_bits) { makePosteriors2(num_quant_bits); }
00835 
00836   // debug
00837   void savePosteriors(std::string url, bool append=false);
00838   void savePosteriors2(std::string url, bool append=false);
00839 
00840 private:
00841   int classes_;
00842   int depth_;
00843   int num_leaves_;
00844   std::vector<RTreeNode> nodes_;
00845   float **posteriors_;        // 16-bytes aligned posteriors
00846   uchar **posteriors2_;     // 16-bytes aligned posteriors
00847   std::vector<int> leaf_counts_;
00848 
00849   void createNodes(int num_nodes, RNG &rng);
00850   void allocPosteriorsAligned(int num_leaves, int num_classes);
00851   void freePosteriors(int which);    // which: 1=posteriors_, 2=posteriors2_, 3=both
00852   void init(int classes, int depth, RNG &rng);
00853   void addExample(int class_id, uchar* patch_data);
00854   void finalize(size_t reduced_num_dim, int num_quant_bits);
00855   int getIndex(uchar* patch_data) const;
00856   inline float* getPosteriorByIndex(int index);
00857   inline const float* getPosteriorByIndex(int index) const;
00858   inline uchar* getPosteriorByIndex2(int index);
00859   inline const uchar* getPosteriorByIndex2(int index) const;
00860   //void makeRandomMeasMatrix(float *cs_phi, PHI_DISTR_TYPE dt, size_t reduced_num_dim);
00861   void convertPosteriorsToChar();
00862   void makePosteriors2(int num_quant_bits);
00863   void compressLeaves(size_t reduced_num_dim);
00864   void estimateQuantPercForPosteriors(float perc[2]);
00865 };
00866 
00867 
00868 inline uchar* getData(IplImage* image)
00869 {
00870   return reinterpret_cast<uchar*>(image->imageData);
00871 }
00872 
00873 inline float* RandomizedTree::getPosteriorByIndex(int index)
00874 {
00875   return const_cast<float*>(const_cast<const RandomizedTree*>(this)->getPosteriorByIndex(index));
00876 }
00877 
00878 inline const float* RandomizedTree::getPosteriorByIndex(int index) const
00879 {
00880   return posteriors_[index];
00881 }
00882 
00883 inline uchar* RandomizedTree::getPosteriorByIndex2(int index)
00884 {
00885   return const_cast<uchar*>(const_cast<const RandomizedTree*>(this)->getPosteriorByIndex2(index));
00886 }
00887 
00888 inline const uchar* RandomizedTree::getPosteriorByIndex2(int index) const
00889 {
00890   return posteriors2_[index];
00891 }
00892 
00893 struct CV_EXPORTS RTreeNode
00894 {
00895   short offset1, offset2;
00896 
00897   RTreeNode() {}
00898   RTreeNode(uchar x1, uchar y1, uchar x2, uchar y2)
00899     : offset1(y1*RandomizedTree::PATCH_SIZE + x1),
00900       offset2(y2*RandomizedTree::PATCH_SIZE + x2)
00901   {}
00902 
00904   inline bool operator() (uchar* patch_data) const
00905   {
00906     return patch_data[offset1] > patch_data[offset2];
00907   }
00908 };
00909 
00910 class CV_EXPORTS RTreeClassifier
00911 {
00912 public:
00913   static const int DEFAULT_TREES = 48;
00914   static const size_t DEFAULT_NUM_QUANT_BITS = 4;
00915 
00916   RTreeClassifier();
00917   void train(std::vector<BaseKeypoint> const& base_set,
00918              RNG &rng,
00919              int num_trees = RTreeClassifier::DEFAULT_TREES,
00920              int depth = RandomizedTree::DEFAULT_DEPTH,
00921              int views = RandomizedTree::DEFAULT_VIEWS,
00922              size_t reduced_num_dim = RandomizedTree::DEFAULT_REDUCED_NUM_DIM,
00923              int num_quant_bits = DEFAULT_NUM_QUANT_BITS);
00924   void train(std::vector<BaseKeypoint> const& base_set,
00925              RNG &rng,
00926              PatchGenerator &make_patch,
00927              int num_trees = RTreeClassifier::DEFAULT_TREES,
00928              int depth = RandomizedTree::DEFAULT_DEPTH,
00929              int views = RandomizedTree::DEFAULT_VIEWS,
00930              size_t reduced_num_dim = RandomizedTree::DEFAULT_REDUCED_NUM_DIM,
00931              int num_quant_bits = DEFAULT_NUM_QUANT_BITS);
00932 
00933   // sig must point to a memory block of at least classes()*sizeof(float|uchar) bytes
00934   void getSignature(IplImage *patch, uchar *sig) const;
00935   void getSignature(IplImage *patch, float *sig) const;
00936   void getSparseSignature(IplImage *patch, float *sig, float thresh) const;
00937   // TODO: deprecated in favor of getSignature overload, remove
00938   void getFloatSignature(IplImage *patch, float *sig) const { getSignature(patch, sig); }
00939 
00940   static int countNonZeroElements(float *vec, int n, double tol=1e-10);
00941   static inline void safeSignatureAlloc(uchar **sig, int num_sig=1, int sig_len=176);
00942   static inline uchar* safeSignatureAlloc(int num_sig=1, int sig_len=176);
00943 
00944   inline int classes() const { return classes_; }
00945   inline int original_num_classes() const { return original_num_classes_; }
00946 
00947   void setQuantization(int num_quant_bits);
00948   void discardFloatPosteriors();
00949 
00950   void read(const char* file_name);
00951   void read(std::istream &is);
00952   void write(const char* file_name) const;
00953   void write(std::ostream &os) const;
00954 
00955   // experimental and debug
00956   void saveAllFloatPosteriors(std::string file_url);
00957   void saveAllBytePosteriors(std::string file_url);
00958   void setFloatPosteriorsFromTextfile_176(std::string url);
00959   float countZeroElements();
00960 
00961   std::vector<RandomizedTree> trees_;
00962 
00963 private:
00964   int classes_;
00965   int num_quant_bits_;
00966   mutable uchar **posteriors_;
00967   mutable unsigned short *ptemp_;
00968   int original_num_classes_;
00969   bool keep_floats_;
00970 };
00971 
00972 /****************************************************************************************\
00973 *                                     One-Way Descriptor                                 *
00974 \****************************************************************************************/
00975 
00976 class CV_EXPORTS OneWayDescriptor
00977 {
00978 public:
00979     OneWayDescriptor();
00980     ~OneWayDescriptor();
00981 
00982     // allocates memory for given descriptor parameters
00983     void Allocate(int pose_count, CvSize size, int nChannels);
00984 
00985     // GenerateSamples: generates affine transformed patches with averaging them over small transformation variations.
00986     // If external poses and transforms were specified, uses them instead of generating random ones
00987     // - pose_count: the number of poses to be generated
00988     // - frontal: the input patch (can be a roi in a larger image)
00989     // - norm: if nonzero, normalizes the output patch so that the sum of pixel intensities is 1
00990     void GenerateSamples(int pose_count, IplImage* frontal, int norm = 0);
00991 
00992     // GenerateSamplesFast: generates affine transformed patches with averaging them over small transformation variations.
00993     // Uses precalculated transformed pca components.
00994     // - frontal: the input patch (can be a roi in a larger image)
00995     // - pca_hr_avg: pca average vector
00996     // - pca_hr_eigenvectors: pca eigenvectors
00997     // - pca_descriptors: an array of precomputed descriptors of pca components containing their affine transformations
00998     //   pca_descriptors[0] corresponds to the average, pca_descriptors[1]-pca_descriptors[pca_dim] correspond to eigenvectors
00999     void GenerateSamplesFast(IplImage* frontal, CvMat* pca_hr_avg,
01000                              CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors);
01001 
01002     // sets the poses and corresponding transforms
01003     void SetTransforms(CvAffinePose* poses, CvMat** transforms);
01004 
01005     // Initialize: builds a descriptor.
01006     // - pose_count: the number of poses to build. If poses were set externally, uses them rather than generating random ones
01007     // - frontal: input patch. Can be a roi in a larger image
01008     // - feature_name: the feature name to be associated with the descriptor
01009     // - norm: if 1, the affine transformed patches are normalized so that their sum is 1
01010     void Initialize(int pose_count, IplImage* frontal, const char* feature_name = 0, int norm = 0);
01011 
01012     // InitializeFast: builds a descriptor using precomputed descriptors of pca components
01013     // - pose_count: the number of poses to build
01014     // - frontal: input patch. Can be a roi in a larger image
01015     // - feature_name: the feature name to be associated with the descriptor
01016     // - pca_hr_avg: average vector for PCA
01017     // - pca_hr_eigenvectors: PCA eigenvectors (one vector per row)
01018     // - pca_descriptors: precomputed descriptors of PCA components, the first descriptor for the average vector
01019     // followed by the descriptors for eigenvectors
01020     void InitializeFast(int pose_count, IplImage* frontal, const char* feature_name,
01021                         CvMat* pca_hr_avg, CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors);
01022 
01023     // ProjectPCASample: unwarps an image patch into a vector and projects it into PCA space
01024     // - patch: input image patch
01025     // - avg: PCA average vector
01026     // - eigenvectors: PCA eigenvectors, one per row
01027     // - pca_coeffs: output PCA coefficients
01028     void ProjectPCASample(IplImage* patch, CvMat* avg, CvMat* eigenvectors, CvMat* pca_coeffs) const;
01029 
01030     // InitializePCACoeffs: projects all warped patches into PCA space
01031     // - avg: PCA average vector
01032     // - eigenvectors: PCA eigenvectors, one per row
01033     void InitializePCACoeffs(CvMat* avg, CvMat* eigenvectors);
01034 
01035     // EstimatePose: finds the closest match between an input patch and a set of patches with different poses
01036     // - patch: input image patch
01037     // - pose_idx: the output index of the closest pose
01038     // - distance: the distance to the closest pose (L2 distance)
01039     void EstimatePose(IplImage* patch, int& pose_idx, float& distance) const;
01040 
01041     // EstimatePosePCA: finds the closest match between an input patch and a set of patches with different poses.
01042     // The distance between patches is computed in PCA space
01043     // - patch: input image patch
01044     // - pose_idx: the output index of the closest pose
01045     // - distance: distance to the closest pose (L2 distance in PCA space)
01046     // - avg: PCA average vector. If 0, matching without PCA is used
01047     // - eigenvectors: PCA eigenvectors, one per row
01048     void EstimatePosePCA(CvArr* patch, int& pose_idx, float& distance, CvMat* avg, CvMat* eigenvalues) const;
01049 
01050     // GetPatchSize: returns the size of each image patch after warping (2 times smaller than the input patch)
01051     CvSize GetPatchSize() const
01052     {
01053         return m_patch_size;
01054     }
01055 
01056     // GetInputPatchSize: returns the required size of the patch that the descriptor is built from
01057     // (2 time larger than the patch after warping)
01058     CvSize GetInputPatchSize() const
01059     {
01060         return cvSize(m_patch_size.width*2, m_patch_size.height*2);
01061     }
01062 
01063     // GetPatch: returns a patch corresponding to specified pose index
01064     // - index: pose index
01065     // - return value: the patch corresponding to specified pose index
01066     IplImage* GetPatch(int index);
01067 
01068     // GetPose: returns a pose corresponding to specified pose index
01069     // - index: pose index
01070     // - return value: the pose corresponding to specified pose index
01071     CvAffinePose GetPose(int index) const;
01072 
01073     // Save: saves all patches with different poses to a specified path
01074     void Save(const char* path);
01075 
01076     // ReadByName: reads a descriptor from a file storage
01077     // - fs: file storage
01078     // - parent: parent node
01079     // - name: node name
01080     // - return value: 1 if succeeded, 0 otherwise
01081     int ReadByName(CvFileStorage* fs, CvFileNode* parent, const char* name);
01082 
01083     // ReadByName: reads a descriptor from a file node
01084     // - parent: parent node
01085     // - name: node name
01086     // - return value: 1 if succeeded, 0 otherwise
01087     int ReadByName(const FileNode &parent, const char* name);
01088 
01089     // Write: writes a descriptor into a file storage
01090     // - fs: file storage
01091     // - name: node name
01092     void Write(CvFileStorage* fs, const char* name);
01093 
01094     // GetFeatureName: returns a name corresponding to a feature
01095     const char* GetFeatureName() const;
01096 
01097     // GetCenter: returns the center of the feature
01098     CvPoint GetCenter() const;
01099 
01100     void SetPCADimHigh(int pca_dim_high) {m_pca_dim_high = pca_dim_high;};
01101     void SetPCADimLow(int pca_dim_low) {m_pca_dim_low = pca_dim_low;};
01102 
01103     int GetPCADimLow() const;
01104     int GetPCADimHigh() const;
01105 
01106     CvMat** GetPCACoeffs() const {return m_pca_coeffs;}
01107 
01108 protected:
01109     int m_pose_count; // the number of poses
01110     CvSize m_patch_size; // size of each image
01111     IplImage** m_samples; // an array of length m_pose_count containing the patch in different poses
01112     IplImage* m_input_patch;
01113     IplImage* m_train_patch;
01114     CvMat** m_pca_coeffs; // an array of length m_pose_count containing pca decomposition of the patch in different poses
01115     CvAffinePose* m_affine_poses; // an array of poses
01116     CvMat** m_transforms; // an array of affine transforms corresponding to poses
01117 
01118     string m_feature_name; // the name of the feature associated with the descriptor
01119     CvPoint m_center; // the coordinates of the feature (the center of the input image ROI)
01120 
01121     int m_pca_dim_high; // the number of descriptor pca components to use for generating affine poses
01122     int m_pca_dim_low; // the number of pca components to use for comparison
01123 };
01124 
01125 
01126 // OneWayDescriptorBase: encapsulates functionality for training/loading a set of one way descriptors
01127 // and finding the nearest closest descriptor to an input feature
01128 class CV_EXPORTS OneWayDescriptorBase
01129 {
01130 public:
01131 
01132     // creates an instance of OneWayDescriptor from a set of training files
01133     // - patch_size: size of the input (large) patch
01134     // - pose_count: the number of poses to generate for each descriptor
01135     // - train_path: path to training files
01136     // - pca_config: the name of the file that contains PCA for small patches (2 times smaller
01137     // than patch_size each dimension
01138     // - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size)
01139     // - pca_desc_config: the name of the file that contains descriptors of PCA components
01140     OneWayDescriptorBase(CvSize patch_size, int pose_count, const char* train_path = 0, const char* pca_config = 0,
01141                          const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1,
01142                          int pca_dim_high = 100, int pca_dim_low = 100);
01143 
01144     OneWayDescriptorBase(CvSize patch_size, int pose_count, const string &pca_filename, const string &train_path = string(), const string &images_list = string(),
01145                          float _scale_min = 0.7f, float _scale_max=1.5f, float _scale_step=1.2f, int pyr_levels = 1,
01146                          int pca_dim_high = 100, int pca_dim_low = 100);
01147 
01148 
01149     virtual ~OneWayDescriptorBase();
01150     void clear ();
01151 
01152 
01153     // Allocate: allocates memory for a given number of descriptors
01154     void Allocate(int train_feature_count);
01155 
01156     // AllocatePCADescriptors: allocates memory for pca descriptors
01157     void AllocatePCADescriptors();
01158 
01159     // returns patch size
01160     CvSize GetPatchSize() const {return m_patch_size;};
01161     // returns the number of poses for each descriptor
01162     int GetPoseCount() const {return m_pose_count;};
01163 
01164     // returns the number of pyramid levels
01165     int GetPyrLevels() const {return m_pyr_levels;};
01166 
01167     // returns the number of descriptors
01168     int GetDescriptorCount() const {return m_train_feature_count;};
01169 
01170     // CreateDescriptorsFromImage: creates descriptors for each of the input features
01171     // - src: input image
01172     // - features: input features
01173     // - pyr_levels: the number of pyramid levels
01174     void CreateDescriptorsFromImage(IplImage* src, const std::vector<cv::KeyPoint>& features);
01175 
01176     // CreatePCADescriptors: generates descriptors for PCA components, needed for fast generation of feature descriptors
01177     void CreatePCADescriptors();
01178 
01179     // returns a feature descriptor by feature index
01180     const OneWayDescriptor* GetDescriptor(int desc_idx) const {return &m_descriptors[desc_idx];};
01181 
01182     // FindDescriptor: finds the closest descriptor
01183     // - patch: input image patch
01184     // - desc_idx: output index of the closest descriptor to the input patch
01185     // - pose_idx: output index of the closest pose of the closest descriptor to the input patch
01186     // - distance: distance from the input patch to the closest feature pose
01187     // - _scales: scales of the input patch for each descriptor
01188     // - scale_ranges: input scales variation (float[2])
01189     void FindDescriptor(IplImage* patch, int& desc_idx, int& pose_idx, float& distance, float* _scale = 0, float* scale_ranges = 0) const;
01190 
01191     // - patch: input image patch
01192     // - n: number of the closest indexes
01193     // - desc_idxs: output indexes of the closest descriptor to the input patch (n)
01194     // - pose_idx: output indexes of the closest pose of the closest descriptor to the input patch (n)
01195     // - distances: distance from the input patch to the closest feature pose (n)
01196     // - _scales: scales of the input patch
01197     // - scale_ranges: input scales variation (float[2])
01198     void FindDescriptor(IplImage* patch, int n, std::vector<int>& desc_idxs, std::vector<int>& pose_idxs,
01199                         std::vector<float>& distances, std::vector<float>& _scales, float* scale_ranges = 0) const;
01200 
01201     // FindDescriptor: finds the closest descriptor
01202     // - src: input image
01203     // - pt: center of the feature
01204     // - desc_idx: output index of the closest descriptor to the input patch
01205     // - pose_idx: output index of the closest pose of the closest descriptor to the input patch
01206     // - distance: distance from the input patch to the closest feature pose
01207     void FindDescriptor(IplImage* src, cv::Point2f pt, int& desc_idx, int& pose_idx, float& distance) const;
01208 
01209     // InitializePoses: generates random poses
01210     void InitializePoses();
01211 
01212     // InitializeTransformsFromPoses: generates 2x3 affine matrices from poses (initializes m_transforms)
01213     void InitializeTransformsFromPoses();
01214 
01215     // InitializePoseTransforms: subsequently calls InitializePoses and InitializeTransformsFromPoses
01216     void InitializePoseTransforms();
01217 
01218     // InitializeDescriptor: initializes a descriptor
01219     // - desc_idx: descriptor index
01220     // - train_image: image patch (ROI is supported)
01221     // - feature_label: feature textual label
01222     void InitializeDescriptor(int desc_idx, IplImage* train_image, const char* feature_label);
01223 
01224     void InitializeDescriptor(int desc_idx, IplImage* train_image, const cv::KeyPoint& keypoint, const char* feature_label);
01225 
01226     // InitializeDescriptors: load features from an image and create descriptors for each of them
01227     void InitializeDescriptors(IplImage* train_image, const vector<cv::KeyPoint>& features,
01228                                const char* feature_label = "", int desc_start_idx = 0);
01229 
01230     // Write: writes this object to a file storage
01231     // - fs: output filestorage
01232     void Write (FileStorage &fs) const;
01233     
01234     // Read: reads OneWayDescriptorBase object from a file node
01235     // - fn: input file node    
01236     void Read (const FileNode &fn);
01237 
01238     // LoadPCADescriptors: loads PCA descriptors from a file
01239     // - filename: input filename
01240     int LoadPCADescriptors(const char* filename);
01241 
01242     // LoadPCADescriptors: loads PCA descriptors from a file node
01243     // - fn: input file node
01244     int LoadPCADescriptors(const FileNode &fn);
01245 
01246     // SavePCADescriptors: saves PCA descriptors to a file
01247     // - filename: output filename
01248     void SavePCADescriptors(const char* filename);
01249 
01250     // SavePCADescriptors: saves PCA descriptors to a file storage
01251     // - fs: output file storage
01252     void SavePCADescriptors(CvFileStorage* fs) const;
01253 
01254     // GeneratePCA: calculate and save PCA components and descriptors
01255     // - img_path: path to training PCA images directory
01256     // - images_list: filename with filenames of training PCA images
01257     void GeneratePCA(const char* img_path, const char* images_list, int pose_count=500);
01258 
01259     // SetPCAHigh: sets the high resolution pca matrices (copied to internal structures)
01260     void SetPCAHigh(CvMat* avg, CvMat* eigenvectors);
01261 
01262     // SetPCALow: sets the low resolution pca matrices (copied to internal structures)
01263     void SetPCALow(CvMat* avg, CvMat* eigenvectors);
01264 
01265     int GetLowPCA(CvMat** avg, CvMat** eigenvectors)
01266     {
01267         *avg = m_pca_avg;
01268         *eigenvectors = m_pca_eigenvectors;
01269         return m_pca_dim_low;
01270     };
01271 
01272     int GetPCADimLow() const {return m_pca_dim_low;};
01273     int GetPCADimHigh() const {return m_pca_dim_high;};
01274 
01275     void ConvertDescriptorsArrayToTree(); // Converting pca_descriptors array to KD tree
01276 
01277     // GetPCAFilename: get default PCA filename
01278     static string GetPCAFilename () { return "pca.yml"; }
01279 
01280     virtual bool empty() const { return m_train_feature_count <= 0 ? true : false; }
01281 
01282 protected:
01283     CvSize m_patch_size; // patch size
01284     int m_pose_count; // the number of poses for each descriptor
01285     int m_train_feature_count; // the number of the training features
01286     OneWayDescriptor* m_descriptors; // array of train feature descriptors
01287     CvMat* m_pca_avg; // PCA average Vector for small patches
01288     CvMat* m_pca_eigenvectors; // PCA eigenvectors for small patches
01289     CvMat* m_pca_hr_avg; // PCA average Vector for large patches
01290     CvMat* m_pca_hr_eigenvectors; // PCA eigenvectors for large patches
01291     OneWayDescriptor* m_pca_descriptors; // an array of PCA descriptors
01292 
01293     cv::flann::Index* m_pca_descriptors_tree;
01294     CvMat* m_pca_descriptors_matrix;
01295 
01296     CvAffinePose* m_poses; // array of poses
01297     CvMat** m_transforms; // array of affine transformations corresponding to poses
01298 
01299     int m_pca_dim_high;
01300     int m_pca_dim_low;
01301 
01302     int m_pyr_levels;
01303     float scale_min;
01304     float scale_max;
01305     float scale_step;
01306 
01307     // SavePCAall: saves PCA components and descriptors to a file storage
01308     // - fs: output file storage
01309     void SavePCAall (FileStorage &fs) const;
01310 
01311     // LoadPCAall: loads PCA components and descriptors from a file node
01312     // - fn: input file node
01313     void LoadPCAall (const FileNode &fn);
01314 };
01315 
01316 class CV_EXPORTS OneWayDescriptorObject : public OneWayDescriptorBase
01317 {
01318 public:
01319     // creates an instance of OneWayDescriptorObject from a set of training files
01320     // - patch_size: size of the input (large) patch
01321     // - pose_count: the number of poses to generate for each descriptor
01322     // - train_path: path to training files
01323     // - pca_config: the name of the file that contains PCA for small patches (2 times smaller
01324     // than patch_size each dimension
01325     // - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size)
01326     // - pca_desc_config: the name of the file that contains descriptors of PCA components
01327     OneWayDescriptorObject(CvSize patch_size, int pose_count, const char* train_path, const char* pca_config,
01328                            const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 1);
01329 
01330     OneWayDescriptorObject(CvSize patch_size, int pose_count, const string &pca_filename,
01331                            const string &train_path = string (), const string &images_list = string (),
01332                            float _scale_min = 0.7f, float _scale_max=1.5f, float _scale_step=1.2f, int pyr_levels = 1);
01333 
01334 
01335     virtual ~OneWayDescriptorObject();
01336 
01337     // Allocate: allocates memory for a given number of features
01338     // - train_feature_count: the total number of features
01339     // - object_feature_count: the number of features extracted from the object
01340     void Allocate(int train_feature_count, int object_feature_count);
01341 
01342 
01343     void SetLabeledFeatures(const vector<cv::KeyPoint>& features) {m_train_features = features;};
01344     vector<cv::KeyPoint>& GetLabeledFeatures() {return m_train_features;};
01345     const vector<cv::KeyPoint>& GetLabeledFeatures() const {return m_train_features;};
01346     vector<cv::KeyPoint> _GetLabeledFeatures() const;
01347 
01348     // IsDescriptorObject: returns 1 if descriptor with specified index is positive, otherwise 0
01349     int IsDescriptorObject(int desc_idx) const;
01350 
01351     // MatchPointToPart: returns the part number of a feature if it matches one of the object parts, otherwise -1
01352     int MatchPointToPart(CvPoint pt) const;
01353 
01354     // GetDescriptorPart: returns the part number of the feature corresponding to a specified descriptor
01355     // - desc_idx: descriptor index
01356     int GetDescriptorPart(int desc_idx) const;
01357 
01358 
01359     void InitializeObjectDescriptors(IplImage* train_image, const vector<cv::KeyPoint>& features,
01360                                      const char* feature_label, int desc_start_idx = 0, float scale = 1.0f,
01361                                      int is_background = 0);
01362 
01363     // GetObjectFeatureCount: returns the number of object features
01364     int GetObjectFeatureCount() const {return m_object_feature_count;};
01365 
01366 protected:
01367     int* m_part_id; // contains part id for each of object descriptors
01368     vector<cv::KeyPoint> m_train_features; // train features
01369     int m_object_feature_count; // the number of the positive features
01370 
01371 };
01372 
01373 
01374 /****************************************************************************************\
01375 *                                    FeatureDetector                                     *
01376 \****************************************************************************************/
01377 
01378 /*
01379  * Abstract base class for 2D image feature detectors.
01380  */
01381 class CV_EXPORTS FeatureDetector
01382 {
01383 public:
01384     virtual ~FeatureDetector();
01385     
01386     /*
01387      * Detect keypoints in an image.
01388      * image        The image.
01389      * keypoints    The detected keypoints.
01390      * mask         Mask specifying where to look for keypoints (optional). Must be a char
01391      *              matrix with non-zero values in the region of interest.
01392      */
01393     void detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01394     
01395     /*
01396      * Detect keypoints in an image set.
01397      * images       Image collection.
01398      * keypoints    Collection of keypoints detected in an input images. keypoints[i] is a set of keypoints detected in an images[i].
01399      * masks        Masks for image set. masks[i] is a mask for images[i].
01400      */
01401     void detect( const vector<Mat>& images, vector<vector<KeyPoint> >& keypoints, const vector<Mat>& masks=vector<Mat>() ) const;
01402 
01403     // Read detector object from a file node.
01404     virtual void read( const FileNode& );
01405     // Read detector object from a file node.
01406     virtual void write( FileStorage& ) const;
01407 
01408     // Return true if detector object is empty
01409     virtual bool empty() const;
01410 
01411     // Create feature detector by detector name.
01412     static Ptr<FeatureDetector> create( const string& detectorType );
01413 
01414 protected:
01415     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const = 0;
01416 
01417     /*
01418      * Remove keypoints that are not in the mask.
01419      * Helper function, useful when wrapping a library call for keypoint detection that
01420      * does not support a mask argument.
01421      */
01422     static void removeInvalidPoints( const Mat& mask, vector<KeyPoint>& keypoints );
01423 };
01424 
01425 class CV_EXPORTS FastFeatureDetector : public FeatureDetector
01426 {
01427 public:
01428     FastFeatureDetector( int threshold=10, bool nonmaxSuppression=true );
01429     virtual void read( const FileNode& fn );
01430     virtual void write( FileStorage& fs ) const;
01431 
01432 protected:
01433     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01434 
01435     int threshold;
01436     bool nonmaxSuppression;
01437 };
01438 
01439 
01440 class CV_EXPORTS GoodFeaturesToTrackDetector : public FeatureDetector
01441 {
01442 public:
01443     class CV_EXPORTS Params
01444     {
01445     public:
01446         Params( int maxCorners=1000, double qualityLevel=0.01, double minDistance=1.,
01447                 int blockSize=3, bool useHarrisDetector=false, double k=0.04 );
01448         void read( const FileNode& fn );
01449         void write( FileStorage& fs ) const;
01450 
01451         int maxCorners;
01452         double qualityLevel;
01453         double minDistance;
01454         int blockSize;
01455         bool useHarrisDetector;
01456         double k;
01457     };
01458 
01459     GoodFeaturesToTrackDetector( const GoodFeaturesToTrackDetector::Params& params=GoodFeaturesToTrackDetector::Params() );
01460     GoodFeaturesToTrackDetector( int maxCorners, double qualityLevel, double minDistance,
01461                                  int blockSize=3, bool useHarrisDetector=false, double k=0.04 );
01462     virtual void read( const FileNode& fn );
01463     virtual void write( FileStorage& fs ) const;
01464 
01465 protected:
01466     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01467 
01468     Params params;
01469 };
01470 
01471 class CV_EXPORTS MserFeatureDetector : public FeatureDetector
01472 {
01473 public:
01474     MserFeatureDetector( CvMSERParams params=cvMSERParams() );
01475     MserFeatureDetector( int delta, int minArea, int maxArea, double maxVariation, double minDiversity,
01476                          int maxEvolution, double areaThreshold, double minMargin, int edgeBlurSize );
01477     virtual void read( const FileNode& fn );
01478     virtual void write( FileStorage& fs ) const;
01479 
01480 protected:
01481     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01482 
01483     MSER mser;
01484 };
01485 
01486 class CV_EXPORTS StarFeatureDetector : public FeatureDetector
01487 {
01488 public:
01489     StarFeatureDetector( const CvStarDetectorParams& params=cvStarDetectorParams() );
01490     StarFeatureDetector( int maxSize, int responseThreshold=30, int lineThresholdProjected = 10,
01491                          int lineThresholdBinarized=8, int suppressNonmaxSize=5 );
01492     virtual void read( const FileNode& fn );
01493     virtual void write( FileStorage& fs ) const;
01494 
01495 protected:
01496     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01497 
01498     StarDetector star;
01499 };
01500 
01501 class CV_EXPORTS SiftFeatureDetector : public FeatureDetector
01502 {
01503 public:
01504     SiftFeatureDetector( const SIFT::DetectorParams& detectorParams=SIFT::DetectorParams(),
01505                          const SIFT::CommonParams& commonParams=SIFT::CommonParams() );
01506     SiftFeatureDetector( double threshold, double edgeThreshold,
01507                          int nOctaves=SIFT::CommonParams::DEFAULT_NOCTAVES,
01508                          int nOctaveLayers=SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS,
01509                          int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
01510                          int angleMode=SIFT::CommonParams::FIRST_ANGLE );
01511     virtual void read( const FileNode& fn );
01512     virtual void write( FileStorage& fs ) const;
01513 
01514 protected:
01515     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01516 
01517     SIFT sift;
01518 };
01519 
01520 class CV_EXPORTS SurfFeatureDetector : public FeatureDetector
01521 {
01522 public:
01523     SurfFeatureDetector( double hessianThreshold=400., int octaves=3, int octaveLayers=4, bool upright=false );
01524     virtual void read( const FileNode& fn );
01525     virtual void write( FileStorage& fs ) const;
01526 
01527 protected:
01528     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01529 
01530     SURF surf;
01531 };
01532 
01536 class CV_EXPORTS OrbFeatureDetector : public cv::FeatureDetector
01537 {
01538 public:
01543   OrbFeatureDetector(size_t n_features = 700, ORB::CommonParams params = ORB::CommonParams());
01544 
01545   virtual void read(const cv::FileNode&);
01546   virtual void write(cv::FileStorage&) const;
01547 
01548 protected:
01549   virtual void
01550   detectImpl(const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask = cv::Mat()) const;
01551 private:
01553   mutable ORB orb_;
01555   ORB::CommonParams params_;
01557   unsigned int n_features_;
01558 };
01559 
01560 class CV_EXPORTS SimpleBlobDetector : public cv::FeatureDetector
01561 {
01562 public:
01563   struct CV_EXPORTS Params
01564   {
01565       Params();
01566       float thresholdStep;
01567       float minThreshold;
01568       float maxThreshold;
01569       size_t minRepeatability;
01570       float minDistBetweenBlobs;
01571 
01572       bool filterByColor;
01573       uchar blobColor;
01574 
01575       bool filterByArea;
01576       float minArea, maxArea;
01577 
01578       bool filterByCircularity;
01579       float minCircularity, maxCircularity;
01580 
01581       bool filterByInertia;
01582       float minInertiaRatio, maxInertiaRatio;
01583 
01584       bool filterByConvexity;
01585       float minConvexity, maxConvexity;
01586   };
01587 
01588   SimpleBlobDetector(const SimpleBlobDetector::Params &parameters = SimpleBlobDetector::Params());
01589 
01590 protected:
01591   struct CV_EXPORTS Center
01592   {
01593       Point2d location;
01594       double radius;
01595       double confidence;
01596   };
01597 
01598   virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01599   virtual void findBlobs(const cv::Mat &image, const cv::Mat &binaryImage, std::vector<Center> &centers) const;
01600 
01601   Params params;
01602 };
01603 
01604 class CV_EXPORTS DenseFeatureDetector : public FeatureDetector
01605 {
01606 public:
01607     class CV_EXPORTS Params
01608     {
01609     public:
01610         Params( float initFeatureScale=1.f, int featureScaleLevels=1, float featureScaleMul=0.1f,
01611                 int initXyStep=6, int initImgBound=0, bool varyXyStepWithScale=true, bool varyImgBoundWithScale=false );
01612         float initFeatureScale;
01613         int featureScaleLevels;
01614         float featureScaleMul;
01615 
01616         int initXyStep;
01617         int initImgBound;
01618 
01619         bool varyXyStepWithScale;
01620         bool varyImgBoundWithScale;
01621     };
01622 
01623     DenseFeatureDetector( const DenseFeatureDetector::Params& params=DenseFeatureDetector::Params() );
01624     
01625     // TODO implement read/write
01626 
01627 protected:
01628     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01629 
01630     Params params;
01631 };
01632 
01633 /*
01634  * Adapts a detector to partition the source image into a grid and detect
01635  * points in each cell.
01636  */
01637 class CV_EXPORTS GridAdaptedFeatureDetector : public FeatureDetector
01638 {
01639 public:
01640     /*
01641      * detector            Detector that will be adapted.
01642      * maxTotalKeypoints   Maximum count of keypoints detected on the image. Only the strongest keypoints
01643      *                      will be keeped.
01644      * gridRows            Grid rows count.
01645      * gridCols            Grid column count.
01646      */
01647     GridAdaptedFeatureDetector( const Ptr<FeatureDetector>& detector, int maxTotalKeypoints=1000,
01648                                 int gridRows=4, int gridCols=4 );
01649     
01650     // TODO implement read/write
01651     virtual bool empty() const;
01652 
01653 protected:
01654     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01655 
01656     Ptr<FeatureDetector> detector;
01657     int maxTotalKeypoints;
01658     int gridRows;
01659     int gridCols;
01660 };
01661 
01662 /*
01663  * Adapts a detector to detect points over multiple levels of a Gaussian
01664  * pyramid. Useful for detectors that are not inherently scaled.
01665  */
01666 class CV_EXPORTS PyramidAdaptedFeatureDetector : public FeatureDetector
01667 {
01668 public:
01669     // maxLevel - The 0-based index of the last pyramid layer
01670     PyramidAdaptedFeatureDetector( const Ptr<FeatureDetector>& detector, int maxLevel=2 );
01671     
01672     // TODO implement read/write
01673     virtual bool empty() const;
01674 
01675 protected:
01676     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01677 
01678     Ptr<FeatureDetector> detector;
01679     int maxLevel;
01680 };
01681 
01685 class CV_EXPORTS AdjusterAdapter: public FeatureDetector
01686 {
01687 public:   
01690     virtual ~AdjusterAdapter() {}
01695     virtual void tooFew(int min, int n_detected) = 0;
01700     virtual void tooMany(int max, int n_detected) = 0;
01704     virtual bool good() const = 0;
01705 
01706     virtual Ptr<AdjusterAdapter> clone() const = 0;
01707 
01708     static Ptr<AdjusterAdapter> create( const string& detectorType );
01709 };
01722 class CV_EXPORTS DynamicAdaptedFeatureDetector: public FeatureDetector
01723 {
01724 public:
01725 
01732     DynamicAdaptedFeatureDetector( const Ptr<AdjusterAdapter>& adjaster, int min_features=400, int max_features=500, int max_iters=5 );
01733 
01734     virtual bool empty() const;
01735 
01736 protected:
01737     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01738 
01739 private:
01740     DynamicAdaptedFeatureDetector& operator=(const DynamicAdaptedFeatureDetector&);
01741     DynamicAdaptedFeatureDetector(const DynamicAdaptedFeatureDetector&);
01742 
01743     int escape_iters_;
01744     int min_features_, max_features_;
01745     const Ptr<AdjusterAdapter> adjuster_;
01746 };
01747 
01751 class CV_EXPORTS FastAdjuster: public AdjusterAdapter
01752 {
01753 public:
01757     FastAdjuster(int init_thresh=20, bool nonmax=true, int min_thresh=1, int max_thresh=200);
01758 
01759     virtual void tooFew(int min, int n_detected);
01760     virtual void tooMany(int max, int n_detected);
01761     virtual bool good() const;
01762 
01763     virtual Ptr<AdjusterAdapter> clone() const;
01764 
01765 protected:
01766     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01767 
01768     int thresh_;
01769     bool nonmax_;
01770     int init_thresh_, min_thresh_, max_thresh_;
01771 };
01772 
01773 
01777 class CV_EXPORTS StarAdjuster: public AdjusterAdapter
01778 {
01779 public:
01780     StarAdjuster(double initial_thresh=30.0, double min_thresh=2., double max_thresh=200.);
01781 
01782     virtual void tooFew(int min, int n_detected);
01783     virtual void tooMany(int max, int n_detected);
01784     virtual bool good() const;
01785 
01786     virtual Ptr<AdjusterAdapter> clone() const;
01787 
01788 protected:
01789     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01790 
01791     double thresh_, init_thresh_, min_thresh_, max_thresh_;
01792     CvStarDetectorParams params_; //todo use these instead of thresh_
01793 };
01794 
01795 class CV_EXPORTS SurfAdjuster: public AdjusterAdapter
01796 {
01797 public:
01798     SurfAdjuster( double initial_thresh=400.f, double min_thresh=2, double max_thresh=1000 );
01799 
01800     virtual void tooFew(int min, int n_detected);
01801     virtual void tooMany(int max, int n_detected);
01802     virtual bool good() const;
01803 
01804     virtual Ptr<AdjusterAdapter> clone() const;
01805 
01806 protected:
01807     virtual void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;
01808 
01809     double thresh_, init_thresh_, min_thresh_, max_thresh_;
01810 };
01811 
01812 CV_EXPORTS Mat windowedMatchingMask( const vector<KeyPoint>& keypoints1, const vector<KeyPoint>& keypoints2,
01813                                      float maxDeltaX, float maxDeltaY );
01814 
01815 /****************************************************************************************\
01816 *                                 DescriptorExtractor                                    *
01817 \****************************************************************************************/
01818 
01819 /*
01820  * Abstract base class for computing descriptors for image keypoints.
01821  *
01822  * In this interface we assume a keypoint descriptor can be represented as a
01823  * dense, fixed-dimensional vector of some basic type. Most descriptors used
01824  * in practice follow this pattern, as it makes it very easy to compute
01825  * distances between descriptors. Therefore we represent a collection of
01826  * descriptors as a cv::Mat, where each row is one keypoint descriptor.
01827  */
01828 class CV_EXPORTS DescriptorExtractor
01829 {
01830 public:
01831     virtual ~DescriptorExtractor();
01832 
01833     /*
01834      * Compute the descriptors for a set of keypoints in an image.
01835      * image        The image.
01836      * keypoints    The input keypoints. Keypoints for which a descriptor cannot be computed are removed.
01837      * descriptors  Copmputed descriptors. Row i is the descriptor for keypoint i.
01838      */
01839     void compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
01840 
01841     /*
01842      * Compute the descriptors for a keypoints collection detected in image collection.
01843      * images       Image collection.
01844      * keypoints    Input keypoints collection. keypoints[i] is keypoints detected in images[i].
01845      *              Keypoints for which a descriptor cannot be computed are removed.
01846      * descriptors  Descriptor collection. descriptors[i] are descriptors computed for set keypoints[i].
01847      */
01848     void compute( const vector<Mat>& images, vector<vector<KeyPoint> >& keypoints, vector<Mat>& descriptors ) const;
01849 
01850     virtual void read( const FileNode& );
01851     virtual void write( FileStorage& ) const;
01852 
01853     virtual int descriptorSize() const = 0;
01854     virtual int descriptorType() const = 0;
01855 
01856     virtual bool empty() const;
01857 
01858     static Ptr<DescriptorExtractor> create( const string& descriptorExtractorType );
01859 
01860 protected:
01861     virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const = 0;
01862 
01863     /*
01864      * Remove keypoints within borderPixels of an image edge.
01865      */
01866     static void removeBorderKeypoints( vector<KeyPoint>& keypoints,
01867                                        Size imageSize, int borderSize );
01868 };
01869 
01870 /*
01871  * SiftDescriptorExtractor
01872  */
01873 class CV_EXPORTS SiftDescriptorExtractor : public DescriptorExtractor
01874 {
01875 public:
01876     SiftDescriptorExtractor( const SIFT::DescriptorParams& descriptorParams=SIFT::DescriptorParams(),
01877                              const SIFT::CommonParams& commonParams=SIFT::CommonParams() );
01878     SiftDescriptorExtractor( double magnification, bool isNormalize=true, bool recalculateAngles=true,
01879                              int nOctaves=SIFT::CommonParams::DEFAULT_NOCTAVES,
01880                              int nOctaveLayers=SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS,
01881                              int firstOctave=SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
01882                              int angleMode=SIFT::CommonParams::FIRST_ANGLE );
01883 
01884     virtual void read( const FileNode &fn );
01885     virtual void write( FileStorage &fs ) const;
01886 
01887     virtual int descriptorSize() const;
01888     virtual int descriptorType() const;
01889 
01890 protected:
01891     virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
01892     
01893     SIFT sift;
01894 };
01895 
01896 /*
01897  * SurfDescriptorExtractor
01898  */
01899 class CV_EXPORTS SurfDescriptorExtractor : public DescriptorExtractor
01900 {
01901 public:
01902     SurfDescriptorExtractor( int nOctaves=4, int nOctaveLayers=2, bool extended=false, bool upright=false );
01903 
01904     virtual void read( const FileNode &fn );
01905     virtual void write( FileStorage &fs ) const;
01906 
01907     virtual int descriptorSize() const;
01908     virtual int descriptorType() const;
01909 
01910 protected:
01911     virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
01912 
01913     SURF surf;
01914 };
01915 
01922 class OrbDescriptorExtractor : public cv::DescriptorExtractor
01923 {
01924 public:
01928   OrbDescriptorExtractor(ORB::CommonParams params = ORB::CommonParams());
01929 
01931   ~OrbDescriptorExtractor()
01932   {
01933   }
01934 
01935   virtual int descriptorSize() const;
01936   virtual int descriptorType() const;
01937 
01938   virtual void read(const cv::FileNode&);
01939   virtual void write(cv::FileStorage&) const;
01940 
01941 protected:
01942   void computeImpl(const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, cv::Mat& descriptors) const;
01943 private:
01945   mutable ORB orb_;
01947   ORB::CommonParams params_;
01948 };
01949 
01950 /*
01951  * CalonderDescriptorExtractor
01952  */
01953 template<typename T>
01954 class CV_EXPORTS CalonderDescriptorExtractor : public DescriptorExtractor
01955 {
01956 public:
01957     CalonderDescriptorExtractor( const string& classifierFile );
01958 
01959     virtual void read( const FileNode &fn );
01960     virtual void write( FileStorage &fs ) const;
01961 
01962     virtual int descriptorSize() const { return classifier_.classes(); }
01963     virtual int descriptorType() const { return DataType<T>::type; }
01964 
01965     virtual bool empty() const;
01966 
01967 protected:
01968     virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
01969 
01970     RTreeClassifier classifier_;
01971     static const int BORDER_SIZE = 16;
01972 };
01973 
01974 template<typename T>
01975 CalonderDescriptorExtractor<T>::CalonderDescriptorExtractor(const std::string& classifier_file)
01976 {
01977     classifier_.read( classifier_file.c_str() );
01978 }
01979 
01980 template<typename T>
01981 void CalonderDescriptorExtractor<T>::computeImpl( const cv::Mat& image,
01982                                               std::vector<cv::KeyPoint>& keypoints,
01983                                               cv::Mat& descriptors) const
01984 {
01985     // Cannot compute descriptors for keypoints on the image border.
01986     KeyPointsFilter::runByImageBorder(keypoints, image.size(), BORDER_SIZE);
01987 
01989     descriptors.create(keypoints.size(), classifier_.classes(), cv::DataType<T>::type);
01990 
01991     int patchSize = RandomizedTree::PATCH_SIZE;
01992     int offset = patchSize / 2;
01993     for (size_t i = 0; i < keypoints.size(); ++i)
01994     {
01995         cv::Point2f pt = keypoints[i].pt;
01996         IplImage ipl = image( Rect((int)(pt.x - offset), (int)(pt.y - offset), patchSize, patchSize) );
01997         classifier_.getSignature( &ipl, descriptors.ptr<T>(i));
01998     }
01999 }
02000 
02001 template<typename T>
02002 void CalonderDescriptorExtractor<T>::read( const FileNode& )
02003 {}
02004 
02005 template<typename T>
02006 void CalonderDescriptorExtractor<T>::write( FileStorage& ) const
02007 {}
02008 
02009 template<typename T>
02010 bool CalonderDescriptorExtractor<T>::empty() const
02011 {
02012     return classifier_.trees_.empty();
02013 }
02014 
02015 /*
02016  * OpponentColorDescriptorExtractor
02017  *
02018  * Adapts a descriptor extractor to compute descripors in Opponent Color Space
02019  * (refer to van de Sande et al., CGIV 2008 "Color Descriptors for Object Category Recognition").
02020  * Input RGB image is transformed in Opponent Color Space. Then unadapted descriptor extractor
02021  * (set in constructor) computes descriptors on each of the three channel and concatenate
02022  * them into a single color descriptor.
02023  */
02024 class CV_EXPORTS OpponentColorDescriptorExtractor : public DescriptorExtractor
02025 {
02026 public:
02027     OpponentColorDescriptorExtractor( const Ptr<DescriptorExtractor>& descriptorExtractor );
02028 
02029     virtual void read( const FileNode& );
02030     virtual void write( FileStorage& ) const;
02031 
02032     virtual int descriptorSize() const;
02033     virtual int descriptorType() const;
02034 
02035     virtual bool empty() const;
02036 
02037 protected:
02038     virtual void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const;
02039 
02040     Ptr<DescriptorExtractor> descriptorExtractor;
02041 };
02042 
02043 /*
02044  * BRIEF Descriptor
02045  */
02046 class CV_EXPORTS BriefDescriptorExtractor : public DescriptorExtractor
02047 {
02048 public:
02049     static const int PATCH_SIZE = 48;
02050     static const int KERNEL_SIZE = 9;
02051 
02052     // bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.
02053     BriefDescriptorExtractor( int bytes = 32 );
02054 
02055     virtual int descriptorSize() const;
02056     virtual int descriptorType() const;
02057 
02059 
02060 protected:
02061     virtual void computeImpl(const Mat& image, std::vector<KeyPoint>& keypoints, Mat& descriptors) const;
02062 
02063     typedef void(*PixelTestFn)(const Mat&, const std::vector<KeyPoint>&, Mat&);
02064 
02065     int bytes_;
02066     PixelTestFn test_fn_;
02067 };
02068 
02069 /****************************************************************************************\
02070 *                                          Distance                                      *
02071 \****************************************************************************************/
02072 template<typename T>
02073 struct CV_EXPORTS Accumulator
02074 {
02075     typedef T Type;
02076 };
02077 
02078 template<> struct Accumulator<unsigned char>  { typedef float Type; };
02079 template<> struct Accumulator<unsigned short> { typedef float Type; };
02080 template<> struct Accumulator<char>   { typedef float Type; };
02081 template<> struct Accumulator<short>  { typedef float Type; };
02082 
02083 /*
02084  * Squared Euclidean distance functor
02085  */
02086 template<class T>
02087 struct CV_EXPORTS L2
02088 {
02089     typedef T ValueType;
02090     typedef typename Accumulator<T>::Type ResultType;
02091 
02092     ResultType operator()( const T* a, const T* b, int size ) const
02093     {
02094         ResultType result = ResultType();
02095         for( int i = 0; i < size; i++ )
02096         {
02097             ResultType diff = (ResultType)(a[i] - b[i]);
02098             result += diff*diff;
02099         }
02100         return (ResultType)sqrt((double)result);
02101     }
02102 };
02103 
02104 /*
02105  * Manhattan distance (city block distance) functor
02106  */
02107 template<class T>
02108 struct CV_EXPORTS L1
02109 {
02110     typedef T ValueType;
02111     typedef typename Accumulator<T>::Type ResultType;
02112 
02113     ResultType operator()( const T* a, const T* b, int size ) const
02114     {
02115         ResultType result = ResultType();
02116         for( int i = 0; i < size; i++ )
02117         {
02118             ResultType diff = a[i] - b[i];
02119             result += (ResultType)fabs( diff );
02120         }
02121         return result;
02122     }
02123 };
02124 
02125 /*
02126  * Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor
02127  * bit count of A exclusive XOR'ed with B
02128  */
02129 struct CV_EXPORTS HammingLUT
02130 {
02131     typedef unsigned char ValueType;
02132     typedef int ResultType;
02133 
02136     ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const;
02137 
02143     static unsigned char byteBitsLookUp(unsigned char b);
02144 };
02145 
02146 
02150 struct CV_EXPORTS Hamming
02151 {
02152     typedef unsigned char ValueType;
02153 
02155     // in BruteForce if not
02156     typedef int ResultType;
02157 
02160     ResultType operator()(const unsigned char* a, const unsigned char* b, int size) const;
02161 };
02162 
02163 
02164 /****************************************************************************************\
02165 *                                      DMatch                                            *
02166 \****************************************************************************************/
02167 /*
02168  * Struct for matching: query descriptor index, train descriptor index, train image index and distance between descriptors.
02169  */
02170 struct CV_EXPORTS DMatch
02171 {
02172     DMatch() : queryIdx(-1), trainIdx(-1), imgIdx(-1), distance(std::numeric_limits<float>::max()) {}
02173     DMatch( int _queryIdx, int _trainIdx, float _distance ) :
02174             queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(-1), distance(_distance) {}
02175     DMatch( int _queryIdx, int _trainIdx, int _imgIdx, float _distance ) :
02176             queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(_imgIdx), distance(_distance) {}
02177 
02178     int queryIdx; // query descriptor index
02179     int trainIdx; // train descriptor index
02180     int imgIdx;   // train image index
02181 
02182     float distance;
02183 
02184     // less is better
02185     bool operator<( const DMatch &m ) const
02186     {
02187         return distance < m.distance;
02188     }
02189 };
02190 
02191 /****************************************************************************************\
02192 *                                  DescriptorMatcher                                     *
02193 \****************************************************************************************/
02194 /*
02195  * Abstract base class for matching two sets of descriptors.
02196  */
02197 class CV_EXPORTS DescriptorMatcher
02198 {
02199 public:
02200     virtual ~DescriptorMatcher();
02201 
02202     /*
02203      * Add descriptors to train descriptor collection.
02204      * descriptors      Descriptors to add. Each descriptors[i] is a descriptors set from one image.
02205      */
02206     virtual void add( const vector<Mat>& descriptors );
02207     /*
02208      * Get train descriptors collection.
02209      */
02210     const vector<Mat>& getTrainDescriptors() const;
02211     /*
02212      * Clear train descriptors collection.
02213      */
02214     virtual void clear();
02215 
02216     /*
02217      * Return true if there are not train descriptors in collection.
02218      */
02219     virtual bool empty() const;
02220     /*
02221      * Return true if the matcher supports mask in match methods.
02222      */
02223     virtual bool isMaskSupported() const = 0;
02224 
02225     /*
02226      * Train matcher (e.g. train flann index).
02227      * In all methods to match the method train() is run every time before matching.
02228      * Some descriptor matchers (e.g. BruteForceMatcher) have empty implementation
02229      * of this method, other matchers really train their inner structures
02230      * (e.g. FlannBasedMatcher trains flann::Index). So nonempty implementation
02231      * of train() should check the class object state and do traing/retraining
02232      * only if the state requires that (e.g. FlannBasedMatcher trains flann::Index
02233      * if it has not trained yet or if new descriptors have been added to the train
02234      * collection).
02235      */
02236     virtual void train();
02237     /*
02238      * Group of methods to match descriptors from image pair.
02239      * Method train() is run in this methods.
02240      */
02241     // Find one best match for each query descriptor (if mask is empty).
02242     void match( const Mat& queryDescriptors, const Mat& trainDescriptors,
02243                 vector<DMatch>& matches, const Mat& mask=Mat() ) const;
02244     // Find k best matches for each query descriptor (in increasing order of distances).
02245     // compactResult is used when mask is not empty. If compactResult is false matches
02246     // vector will have the same size as queryDescriptors rows. If compactResult is true
02247     // matches vector will not contain matches for fully masked out query descriptors.
02248     void knnMatch( const Mat& queryDescriptors, const Mat& trainDescriptors,
02249                    vector<vector<DMatch> >& matches, int k,
02250                    const Mat& mask=Mat(), bool compactResult=false ) const;
02251     // Find best matches for each query descriptor which have distance less than
02252     // maxDistance (in increasing order of distances).
02253     void radiusMatch( const Mat& queryDescriptors, const Mat& trainDescriptors,
02254                       vector<vector<DMatch> >& matches, float maxDistance,
02255                       const Mat& mask=Mat(), bool compactResult=false ) const;
02256     /*
02257      * Group of methods to match descriptors from one image to image set.
02258      * See description of similar methods for matching image pair above.
02259      */
02260     void match( const Mat& queryDescriptors, vector<DMatch>& matches,
02261                 const vector<Mat>& masks=vector<Mat>() );
02262     void knnMatch( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
02263            const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
02264     void radiusMatch( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
02265                    const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
02266 
02267     // Reads matcher object from a file node
02268     virtual void read( const FileNode& );
02269     // Writes matcher object to a file storage
02270     virtual void write( FileStorage& ) const;
02271 
02272     // Clone the matcher. If emptyTrainData is false the method create deep copy of the object, i.e. copies
02273     // both parameters and train data. If emptyTrainData is true the method create object copy with current parameters
02274     // but with empty train data.
02275     virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const = 0;
02276 
02277     static Ptr<DescriptorMatcher> create( const string& descriptorMatcherType );
02278 protected:
02279     /*
02280      * Class to work with descriptors from several images as with one merged matrix.
02281      * It is used e.g. in FlannBasedMatcher.
02282      */
02283     class CV_EXPORTS DescriptorCollection
02284     {
02285     public:
02286         DescriptorCollection();
02287         DescriptorCollection( const DescriptorCollection& collection );
02288         virtual ~DescriptorCollection();
02289 
02290         // Vector of matrices "descriptors" will be merged to one matrix "mergedDescriptors" here.
02291         void set( const vector<Mat>& descriptors );
02292         virtual void clear();
02293 
02294         const Mat& getDescriptors() const;
02295         const Mat getDescriptor( int imgIdx, int localDescIdx ) const;
02296         const Mat getDescriptor( int globalDescIdx ) const;
02297         void getLocalIdx( int globalDescIdx, int& imgIdx, int& localDescIdx ) const;
02298 
02299         int size() const;
02300 
02301     protected:
02302         Mat mergedDescriptors;
02303         vector<int> startIdxs;
02304     };
02305 
02306     // In fact the matching is implemented only by the following two methods. These methods suppose
02307     // that the class object has been trained already. Public match methods call these methods
02308     // after calling train().
02309     virtual void knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
02310            const vector<Mat>& masks=vector<Mat>(), bool compactResult=false ) = 0;
02311     virtual void radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
02312            const vector<Mat>& masks=vector<Mat>(), bool compactResult=false ) = 0;
02313 
02314     static bool isPossibleMatch( const Mat& mask, int queryIdx, int trainIdx );
02315     static bool isMaskedOut( const vector<Mat>& masks, int queryIdx );
02316 
02317     static Mat clone_op( Mat m ) { return m.clone(); }
02318     void checkMasks( const vector<Mat>& masks, int queryDescriptorsCount ) const;
02319 
02320     // Collection of descriptors from train images.
02321     vector<Mat> trainDescCollection;
02322 };
02323 
02324 /*
02325  * Brute-force descriptor matcher.
02326  *
02327  * For each descriptor in the first set, this matcher finds the closest
02328  * descriptor in the second set by trying each one.
02329  *
02330  * For efficiency, BruteForceMatcher is templated on the distance metric.
02331  * For float descriptors, a common choice would be cv::L2<float>.
02332  */
02333 template<class Distance>
02334 class CV_EXPORTS BruteForceMatcher : public DescriptorMatcher
02335 {
02336 public:
02337     BruteForceMatcher( Distance d = Distance() ) : distance(d) {}
02338     virtual ~BruteForceMatcher() {}
02339 
02340     virtual bool isMaskSupported() const { return true; }
02341 
02342     virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const;
02343 
02344 protected:
02345     virtual void knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
02346            const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
02347     virtual void radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
02348            const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
02349 
02350     Distance distance;
02351 
02352 private:
02353     /*
02354      * Next two methods are used to implement specialization.
02355      */
02356     static void commonKnnMatchImpl( BruteForceMatcher<Distance>& matcher,
02357                     const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
02358                     const vector<Mat>& masks, bool compactResult );
02359     static void commonRadiusMatchImpl( BruteForceMatcher<Distance>& matcher,
02360                     const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
02361                     const vector<Mat>& masks, bool compactResult );
02362 };
02363 
02364 template<class Distance>
02365 Ptr<DescriptorMatcher> BruteForceMatcher<Distance>::clone( bool emptyTrainData ) const
02366 {
02367     BruteForceMatcher* matcher = new BruteForceMatcher(distance);
02368     if( !emptyTrainData )
02369     {
02370         std::transform( trainDescCollection.begin(), trainDescCollection.end(),
02371                         matcher->trainDescCollection.begin(), clone_op );
02372     }
02373     return matcher;
02374 }
02375 
02376 template<class Distance>
02377 void BruteForceMatcher<Distance>::knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
02378                                                 const vector<Mat>& masks, bool compactResult )
02379 {
02380     commonKnnMatchImpl( *this, queryDescriptors, matches, k, masks, compactResult );
02381 }
02382 
02383 template<class Distance>
02384 void BruteForceMatcher<Distance>::radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches,
02385                                                    float maxDistance, const vector<Mat>& masks, bool compactResult )
02386 {
02387     commonRadiusMatchImpl( *this, queryDescriptors, matches, maxDistance, masks, compactResult );
02388 }
02389 
02390 template<class Distance>
02391 inline void BruteForceMatcher<Distance>::commonKnnMatchImpl( BruteForceMatcher<Distance>& matcher,
02392                           const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int knn,
02393                           const vector<Mat>& masks, bool compactResult )
02394  {
02395      typedef typename Distance::ValueType ValueType;
02396      typedef typename Distance::ResultType DistanceType;
02397      CV_DbgAssert( !queryDescriptors.empty() );
02398      CV_Assert( DataType<ValueType>::type == queryDescriptors.type() );
02399      
02400      int dimension = queryDescriptors.cols;
02401      matches.reserve(queryDescriptors.rows);
02402 
02403      size_t imgCount = matcher.trainDescCollection.size();
02404      vector<Mat> allDists( imgCount ); // distances between one query descriptor and all train descriptors
02405      for( size_t i = 0; i < imgCount; i++ )
02406         allDists[i] = Mat( 1, matcher.trainDescCollection[i].rows, DataType<DistanceType>::type );
02407 
02408      for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
02409      {
02410          if( matcher.isMaskedOut( masks, qIdx ) )
02411          {
02412              if( !compactResult ) // push empty vector
02413                  matches.push_back( vector<DMatch>() );
02414          }
02415          else
02416          {
02417              // 1. compute distances between i-th query descriptor and all train descriptors
02418              for( size_t iIdx = 0; iIdx < imgCount; iIdx++ )
02419              {
02420                  CV_Assert( DataType<ValueType>::type == matcher.trainDescCollection[iIdx].type() ||  matcher.trainDescCollection[iIdx].empty() );
02421                  CV_Assert( queryDescriptors.cols == matcher.trainDescCollection[iIdx].cols || 
02422                             matcher.trainDescCollection[iIdx].empty() );
02423 
02424                  const ValueType* d1 = (const ValueType*)(queryDescriptors.data + queryDescriptors.step*qIdx);
02425                  allDists[iIdx].setTo( Scalar::all(std::numeric_limits<DistanceType>::max()) );
02426                  for( int tIdx = 0; tIdx < matcher.trainDescCollection[iIdx].rows; tIdx++ )
02427                  {
02428                      if( masks.empty() || matcher.isPossibleMatch(masks[iIdx], qIdx, tIdx) )
02429                      {
02430                          const ValueType* d2 = (const ValueType*)(matcher.trainDescCollection[iIdx].data +
02431                                                                   matcher.trainDescCollection[iIdx].step*tIdx);
02432                          allDists[iIdx].at<DistanceType>(0, tIdx) = matcher.distance(d1, d2, dimension);
02433                      }
02434                  }
02435              }
02436 
02437              // 2. choose k nearest matches for query[i]
02438              matches.push_back( vector<DMatch>() );
02439              vector<vector<DMatch> >::reverse_iterator curMatches = matches.rbegin();
02440              for( int k = 0; k < knn; k++ )
02441              {
02442                  DMatch bestMatch;
02443                  bestMatch.distance = std::numeric_limits<float>::max();
02444                  for( size_t iIdx = 0; iIdx < imgCount; iIdx++ )
02445                  {
02446                      if( !allDists[iIdx].empty() )
02447                      {
02448                          double minVal;
02449                          Point minLoc;
02450                          minMaxLoc( allDists[iIdx], &minVal, 0, &minLoc, 0 );
02451                          if( minVal < bestMatch.distance )
02452                                  bestMatch = DMatch( qIdx, minLoc.x, (int)iIdx, (float)minVal );
02453                      }
02454                  }
02455                  if( bestMatch.trainIdx == -1 )
02456                      break;
02457 
02458                  allDists[bestMatch.imgIdx].at<DistanceType>(0, bestMatch.trainIdx) = std::numeric_limits<DistanceType>::max();
02459                  curMatches->push_back( bestMatch );
02460              }
02461              //TODO should already be sorted at this point?
02462              std::sort( curMatches->begin(), curMatches->end() );
02463          }
02464      }
02465 }
02466 
02467 template<class Distance>
02468 inline void BruteForceMatcher<Distance>::commonRadiusMatchImpl( BruteForceMatcher<Distance>& matcher,
02469                              const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
02470                              const vector<Mat>& masks, bool compactResult )
02471 {
02472     typedef typename Distance::ValueType ValueType;
02473     typedef typename Distance::ResultType DistanceType;
02474     CV_DbgAssert( !queryDescriptors.empty() );
02475     CV_Assert( DataType<ValueType>::type == queryDescriptors.type() );
02476     
02477     int dimension = queryDescriptors.cols;
02478     matches.reserve(queryDescriptors.rows);
02479 
02480     size_t imgCount = matcher.trainDescCollection.size();
02481     for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
02482     {
02483         if( matcher.isMaskedOut( masks, qIdx ) )
02484         {
02485             if( !compactResult ) // push empty vector
02486                 matches.push_back( vector<DMatch>() );
02487         }
02488         else
02489         {
02490             matches.push_back( vector<DMatch>() );
02491             vector<vector<DMatch> >::reverse_iterator curMatches = matches.rbegin();
02492             for( size_t iIdx = 0; iIdx < imgCount; iIdx++ )
02493             {
02494                 CV_Assert( DataType<ValueType>::type == matcher.trainDescCollection[iIdx].type() ||
02495                            matcher.trainDescCollection[iIdx].empty() );
02496                 CV_Assert( queryDescriptors.cols == matcher.trainDescCollection[iIdx].cols ||
02497                            matcher.trainDescCollection[iIdx].empty() );
02498 
02499                 const ValueType* d1 = (const ValueType*)(queryDescriptors.data + queryDescriptors.step*qIdx);
02500                 for( int tIdx = 0; tIdx < matcher.trainDescCollection[iIdx].rows; tIdx++ )
02501                 {
02502                     if( masks.empty() || matcher.isPossibleMatch(masks[iIdx], qIdx, tIdx) )
02503                     {
02504                         const ValueType* d2 = (const ValueType*)(matcher.trainDescCollection[iIdx].data +
02505                                                                  matcher.trainDescCollection[iIdx].step*tIdx);
02506                         DistanceType d = matcher.distance(d1, d2, dimension);
02507                         if( d < maxDistance )
02508                             curMatches->push_back( DMatch( qIdx, tIdx, (int)iIdx, (float)d ) );
02509                     }
02510                 }
02511             }
02512             std::sort( curMatches->begin(), curMatches->end() );
02513         }
02514     }
02515 }
02516 
02517 /*
02518  * BruteForceMatcher L2 specialization
02519  */
02520 template<>
02521 void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
02522                                                   const vector<Mat>& masks, bool compactResult );
02523 template<>
02524 void BruteForceMatcher<L2<float> >::radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches,
02525                                                      float maxDistance, const vector<Mat>& masks, bool compactResult );
02526 
02527 /*
02528  * Flann based matcher
02529  */
02530 class CV_EXPORTS FlannBasedMatcher : public DescriptorMatcher
02531 {
02532 public:
02533     FlannBasedMatcher( const Ptr<flann::IndexParams>& indexParams=new flann::KDTreeIndexParams(),
02534                        const Ptr<flann::SearchParams>& searchParams=new flann::SearchParams() );
02535 
02536     virtual void add( const vector<Mat>& descriptors );
02537     virtual void clear();
02538 
02539     virtual void train();
02540     virtual bool isMaskSupported() const;
02541     
02542     virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const;
02543 
02544 protected:
02545     static void convertToDMatches( const DescriptorCollection& descriptors,
02546                                    const Mat& indices, const Mat& distances,
02547                                    vector<vector<DMatch> >& matches );
02548 
02549     virtual void knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int k,
02550                    const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
02551     virtual void radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
02552                    const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
02553 
02554     Ptr<flann::IndexParams> indexParams;
02555     Ptr<flann::SearchParams> searchParams;
02556     Ptr<flann::Index> flannIndex;
02557 
02558     DescriptorCollection mergedDescriptors;
02559     int addedDescCount;
02560 };
02561 
02562 /****************************************************************************************\
02563 *                                GenericDescriptorMatcher                                *
02564 \****************************************************************************************/
02565 /*
02566  *   Abstract interface for a keypoint descriptor and matcher
02567  */
02568 class GenericDescriptorMatcher;
02569 typedef GenericDescriptorMatcher GenericDescriptorMatch;
02570 
02571 class CV_EXPORTS GenericDescriptorMatcher
02572 {
02573 public:
02574     GenericDescriptorMatcher();
02575     virtual ~GenericDescriptorMatcher();
02576 
02577     /*
02578      * Add train collection: images and keypoints from them.
02579      * images       A set of train images.
02580      * ketpoints    Keypoint collection that have been detected on train images.
02581      *
02582      * Keypoints for which a descriptor cannot be computed are removed. Such keypoints
02583      * must be filtered in this method befor adding keypoints to train collection "trainPointCollection".
02584      * If inheritor class need perform such prefiltering the method add() must be overloaded.
02585      * In the other class methods programmer has access to the train keypoints by a constant link.
02586      */
02587     virtual void add( const vector<Mat>& images,
02588                       vector<vector<KeyPoint> >& keypoints );
02589 
02590     const vector<Mat>& getTrainImages() const;
02591     const vector<vector<KeyPoint> >& getTrainKeypoints() const;
02592 
02593     /*
02594      * Clear images and keypoints storing in train collection.
02595      */
02596     virtual void clear();
02597     /*
02598      * Returns true if matcher supports mask to match descriptors.
02599      */
02600     virtual bool isMaskSupported() = 0;
02601     /*
02602      * Train some inner structures (e.g. flann index or decision trees).
02603      * train() methods is run every time in matching methods. So the method implementation
02604      * should has a check whether these inner structures need be trained/retrained or not.
02605      */
02606     virtual void train();
02607 
02608     /*
02609      * Classifies query keypoints.
02610      * queryImage    The query image
02611      * queryKeypoints   Keypoints from the query image
02612      * trainImage    The train image
02613      * trainKeypoints   Keypoints from the train image
02614      */
02615     // Classify keypoints from query image under one train image.
02616     void classify( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02617                            const Mat& trainImage, vector<KeyPoint>& trainKeypoints ) const;
02618     // Classify keypoints from query image under train image collection.
02619     void classify( const Mat& queryImage, vector<KeyPoint>& queryKeypoints );
02620 
02621     /*
02622      * Group of methods to match keypoints from image pair.
02623      * Keypoints for which a descriptor cannot be computed are removed.
02624      * train() method is called here.
02625      */
02626     // Find one best match for each query descriptor (if mask is empty).
02627     void match( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02628                 const Mat& trainImage, vector<KeyPoint>& trainKeypoints,
02629                 vector<DMatch>& matches, const Mat& mask=Mat() ) const;
02630     // Find k best matches for each query keypoint (in increasing order of distances).
02631     // compactResult is used when mask is not empty. If compactResult is false matches
02632     // vector will have the same size as queryDescriptors rows.
02633     // If compactResult is true matches vector will not contain matches for fully masked out query descriptors.
02634     void knnMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02635                    const Mat& trainImage, vector<KeyPoint>& trainKeypoints,
02636                    vector<vector<DMatch> >& matches, int k,
02637                    const Mat& mask=Mat(), bool compactResult=false ) const;
02638     // Find best matches for each query descriptor which have distance less than maxDistance (in increasing order of distances).
02639     void radiusMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02640                       const Mat& trainImage, vector<KeyPoint>& trainKeypoints,
02641                       vector<vector<DMatch> >& matches, float maxDistance,
02642                       const Mat& mask=Mat(), bool compactResult=false ) const;
02643     /*
02644      * Group of methods to match keypoints from one image to image set.
02645      * See description of similar methods for matching image pair above.
02646      */
02647     void match( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02648                 vector<DMatch>& matches, const vector<Mat>& masks=vector<Mat>() );
02649     void knnMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02650                    vector<vector<DMatch> >& matches, int k,
02651                    const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
02652     void radiusMatch( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02653                       vector<vector<DMatch> >& matches, float maxDistance,
02654                       const vector<Mat>& masks=vector<Mat>(), bool compactResult=false );
02655 
02656     // Reads matcher object from a file node
02657     virtual void read( const FileNode& );
02658     // Writes matcher object to a file storage
02659     virtual void write( FileStorage& ) const;
02660 
02661     // Return true if matching object is empty (e.g. feature detector or descriptor matcher are empty)
02662     virtual bool empty() const;
02663 
02664     // Clone the matcher. If emptyTrainData is false the method create deep copy of the object, i.e. copies
02665     // both parameters and train data. If emptyTrainData is true the method create object copy with current parameters
02666     // but with empty train data.
02667     virtual Ptr<GenericDescriptorMatcher> clone( bool emptyTrainData=false ) const = 0;
02668 
02669     static Ptr<GenericDescriptorMatcher> create( const string& genericDescritptorMatcherType,
02670                                                  const string &paramsFilename=string() );
02671 
02672 protected:
02673     // In fact the matching is implemented only by the following two methods. These methods suppose
02674     // that the class object has been trained already. Public match methods call these methods
02675     // after calling train().
02676     virtual void knnMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02677                                vector<vector<DMatch> >& matches, int k,
02678                                const vector<Mat>& masks, bool compactResult ) = 0;
02679     virtual void radiusMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02680                                   vector<vector<DMatch> >& matches, float maxDistance,
02681                                   const vector<Mat>& masks, bool compactResult ) = 0;
02682     /*
02683      * A storage for sets of keypoints together with corresponding images and class IDs
02684      */
02685     class CV_EXPORTS KeyPointCollection
02686     {
02687     public:
02688         KeyPointCollection();
02689         KeyPointCollection( const KeyPointCollection& collection );
02690         void add( const vector<Mat>& images, const vector<vector<KeyPoint> >& keypoints );
02691         void clear();
02692 
02693         // Returns the total number of keypoints in the collection
02694         size_t keypointCount() const;
02695         size_t imageCount() const;
02696 
02697         const vector<vector<KeyPoint> >& getKeypoints() const;
02698         const vector<KeyPoint>& getKeypoints( int imgIdx ) const;
02699         const KeyPoint& getKeyPoint( int imgIdx, int localPointIdx ) const;
02700         const KeyPoint& getKeyPoint( int globalPointIdx ) const;
02701         void getLocalIdx( int globalPointIdx, int& imgIdx, int& localPointIdx ) const;
02702 
02703         const vector<Mat>& getImages() const;
02704         const Mat& getImage( int imgIdx ) const;
02705 
02706     protected:
02707         int pointCount;
02708 
02709         vector<Mat> images;
02710         vector<vector<KeyPoint> > keypoints;
02711         // global indices of the first points in each image, startIndices.size() = keypoints.size()
02712         vector<int> startIndices;
02713 
02714     private:
02715         static Mat clone_op( Mat m ) { return m.clone(); }
02716     };
02717 
02718     KeyPointCollection trainPointCollection;
02719 };
02720 
02721 /*
02722  *  OneWayDescriptorMatcher
02723  */
02724 class OneWayDescriptorMatcher;
02725 typedef OneWayDescriptorMatcher OneWayDescriptorMatch;
02726 
02727 class CV_EXPORTS OneWayDescriptorMatcher : public GenericDescriptorMatcher
02728 {
02729 public:
02730     class CV_EXPORTS Params
02731     {
02732     public:
02733         static const int POSE_COUNT = 500;
02734         static const int PATCH_WIDTH = 24;
02735         static const int PATCH_HEIGHT = 24;
02736         static float GET_MIN_SCALE() { return 0.7f; }
02737         static float GET_MAX_SCALE() { return 1.5f; }
02738         static float GET_STEP_SCALE() { return 1.2f; }
02739 
02740         Params( int poseCount = POSE_COUNT,
02741                 Size patchSize = Size(PATCH_WIDTH, PATCH_HEIGHT),
02742                 string pcaFilename = string(),
02743                 string trainPath = string(), string trainImagesList = string(),
02744                 float minScale = GET_MIN_SCALE(), float maxScale = GET_MAX_SCALE(),
02745                 float stepScale = GET_STEP_SCALE() );
02746 
02747         int poseCount;
02748         Size patchSize;
02749         string pcaFilename;
02750         string trainPath;
02751         string trainImagesList;
02752 
02753         float minScale, maxScale, stepScale;
02754     };
02755 
02756     OneWayDescriptorMatcher( const Params& params=Params() );
02757     virtual ~OneWayDescriptorMatcher();
02758 
02759     void initialize( const Params& params, const Ptr<OneWayDescriptorBase>& base=Ptr<OneWayDescriptorBase>() );
02760 
02761     // Clears keypoints storing in collection and OneWayDescriptorBase
02762     virtual void clear();
02763 
02764     virtual void train();
02765 
02766     virtual bool isMaskSupported();
02767 
02768     virtual void read( const FileNode &fn );
02769     virtual void write( FileStorage& fs ) const;
02770 
02771     virtual bool empty() const;
02772 
02773     virtual Ptr<GenericDescriptorMatcher> clone( bool emptyTrainData=false ) const;
02774 
02775 protected:
02776     // Matches a set of keypoints from a single image of the training set. A rectangle with a center in a keypoint
02777     // and size (patch_width/2*scale, patch_height/2*scale) is cropped from the source image for each
02778     // keypoint. scale is iterated from DescriptorOneWayParams::min_scale to DescriptorOneWayParams::max_scale.
02779     // The minimum distance to each training patch with all its affine poses is found over all scales.
02780     // The class ID of a match is returned for each keypoint. The distance is calculated over PCA components
02781     // loaded with DescriptorOneWay::Initialize, kd tree is used for finding minimum distances.
02782     virtual void knnMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02783                                vector<vector<DMatch> >& matches, int k,
02784                                const vector<Mat>& masks, bool compactResult );
02785     virtual void radiusMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02786                                   vector<vector<DMatch> >& matches, float maxDistance,
02787                                   const vector<Mat>& masks, bool compactResult );
02788 
02789     Ptr<OneWayDescriptorBase> base;
02790     Params params;
02791     int prevTrainCount;
02792 };
02793 
02794 /*
02795  *  FernDescriptorMatcher
02796  */
02797 class FernDescriptorMatcher;
02798 typedef FernDescriptorMatcher FernDescriptorMatch;
02799 
02800 class CV_EXPORTS FernDescriptorMatcher : public GenericDescriptorMatcher
02801 {
02802 public:
02803     class CV_EXPORTS Params
02804     {
02805     public:
02806         Params( int nclasses=0,
02807                 int patchSize=FernClassifier::PATCH_SIZE,
02808                 int signatureSize=FernClassifier::DEFAULT_SIGNATURE_SIZE,
02809                 int nstructs=FernClassifier::DEFAULT_STRUCTS,
02810                 int structSize=FernClassifier::DEFAULT_STRUCT_SIZE,
02811                 int nviews=FernClassifier::DEFAULT_VIEWS,
02812                 int compressionMethod=FernClassifier::COMPRESSION_NONE,
02813                 const PatchGenerator& patchGenerator=PatchGenerator() );
02814 
02815         Params( const string& filename );
02816 
02817         int nclasses;
02818         int patchSize;
02819         int signatureSize;
02820         int nstructs;
02821         int structSize;
02822         int nviews;
02823         int compressionMethod;
02824         PatchGenerator patchGenerator;
02825 
02826         string filename;
02827     };
02828 
02829     FernDescriptorMatcher( const Params& params=Params() );
02830     virtual ~FernDescriptorMatcher();
02831 
02832     virtual void clear();
02833 
02834     virtual void train();
02835 
02836     virtual bool isMaskSupported();
02837 
02838     virtual void read( const FileNode &fn );
02839     virtual void write( FileStorage& fs ) const;
02840     virtual bool empty() const;
02841     
02842     virtual Ptr<GenericDescriptorMatcher> clone( bool emptyTrainData=false ) const;
02843 
02844 protected:
02845     virtual void knnMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02846                                vector<vector<DMatch> >& matches, int k,
02847                                const vector<Mat>& masks, bool compactResult );
02848     virtual void radiusMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02849                                   vector<vector<DMatch> >& matches, float maxDistance,
02850                                   const vector<Mat>& masks, bool compactResult );
02851 
02852     void trainFernClassifier();
02853     void calcBestProbAndMatchIdx( const Mat& image, const Point2f& pt,
02854                                   float& bestProb, int& bestMatchIdx, vector<float>& signature );
02855     Ptr<FernClassifier> classifier;
02856     Params params;
02857     int prevTrainCount;
02858 };
02859 
02860 /****************************************************************************************\
02861 *                                VectorDescriptorMatcher                                 *
02862 \****************************************************************************************/
02863 
02864 /*
02865  *  A class used for matching descriptors that can be described as vectors in a finite-dimensional space
02866  */
02867 class VectorDescriptorMatcher;
02868 typedef VectorDescriptorMatcher VectorDescriptorMatch;
02869 
02870 class CV_EXPORTS VectorDescriptorMatcher : public GenericDescriptorMatcher
02871 {
02872 public:
02873     VectorDescriptorMatcher( const Ptr<DescriptorExtractor>& extractor, const Ptr<DescriptorMatcher>& matcher );
02874     virtual ~VectorDescriptorMatcher();
02875 
02876     virtual void add( const vector<Mat>& imgCollection,
02877                       vector<vector<KeyPoint> >& pointCollection );
02878 
02879     virtual void clear();
02880 
02881     virtual void train();
02882 
02883     virtual bool isMaskSupported();
02884 
02885     virtual void read( const FileNode& fn );
02886     virtual void write( FileStorage& fs ) const;
02887     virtual bool empty() const;
02888 
02889     virtual Ptr<GenericDescriptorMatcher> clone( bool emptyTrainData=false ) const;
02890 
02891 protected:
02892     virtual void knnMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02893                                vector<vector<DMatch> >& matches, int k,
02894                                const vector<Mat>& masks, bool compactResult );
02895     virtual void radiusMatchImpl( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
02896                                   vector<vector<DMatch> >& matches, float maxDistance,
02897                                   const vector<Mat>& masks, bool compactResult );
02898 
02899     Ptr<DescriptorExtractor> extractor;
02900     Ptr<DescriptorMatcher> matcher;
02901 };
02902 
02903 /****************************************************************************************\
02904 *                                   Drawing functions                                    *
02905 \****************************************************************************************/
02906 struct CV_EXPORTS DrawMatchesFlags
02907 {
02908     enum{ DEFAULT = 0, // Output image matrix will be created (Mat::create),
02909                        // i.e. existing memory of output image may be reused.
02910                        // Two source image, matches and single keypoints will be drawn.
02911                        // For each keypoint only the center point will be drawn (without
02912                        // the circle around keypoint with keypoint size and orientation).
02913           DRAW_OVER_OUTIMG = 1, // Output image matrix will not be created (Mat::create).
02914                                 // Matches will be drawn on existing content of output image.
02915           NOT_DRAW_SINGLE_POINTS = 2, // Single keypoints will not be drawn.
02916           DRAW_RICH_KEYPOINTS = 4 // For each keypoint the circle around keypoint with keypoint size and
02917                                   // orientation will be drawn.
02918         };
02919 };
02920 
02921 // Draw keypoints.
02922 CV_EXPORTS void drawKeypoints( const Mat& image, const vector<KeyPoint>& keypoints, Mat& outImage,
02923                                const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );
02924 
02925 // Draws matches of keypints from two images on output image.
02926 CV_EXPORTS void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
02927                              const Mat& img2, const vector<KeyPoint>& keypoints2,
02928                              const vector<DMatch>& matches1to2, Mat& outImg,
02929                              const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
02930                              const vector<char>& matchesMask=vector<char>(), int flags=DrawMatchesFlags::DEFAULT );
02931 
02932 CV_EXPORTS void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
02933                              const Mat& img2, const vector<KeyPoint>& keypoints2,
02934                              const vector<vector<DMatch> >& matches1to2, Mat& outImg,
02935                              const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
02936                              const vector<vector<char> >& matchesMask=vector<vector<char> >(), int flags=DrawMatchesFlags::DEFAULT );
02937 
02938 /****************************************************************************************\
02939 *   Functions to evaluate the feature detectors and [generic] descriptor extractors      *
02940 \****************************************************************************************/
02941 
02942 CV_EXPORTS void evaluateFeatureDetector( const Mat& img1, const Mat& img2, const Mat& H1to2,
02943                                          vector<KeyPoint>* keypoints1, vector<KeyPoint>* keypoints2,
02944                                          float& repeatability, int& correspCount,
02945                                          const Ptr<FeatureDetector>& fdetector=Ptr<FeatureDetector>() );
02946 
02947 CV_EXPORTS void computeRecallPrecisionCurve( const vector<vector<DMatch> >& matches1to2,
02948                                              const vector<vector<uchar> >& correctMatches1to2Mask,
02949                                              vector<Point2f>& recallPrecisionCurve );
02950 
02951 CV_EXPORTS float getRecall( const vector<Point2f>& recallPrecisionCurve, float l_precision );
02952 CV_EXPORTS int getNearestPoint( const vector<Point2f>& recallPrecisionCurve, float l_precision );
02953 
02954 CV_EXPORTS void evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, const Mat& H1to2,
02955                                                   vector<KeyPoint>& keypoints1, vector<KeyPoint>& keypoints2,
02956                                                   vector<vector<DMatch> >* matches1to2, vector<vector<uchar> >* correctMatches1to2Mask,
02957                                                   vector<Point2f>& recallPrecisionCurve,
02958                                                   const Ptr<GenericDescriptorMatcher>& dmatch=Ptr<GenericDescriptorMatcher>() );
02959 
02960 
02961 /****************************************************************************************\
02962 *                                     Bag of visual words                                *
02963 \****************************************************************************************/
02964 /*
02965  * Abstract base class for training of a 'bag of visual words' vocabulary from a set of descriptors
02966  */
02967 class CV_EXPORTS BOWTrainer
02968 {
02969 public:
02970     BOWTrainer();
02971     virtual ~BOWTrainer();
02972 
02973     void add( const Mat& descriptors );
02974     const vector<Mat>& getDescriptors() const;
02975     int descripotorsCount() const;
02976 
02977     virtual void clear();
02978 
02979     /*
02980      * Train visual words vocabulary, that is cluster training descriptors and
02981      * compute cluster centers.
02982      * Returns cluster centers.
02983      *
02984      * descriptors      Training descriptors computed on images keypoints.
02985      */
02986     virtual Mat cluster() const = 0;
02987     virtual Mat cluster( const Mat& descriptors ) const = 0;
02988 
02989 protected:
02990     vector<Mat> descriptors;
02991     int size;
02992 };
02993 
02994 /*
02995  * This is BOWTrainer using cv::kmeans to get vocabulary.
02996  */
02997 class CV_EXPORTS BOWKMeansTrainer : public BOWTrainer
02998 {
02999 public:
03000     BOWKMeansTrainer( int clusterCount, const TermCriteria& termcrit=TermCriteria(),
03001                       int attempts=3, int flags=KMEANS_PP_CENTERS );
03002     virtual ~BOWKMeansTrainer();
03003 
03004     // Returns trained vocabulary (i.e. cluster centers).
03005     virtual Mat cluster() const;
03006     virtual Mat cluster( const Mat& descriptors ) const;
03007 
03008 protected:
03009 
03010     int clusterCount;
03011     TermCriteria termcrit;
03012     int attempts;
03013     int flags;
03014 };
03015 
03016 /*
03017  * Class to compute image descriptor using bag of visual words.
03018  */
03019 class CV_EXPORTS BOWImgDescriptorExtractor
03020 {
03021 public:
03022     BOWImgDescriptorExtractor( const Ptr<DescriptorExtractor>& dextractor,
03023                                const Ptr<DescriptorMatcher>& dmatcher );
03024     virtual ~BOWImgDescriptorExtractor();
03025 
03026     void setVocabulary( const Mat& vocabulary );
03027     const Mat& getVocabulary() const;
03028     void compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& imgDescriptor,
03029                   vector<vector<int> >* pointIdxsOfClusters=0, Mat* descriptors=0 );
03030     // compute() is not constant because DescriptorMatcher::match is not constant
03031 
03032     int descriptorSize() const;
03033     int descriptorType() const;
03034 
03035 protected:
03036     Mat vocabulary;
03037     Ptr<DescriptorExtractor> dextractor;
03038     Ptr<DescriptorMatcher> dmatcher;
03039 };
03040 
03041 } /* namespace cv */
03042 
03043 #endif /* __cplusplus */
03044 
03045 #endif
03046 
03047 /* End of file. */