diff --git a/src/examples/feature_detection.cpp b/src/examples/feature_detection.cpp index 24cfb716a9646b1eb9fbc82f2fb5b17881682796..cdb43ef041721ac51402141ff080c16021c83ef4 100644 --- a/src/examples/feature_detection.cpp +++ b/src/examples/feature_detection.cpp @@ -4,6 +4,7 @@ // STD stuff #include <string> + int main(int argc, char *argv[]) { CFeature_Detector detector; @@ -71,3 +72,6 @@ int main(int argc, char *argv[]) cv::destroyAllWindows(); } + + + diff --git a/src/feature_detector/feature_detector.cpp b/src/feature_detector/feature_detector.cpp index e427d9379c44d58fc835b6383eb0e1d60b0a85bd..66b408b4597614db3f957e7eae2379dbbd4c6e36 100644 --- a/src/feature_detector/feature_detector.cpp +++ b/src/feature_detector/feature_detector.cpp @@ -1,7 +1,7 @@ #include "feature_detector.h" CFeature_Detector::CFeature_Detector(const DETECTOR_TYPE& _type) : - is_init_(false), is_line_(false), is_limited_(false), keypoints_limit_(-1), detect_time_(0.0) + type_(__DELIM__), is_init_(false), is_line_(false), is_limited_(false), keypoints_limit_(-1), detect_time_(0.0) { is_init_ = init(_type); @@ -13,7 +13,7 @@ CFeature_Detector::CFeature_Detector(const DETECTOR_TYPE& _type) : } CFeature_Detector::CFeature_Detector(const int&_type) : - is_init_(false), is_line_(false), is_limited_(false), keypoints_limit_(-1), detect_time_(0.0) + type_(__DELIM__), is_init_(false), is_line_(false), is_limited_(false), keypoints_limit_(-1), detect_time_(0.0) { is_init_ = init(intToDetectorType(_type)); @@ -25,7 +25,7 @@ CFeature_Detector::CFeature_Detector(const int&_type) : } CFeature_Detector::CFeature_Detector(void) : - is_init_(false), is_line_(false), is_limited_(false), keypoints_limit_(-1), detect_time_(0.0) + type_(__DELIM__), is_init_(false), is_line_(false), is_limited_(false), keypoints_limit_(-1), detect_time_(0.0) { } @@ -37,7 +37,8 @@ std::vector<DETECTOR_TYPE> CFeature_Detector::listDetectors(void) { std::vector<DETECTOR_TYPE> list; - for(int ii = 0; ii < ED+1; ii++){ + for (int ii = 0; ii < ED + 1; ii++) + { list.push_back(static_cast<DETECTOR_TYPE>(ii)); } @@ -46,13 +47,13 @@ std::vector<DETECTOR_TYPE> CFeature_Detector::listDetectors(void) bool CFeature_Detector::setDetectorType(const DETECTOR_TYPE& _type) { - is_init_ = init( _type ); + is_init_ = init(_type); return is_init_; } bool CFeature_Detector::setDetectorType(const int& _type) { - is_init_ = init( intToDetectorType(_type) ); + is_init_ = init(intToDetectorType(_type)); return is_init_; } @@ -79,10 +80,11 @@ int CFeature_Detector::getKeyPointsLimit(void) bool CFeature_Detector::init(DETECTOR_TYPE _type) { if (is_init_) - std::cerr << "[CFeature_Detector::init]: Detector already initialized." << std::endl; + std::cerr << "[CFeature_Detector::init]: Detector already initialized." << std::endl; bool success = false; + // TODO: Set parameters for each detector type switch (_type) { case FAST: @@ -110,11 +112,11 @@ bool CFeature_Detector::init(DETECTOR_TYPE _type) success = true; break; case GFTT: - feature_detector_ = cv::GFTTDetector::create(1000,0.01,1.0,3,false,0.04); + feature_detector_ = cv::GFTTDetector::create(1000, 0.01, 1.0, 3, false, 0.04); success = true; break; case HARRIS: - feature_detector_ = cv::GFTTDetector::create(1000,0.01,1.0,3,true,0.04); + feature_detector_ = cv::GFTTDetector::create(1000, 0.01, 1.0, 3, true, 0.04); success = true; break; case SBD: @@ -143,6 +145,9 @@ bool CFeature_Detector::init(DETECTOR_TYPE _type) is_line_ = true; success = true; break; + case __DELIM__: + success = false; + break; } if (success) @@ -156,15 +161,19 @@ bool CFeature_Detector::init(DETECTOR_TYPE _type) CFeature_Detector::KeyPointVector CFeature_Detector::detectKeyPoints(const cv::Mat& _image) { if (!is_init_) - std::cerr << "[CFeature_Detector::detectKeyPoints]: Detector non initialized." << std::endl; + std::cerr << "[CFeature_Detector::detectKeyPoints]: Detector non initialized." << std::endl; + + // TODO: Set a clever mask to reduce image search + if (mask_.empty()) + mask_ = cv::Mat::ones(_image.size(), CV_8U); KeyPointVector kpts; clock_t tStart = clock(); - feature_detector_->detect(_image, kpts); + feature_detector_->detect(_image, kpts, mask_); detect_time_ = (double)(clock() - tStart) / CLOCKS_PER_SEC; - if (this->isLimited()) + if (isLimited()) { cv::KeyPointsFilter filter; filter.retainBest(kpts, this->getKeyPointsLimit()); @@ -176,23 +185,27 @@ CFeature_Detector::KeyPointVector CFeature_Detector::detectKeyPoints(const cv::M CFeature_Detector::KeyLineVector CFeature_Detector::detectKeyLines(const cv::Mat& _image) { if (!is_init_) - std::cerr << "[CFeature_Detector::detectKeyLines]: Detector non initialized." << std::endl; + std::cerr << "[CFeature_Detector::detectKeyLines]: Detector non initialized." << std::endl; KeyLineVector kls; KeyLineVector kls2; + // TODO: Set a clever mask to reduce image search + if (mask_.empty()) + mask_ = cv::Mat::ones(_image.size(), CV_8U); + clock_t tStart = clock(); if (type_ == LSD) - lsd_detector_->detect(_image, kls, SCALE_FACTOR_LINE_DETECTOR, NUM_OCTAVE_LINE_DETECTOR); + lsd_detector_->detect(_image, kls, SCALE_FACTOR_LINE_DETECTOR, NUM_OCTAVE_LINE_DETECTOR, mask_); else - ed_detector_->detect(_image, kls2); + ed_detector_->detect(_image, kls2, mask_); detect_time_ = (double)(clock() - tStart) / CLOCKS_PER_SEC; kls.insert(kls.end(), kls2.begin(), kls2.end()); return kls; } -bool CFeature_Detector::limitKeypts(unsigned int _nFeatures) +bool CFeature_Detector::setLimitKeypts(unsigned int _nFeatures) { if (_nFeatures > 0) { @@ -203,7 +216,7 @@ bool CFeature_Detector::limitKeypts(unsigned int _nFeatures) return false; } -cv::Mat CFeature_Detector::drawKeyFeatures(const cv::Mat& _image, const std::vector<cv::KeyPoint>& _kp_vec) +cv::Mat CFeature_Detector::drawKeyFeatures(const cv::Mat& _image, const KeyPointVector& _kp_vec) { cv::Mat img_out(_image); @@ -213,8 +226,7 @@ cv::Mat CFeature_Detector::drawKeyFeatures(const cv::Mat& _image, const std::vec return img_out; } -cv::Mat CFeature_Detector::drawKeyFeatures(const cv::Mat& _image, - const std::vector<cv::line_descriptor::KeyLine>& _kl_vec) +cv::Mat CFeature_Detector::drawKeyFeatures(const cv::Mat& _image, const KeyLineVector& _kl_vec) { cv::Mat img_out(_image); @@ -224,3 +236,15 @@ cv::Mat CFeature_Detector::drawKeyFeatures(const cv::Mat& _image, return img_out; } +DETECTOR_TYPE CFeature_Detector::intToDetectorType(const unsigned int _i) +{ + DETECTOR_TYPE type; + + for (unsigned int ii = 0; ii < __DELIM__; ii++) + { + if (ii == _i) + type = static_cast<DETECTOR_TYPE>(ii); + } + + return type; +} diff --git a/src/feature_detector/feature_detector.h b/src/feature_detector/feature_detector.h index 0d0325ba19ff563ea426d9528b863667fa495de7..942d3d3fa165c614a532f82b6184d7da381e47d7 100644 --- a/src/feature_detector/feature_detector.h +++ b/src/feature_detector/feature_detector.h @@ -20,110 +20,45 @@ typedef cv::Ptr<cv::line_descriptor::LSDDetector> LSDDetector; typedef cv::Ptr<cv::line_descriptor::BinaryDescriptor> EDDetector; /** - * brief Descriptor types + * \brief MACROS to generate all detector types and their corresponding strings */ +#define FOREACH_DETECTOR(DETECTOR) \ + DETECTOR(FAST) \ + DETECTOR(SIFT) \ + DETECTOR(SURF) \ + DETECTOR(ORB) \ + DETECTOR(BRISK) \ + DETECTOR(MSER) \ + DETECTOR(GFTT) \ + DETECTOR(HARRIS) \ + DETECTOR(SBD) \ + DETECTOR(KAZE) \ + DETECTOR(AKAZE) \ + DETECTOR(AGAST) \ + DETECTOR(LSD) \ + DETECTOR(ED) \ + DETECTOR(__DELIM__) \ + +#define GENERATE_ENUM(ENUM) ENUM, +#define GENERATE_STRING(STRING) #STRING, enum DETECTOR_TYPE { - FAST, SIFT, SURF, ORB, BRISK, MSER, GFTT, HARRIS, SBD, KAZE, AKAZE, AGAST, LSD, ED + FOREACH_DETECTOR(GENERATE_ENUM) }; +static const char *DETECTOR_TYPE_STRING[] = {FOREACH_DETECTOR(GENERATE_STRING)}; /** * \brief Stream operator for the detector flags. */ inline std::ostream& operator<<(std::ostream& _os, DETECTOR_TYPE _f) { - switch (_f) - { - case FAST: - _os << "FAST"; - break; - case SIFT: - _os << "SIFT"; - break; - case SURF: - _os << "SURF"; - break; - case ORB: - _os << "ORB"; - break; - case BRISK: - _os << "BRISK"; - break; - case MSER: - _os << "MSER (Maximally Stable Extremal Region Extractor)"; - break; - case GFTT: - _os << "GFTT (Good Features To Track)"; - break; - case HARRIS: - _os << "HARRIS (GFTT using Harris)"; - break; - case SBD: - _os << "SBD (Simple Blob Detector)"; - break; - case KAZE: - _os << "KAZE"; - break; - case AKAZE: - _os << "AKAZE"; - break; - case AGAST: - _os << "AGAST"; - break; - case LSD: - _os << "LSD"; - break; - case ED: - _os << "ED"; - break; - default: - _os.setstate(std::ios_base::failbit); - } + _os << DETECTOR_TYPE_STRING[_f]; return _os; } /** - * \brief Convert an integer to its corresponding descriptor flag. - * - * By default return L2. + * \brief Main feature detector class */ -inline DETECTOR_TYPE intToDetectorType(const unsigned int _i) -{ - switch (_i) - { - case 0: - return FAST; - case 1: - return SIFT; - case 2: - return SURF; - case 3: - return ORB; - case 4: - return BRISK; - case 5: - return MSER; - case 6: - return GFTT; - case 7: - return HARRIS; - case 8: - return SBD; - case 9: - return KAZE; - case 10: - return AKAZE; - case 11: - return AGAST; - case 12: - return LSD; - case 13: - return ED; - default: - return ORB; - } -} - class CFeature_Detector { public: @@ -131,48 +66,97 @@ class CFeature_Detector typedef std::vector<cv::KeyPoint> KeyPointVector; typedef std::vector<cv::line_descriptor::KeyLine> KeyLineVector; + /** + * \brief Constructor + */ CFeature_Detector(const DETECTOR_TYPE& _type); CFeature_Detector(const int& _type); CFeature_Detector(void); + + /** + * \brief Destructor + */ ~CFeature_Detector(); + /** + * \brief List the defined detector types + */ std::vector<DETECTOR_TYPE> listDetectors(void); + /** + * \brief Set detector type + */ bool setDetectorType(const DETECTOR_TYPE& _type); bool setDetectorType(const int& _type); + /** + * \brief Get detection duration + */ double getDetectionTime(void); + /** + * \brief Inform if the detector searches points or lines + */ bool isLine(void); + /** + * \brief Inform if there is a maximum number of features to be detected + */ bool isLimited(void); + /** + * \brief Get number of maximum keypoints allowed + */ int getKeyPointsLimit(void); - bool limitKeypts(unsigned int _nFeatures); + /** + * \brief Set number of maximum keypoints allowed + */ + bool setLimitKeypts(unsigned int _nFeatures); + /** + * \brief Detect features (points or lines) + */ KeyPointVector detectKeyPoints(const cv::Mat&); KeyLineVector detectKeyLines(const cv::Mat&); - cv::Mat drawKeyFeatures(const cv::Mat& _image, const std::vector<cv::KeyPoint>& _kp_vec); - cv::Mat drawKeyFeatures(const cv::Mat& _image, const std::vector<cv::line_descriptor::KeyLine>& _kl_vec); + /** + * \brief Draw detected features + */ + cv::Mat drawKeyFeatures(const cv::Mat& _image, const KeyPointVector& _kp_vec); + cv::Mat drawKeyFeatures(const cv::Mat& _image, const KeyLineVector& _kl_vec); private: DETECTOR_TYPE type_; + // Flags bool is_init_; bool is_line_; bool is_limited_; - unsigned int keypoints_limit_; - double detect_time_; + unsigned int keypoints_limit_; // Max. number of keypoints (saturation) - FeatureDetectorPtr feature_detector_; - LSDDetector lsd_detector_; - EDDetector ed_detector_; + double detect_time_; // Detection time + cv::Mat mask_; // Mask to reduce image search + + FeatureDetectorPtr feature_detector_; // Feature point detectors + LSDDetector lsd_detector_; // Feature line detector + EDDetector ed_detector_; // Feature line detector + + /** + * \brief Initialize detector + */ bool init(DETECTOR_TYPE _type); + + /** + * \brief Convert an integer to its corresponding descriptor flag. + * + * By default return ORB. + */ + DETECTOR_TYPE intToDetectorType(const unsigned int _i); + }; #endif