/*
* Dynamic Feature Detectors
*/
+
+/** \brief A feature detector parameter adjuster, this is used by the DynamicDetector
+ * and is a wrapper for FeatureDetector that allow them to be adjusted after a detection
+ */
+class CV_EXPORTS AdjusterAdapter: public FeatureDetector {
+public:
+ /** pure virtual interface
+ */
+ virtual ~AdjusterAdapter() {
+ }
+ /** too few features were detected so, adjust the detector params accordingly
+ * \param min the minimum number of desired features
+ * \param n_detected the number previously detected
+ */
+ virtual void tooFew(int min, int n_detected) = 0;
+ /** too many features were detected so, adjust the detector params accordingly
+ * \param max the maximum number of desired features
+ * \param n_detected the number previously detected
+ */
+ virtual void tooMany(int max, int n_detected) = 0;
+ /** are params maxed out or still valid?
+ * \return false if the parameters can't be adjusted any more
+ */
+ virtual bool good() const = 0;
+};
/** \brief an adaptively adjusting detector that iteratively detects until the desired number
* of features are detected.
* Beware that this is not thread safe - as the adjustment of parameters breaks the const
* of the detection routine...
* /TODO Make this const correct and thread safe
*/
-template<typename Adjuster>
-class DynamicDetectorAdaptor: public FeatureDetector {
+class CV_EXPORTS DynamicDetector: public FeatureDetector {
public:
/** \param min_features the minimum desired features
* \param max_features the maximum desired number of features
* \param max_iters the maximum number of times to try to adjust the feature detector params
* for the FastAdjuster this can be high, but with Star or Surf this can get time consuming
- * \param a a copy of an Adjuster that will do the detection and parameter adjustment
+ * \param a an AdjusterAdapter that will do the detection and parameter adjustment
*/
- DynamicDetectorAdaptor(int min_features, int max_features,
- int max_iters, const Adjuster& a = Adjuster()) :
- escape_iters_(max_iters), min_features_(min_features), max_features_(
- max_features), adjuster_(a) {
- }
+ DynamicDetector(int min_features, int max_features, int max_iters,
+ const Ptr<AdjusterAdapter>& a);
protected:
- virtual void detectImpl(const cv::Mat& image,
- std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask =
- cv::Mat()) const {
- //for oscillation testing
- bool down = false;
- bool up = false;
-
- //flag for whether the correct threshhold has been reached
- bool thresh_good = false;
-
- //this is bad but adjuster should persist from detection to detection
- Adjuster& adjuster = const_cast<Adjuster&> (adjuster_);
-
- //break if the desired number hasn't been reached.
- int iter_count = escape_iters_;
-
- do {
- keypoints.clear();
-
- //the adjuster takes care of calling the detector with updated parameters
- adjuster.detect(image, mask, keypoints);
-
- if (int(keypoints.size()) < min_features_) {
- down = true;
- adjuster.tooFew(min_features_, keypoints.size());
- } else if (int(keypoints.size()) > max_features_) {
- up = true;
- adjuster.tooMany(max_features_, keypoints.size());
- } else
- thresh_good = true;
- } while (--iter_count >= 0 && !(down && up) && !thresh_good
- && adjuster.good());
- }
-
+ virtual void detectImpl(const cv::Mat& image,
+ std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask =
+ cv::Mat()) const;
private:
int escape_iters_;
int min_features_, max_features_;
- Adjuster adjuster_;
+ Ptr<AdjusterAdapter> adjuster_;
};
-struct FastAdjuster {
- FastAdjuster() :
- thresh_(20) {
- }
- void detect(const Mat& img, const Mat& mask, std::vector<
- KeyPoint>& keypoints) const {
- FastFeatureDetector(thresh_, true).detect(img, keypoints, mask);
- }
- void tooFew(int min, int n_detected) {
- //fast is easy to adjust
- thresh_--;
- }
- void tooMany(int max, int n_detected) {
- //fast is easy to adjust
- thresh_++;
- }
-
- //return whether or not the threshhold is beyond
- //a useful point
- bool good() const {
- return (thresh_ > 1) && (thresh_ < 200);
- }
+class FastAdjuster: public AdjusterAdapter {
+public:
+ FastAdjuster(int init_thresh = 20, bool nonmax = true);
+ virtual void tooFew(int min, int n_detected);
+ virtual void tooMany(int max, int n_detected);
+ virtual bool good() const;
+protected:
+ virtual void detectImpl(const cv::Mat& image,
+ std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask =
+ cv::Mat()) const;
int thresh_;
-};
+ bool nonmax_;
-struct StarAdjuster {
- StarAdjuster() :
- thresh_(30) {
- }
- void detect(const Mat& img, const Mat& mask, std::vector<
- KeyPoint>& keypoints) const {
- StarFeatureDetector detector_tmp(16, thresh_, 10, 8, 3);
- detector_tmp.detect(img, keypoints, mask);
- }
- void tooFew(int min, int n_detected) {
- thresh_ *= 0.9;
- if (thresh_ < 1.1)
- thresh_ = 1.1;
- }
- void tooMany(int max, int n_detected) {
- thresh_ *= 1.1;
- }
+};
- //return whether or not the threshhold is beyond
- //a useful point
- bool good() const {
- return (thresh_ > 2) && (thresh_ < 200);
- }
+struct StarAdjuster: public AdjusterAdapter {
+ StarAdjuster(double initial_thresh = 30.0);
+ virtual void tooFew(int min, int n_detected);
+ virtual void tooMany(int max, int n_detected);
+ virtual bool good() const;
+protected:
+ virtual void detectImpl(const cv::Mat& image,
+ std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask =
+ cv::Mat()) const;
double thresh_;
};
-struct SurfAdjuster {
- SurfAdjuster() :
- thresh_(400.0) {
- }
- void detect(const Mat& img, const Mat& mask, std::vector<
- KeyPoint>& keypoints) const {
- SurfFeatureDetector detector_tmp(thresh_);
- detector_tmp.detect(img, keypoints, mask);
- }
- void tooFew(int min, int n_detected) {
- thresh_ *= 0.9;
- if (thresh_ < 1.1)
- thresh_ = 1.1;
- }
- void tooMany(int max, int n_detected) {
- thresh_ *= 1.1;
- }
-
- //return whether or not the threshhold is beyond
- //a useful point
- bool good() const {
- return (thresh_ > 2) && (thresh_ < 1000);
- }
+struct SurfAdjuster: public AdjusterAdapter {
+ SurfAdjuster();
+ virtual void tooFew(int min, int n_detected);
+ virtual void tooMany(int max, int n_detected);
+ virtual bool good() const;
+protected:
+ virtual void detectImpl(const cv::Mat& image,
+ std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask =
+ cv::Mat()) const;
double thresh_;
};
-typedef DynamicDetectorAdaptor<FastAdjuster> FASTDynamicDetector;
-typedef DynamicDetectorAdaptor<StarAdjuster> StarDynamicDetector;
-typedef DynamicDetectorAdaptor<SurfAdjuster> SurfDynamicDetector;
CV_EXPORTS Mat windowedMatchingMask( const vector<KeyPoint>& keypoints1, const vector<KeyPoint>& keypoints2,
float maxDeltaX, float maxDeltaY );
/*
* Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor
- * bit count of A exclusive ored with B
+ * bit count of A exclusive XOR'ed with B
*/
struct CV_EXPORTS HammingLUT
{
typedef unsigned char ValueType;
typedef int ResultType;
- ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const
- {
- ResultType result = 0;
- for (int i = 0; i < size; i++)
- {
- result += byteBitsLookUp(a[i] ^ b[i]);
- }
- return result;
- }
+ ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const;
+
/** \brief given a byte, count the bits using a compile time generated look up table
* \param b the byte to count bits. The look up table has an entry for all
* values of b, where that entry is the number of bits.
static unsigned char byteBitsLookUp(unsigned char b);
};
-#if __GNUC__
-/// Hamming distance functor
-/// @todo Variable-length version, maybe default size=0 and specialize
-/// @todo Need to choose C/SSE4 at runtime, but amortize this at matcher level for efficiency...
+/// Hamming distance functor, this one will try to use gcc's __builtin_popcountl
+/// but will fall back on HammingLUT if not available
+/// bit count of A exclusive XOR'ed with B
struct CV_EXPORTS Hamming
{
typedef unsigned char ValueType;
typedef int ResultType;
-
- ResultType operator()(const unsigned char* a, const unsigned char* b, int size) const
- {
- /// @todo Non-GCC-specific version
- ResultType result = 0;
- for (int i = 0; i < size; i += sizeof(unsigned long))
- {
- unsigned long a2 = *reinterpret_cast<const unsigned long*> (a + i);
- unsigned long b2 = *reinterpret_cast<const unsigned long*> (b + i);
- result += __builtin_popcountl(a2 ^ b2);
- }
- return result;
- }
+ ResultType operator()(const unsigned char* a, const unsigned char* b, int size) const;
};
-#else
-typedef HammingLUT Hamming;
-#endif
+
/****************************************************************************************\
* DMatch *
--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+ //
+ // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+ //
+ // By downloading, copying, installing or using the software you agree to this license.
+ // If you do not agree to this license, do not download, install,
+ // copy or use the software.
+ //
+ //
+ // License Agreement
+ // For Open Source Computer Vision Library
+ //
+ // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+ // Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved.
+ // Third party copyrights are property of their respective owners.
+ //
+ // Redistribution and use in source and binary forms, with or without modification,
+ // are permitted provided that the following conditions are met:
+ //
+ // * Redistribution's of source code must retain the above copyright notice,
+ // this list of conditions and the following disclaimer.
+ //
+ // * Redistribution's in binary form must reproduce the above copyright notice,
+ // this list of conditions and the following disclaimer in the documentation
+ // and/or other materials provided with the distribution.
+ //
+ // * The name of the copyright holders may not be used to endorse or promote products
+ // derived from this software without specific prior written permission.
+ //
+ // This software is provided by the copyright holders and contributors "as is" and
+ // any express or implied warranties, including, but not limited to, the implied
+ // warranties of merchantability and fitness for a particular purpose are disclaimed.
+ // In no event shall the Intel Corporation or contributors be liable for any direct,
+ // indirect, incidental, special, exemplary, or consequential damages
+ // (including, but not limited to, procurement of substitute goods or services;
+ // loss of use, data, or profits; or business interruption) however caused
+ // and on any theory of liability, whether in contract, strict liability,
+ // or tort (including negligence or otherwise) arising in any way out of
+ // the use of this software, even if advised of the possibility of such damage.
+ //
+ //M*/
+
+#include "precomp.hpp"
+namespace cv {
+DynamicDetector::DynamicDetector(int min_features,
+ int max_features, int max_iters, const Ptr<AdjusterAdapter>& a) :
+ escape_iters_(max_iters), min_features_(min_features), max_features_(
+ max_features), adjuster_(a) {
+}
+void DynamicDetector::detectImpl(const cv::Mat& image, std::vector<
+ cv::KeyPoint>& keypoints, const cv::Mat& mask) const {
+ //for oscillation testing
+ bool down = false;
+ bool up = false;
+
+ //flag for whether the correct threshhold has been reached
+ bool thresh_good = false;
+
+ //this is bad but adjuster should persist from detection to detection
+ AdjusterAdapter& adjuster = const_cast<AdjusterAdapter&> (*adjuster_);
+
+ //break if the desired number hasn't been reached.
+ int iter_count = escape_iters_;
+
+ do {
+ keypoints.clear();
+
+ //the adjuster takes care of calling the detector with updated parameters
+ adjuster.detect(image, keypoints,mask);
+
+ if (int(keypoints.size()) < min_features_) {
+ down = true;
+ adjuster.tooFew(min_features_, keypoints.size());
+ } else if (int(keypoints.size()) > max_features_) {
+ up = true;
+ adjuster.tooMany(max_features_, keypoints.size());
+ } else
+ thresh_good = true;
+ } while (--iter_count >= 0 && !(down && up) && !thresh_good
+ && adjuster.good());
+}
+
+FastAdjuster::FastAdjuster(int init_thresh, bool nonmax) :
+ thresh_(init_thresh), nonmax_(nonmax) {
+}
+void FastAdjuster::detectImpl(const cv::Mat& image,
+ std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask) const {
+ FastFeatureDetector(thresh_, nonmax_).detect(image, keypoints, mask);
+}
+void FastAdjuster::tooFew(int min, int n_detected) {
+ //fast is easy to adjust
+ thresh_--;
+}
+void FastAdjuster::tooMany(int max, int n_detected) {
+ //fast is easy to adjust
+ thresh_++;
+}
+
+//return whether or not the threshhold is beyond
+//a useful point
+bool FastAdjuster::good() const {
+ return (thresh_ > 1) && (thresh_ < 200);
+}
+
+StarAdjuster::StarAdjuster(double initial_thresh) :
+ thresh_(initial_thresh) {
+}
+void StarAdjuster::detectImpl(const cv::Mat& image,
+ std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask) const {
+ StarFeatureDetector detector_tmp(16, thresh_, 10, 8, 3);
+ detector_tmp.detect(image, keypoints, mask);
+}
+void StarAdjuster::tooFew(int min, int n_detected) {
+ thresh_ *= 0.9;
+ if (thresh_ < 1.1)
+ thresh_ = 1.1;
+}
+void StarAdjuster::tooMany(int max, int n_detected) {
+ thresh_ *= 1.1;
+}
+
+bool StarAdjuster::good() const {
+ return (thresh_ > 2) && (thresh_ < 200);
+}
+
+SurfAdjuster::SurfAdjuster() :
+ thresh_(400.0) {
+}
+void SurfAdjuster::detectImpl(const cv::Mat& image,
+ std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask) const {
+ SurfFeatureDetector detector_tmp(thresh_);
+ detector_tmp.detect(image, keypoints, mask);
+}
+void SurfAdjuster::tooFew(int min, int n_detected) {
+ thresh_ *= 0.9;
+ if (thresh_ < 1.1)
+ thresh_ = 1.1;
+}
+void SurfAdjuster::tooMany(int max, int n_detected) {
+ thresh_ *= 1.1;
+}
+
+//return whether or not the threshhold is beyond
+//a useful point
+bool SurfAdjuster::good() const {
+ return (thresh_ > 2) && (thresh_ < 1000);
+}
+
+}