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 ¶meters = 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> ¢ers) 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 ¶msFilename=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. */