0

Currently changing feature type is done by changing the name manually in the code. For example, for SURF detector and descriptor, I have to change the word "SURF" to some other name in the following code sample:

Ptr<SURF> detector = SURF::create();
Ptr<SURF> descriptor = SURF::create();

Is there a way to change the feature type by changing the "SURF" part through program arguments?

I want to be able to bulk evaluate multiple feature types rather than manually typing the feature type each time.

SK90
  • 69
  • 9

3 Answers3

1

It seems you would like the feature provided by the Ptr<FeatureDetector> cv::FeatureDetector::create(const string& detectorType) function:

"FAST" – FastFeatureDetector 
"STAR" – StarFeatureDetector 
"SIFT" – SIFT (nonfree module) 
"SURF" – SURF (nonfree module) 
"ORB" – ORB
"BRISK" – BRISK 
"MSER" – MSER 
"GFTT" – GoodFeaturesToTrackDetector
"HARRIS" – GoodFeaturesToTrackDetector with Harris detector enabled
"Dense" – DenseFeatureDetector 
"SimpleBlob" – SimpleBlobDetector

Also a combined format is supported: 
  feature detector adapter name ( "Grid" – GridAdaptedFeatureDetector, "Pyramid" – PyramidAdaptedFeatureDetector )
   + feature detector name (see above), for example: "GridFAST", "PyramidSTAR"

It returns a pointer to the FeatureDetector base class, so you can use polymorphism to select specific implementation at runtime:

//assuming image path is the first command line parameter and detector type is the second parameter
auto image = cv::imread(argv[1]);
auto ptr = cv::FeatureDetector::create(argv[2]); //auto evaulates to cv::Ptr<cv::FeatureDetector> here
std::vector<cv::KeyPoint> keypoints;
ptr->detect(image, keypoints);
for (auto kp : keypoints)
    cv::circle(image, kp.pt, 2, cv::Scalar(0, 255, 255), -1);
cv::imwrite(argv[1], image);
slawekwin
  • 6,270
  • 1
  • 44
  • 57
  • I was looking at this as well. Could you detail how to use polymorphism for this. I haven't used it before. By the way, I'm planning to use string input as program argument to choose feature type. Edited question for clarification. – SK90 Aug 16 '17 at 12:34
  • 2
    This solution uses a string as input. Have a look at: http://docs.opencv.org/2.4/modules/features2d/doc/common_interfaces_of_feature_detectors.html – Micka Aug 16 '17 at 12:38
  • @SK90 I added an example program showing how you can use this function. You don't have to do anything explicit regarding polymorphism here - just use interface function and let runtime figure out the correct implementation – slawekwin Aug 16 '17 at 12:42
  • @slawekwin I used your code but `error: ‘create’ is not a member of ‘cv::FeatureDetector {aka cv::Feature2D}’`. There seems to be only 'create' for already named features (e.g. Ptr create (arguments)). If there is no way, I may go for if-else option. – SK90 Aug 17 '17 at 06:32
  • @SK90 what includes do you have? `FeatureDetector` is in `opencv2/features2d/features2d.hpp`. Generally for most required features it easiest to just `#include "opencv2/opencv.hpp"` – slawekwin Aug 17 '17 at 06:41
  • @slawekwin I have `features2d.hpp` and added `opencv.hpp`. Still the same error. The error looks to be consistent with library code (i.e. I installed opencv 3.2 and there is no direct implementation of `FeatureDetector::create` or `Feature2D::create` after searching through the whole system). – SK90 Aug 17 '17 at 07:11
  • @Micka I searched for `Ptr create` too based on your link but it is nowhere to be found in my computer – SK90 Aug 17 '17 at 07:25
  • @SK90 it seems this function was dropped in OpenCV 3. This answer only applies to version 2.4 at this time. – slawekwin Aug 17 '17 at 07:45
0

What about a template?

template<class T> cv::Ptr<T> FeatureDetectorCreator()
{
    return T::create();
};

then you can call it with:

cv::Ptr<SURF> detector = FeatureDetectorCreator<SURF>();

Alternative could be a MACRO.

Will only work, if all those feature detectors share a common interface.

Micka
  • 19,585
  • 4
  • 56
  • 74
  • I want to use string input as program argument to program. Edited question to clarify. – SK90 Aug 16 '17 at 12:33
0

OpenCV 3.x

There is no built-in function for this. Use Ptr<FeatureDetector> to define a detector (the descriptor equivalent is Ptr<DescriptorExtractor>). Sample code is as follows:

string det = argv[4]; //assuming detector definition is fourth argument
Ptr<FeatureDetector> detector;
if (det == "SURF") {
    detector = SURF::create();
} else if (det == "SIFT") {
    detector = SIFT::create();
}

OpenCV 2.4.x

Use the provided function Ptr<FeatureDetector> cv::FeatureDetector::create(const string& detectorType). For further details please refer to answer by slawekwin.

SK90
  • 69
  • 9