3

I'm trying to run feature detection on an image using some of the inbuilt OpenCV feature detectors. However, I only want to detect the top/best n features present in the image (lets say 30 for this example). I already have code that will find features and then use them to identify that object in other images, but I can't work out how to restrict the number of keypoints found. I initialise the various detectors/extractors/matchers as below:

private final FeatureDetector mFeatureDetector = FeatureDetector.create(FeatureDetector.ORB);
private final DescriptorExtractor mDescriptorExtractor = descriptorExtractor.create(DescriptorExtractor.ORB);
private final DescriptorMatcher mDescriptorMatcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMINGLUT);

I have tried to find a solution already on SO but the only solutions I can find aren't for the android version of OpenCV. Trying similar methods to these solutions also didn't work.

The only method I can think of that might work is just taking the first 30 features, but I don't think this will work well as they might all be clustered in one part of the image. So I was wondering if anyone knows how the top 30 features can be chosen (if indeed they can). I don't mind which feature detection algorithm the solution is for (MSER, ORB, SIFT, SURF, STAR, GFTT, etc.).

I also require that exactly 30 features be detected each time, so playing with the sensitivity until it's "about right" isn't an option.

EDIT: the reason for needing to find exactly 30 features is that I am going to use them to train my detector. The idea is that I will get 30 features from each of a set of training images and then use the result to then find the object again in a scene. As the training images will be close ups of the object it doesn't matter that the features won't be clustered in one part of the image.

Community
  • 1
  • 1
  • 2
    Every algorithm don't have `nFeatures` ( see SURF constructor in src ) as in https://github.com/Itseez/opencv_contrib/blob/master/modules/xfeatures2d/include/opencv2/xfeatures2d/nonfree.hpp#L79. Java wrappers are not provided for each algorithm may be since they are not free. We just have generic `create`. Also, even if you get best 30 features, there is no guarantee they will not be clustered in one part of image. Can you give more clarity on need for limiting features? Will a `knnMatch` or `radiusMatch` help ? – kiranpradeep Dec 18 '14 at 08:40
  • I have updated my question with why I need to limit the features (I'm training my detector in a way that needs a constant number of features). Unfortunately I don't think that `knnMatch` or `radiusMatch` will help, but thanks for the thought. Do you know how the nFeatures algorithm was implemented? – TheOmegaPostulate Dec 18 '14 at 22:50
  • 1
    Iam not sure if i have understand your question correct! In C++ the feature Points (I know it from SURF) are sorted by the response of the used Filter. If it is not in Android you can do on your own, because every Keypoint you detect has an float response member value. So take the first 30 keypoints in the list should be the Keypoints with the highest response. They are not clusterd in a part of a Image by natural! – PeterNL Dec 19 '14 at 11:52
  • Thanks for your answer, that's what I was hoping that I'd be able to do! However each SURF keypoint is a 64 bit vector by default, and I don't know which part of that vector is the float response member value. Do you know which one it is or how I can find out? – TheOmegaPostulate Dec 21 '14 at 22:42

1 Answers1

0

Whilst I haven't been able to find a way of setting the number of keypoints to search for, I have been able to work out how to extract the correct number of keypoints afterwards. Doing this isn't computationally efficient but from the comments I received I don't think doing it before is possible.

My keypoints variable is:

private final MatOfKeyPoint mTargetKeypoints = new MatOfKeyPoint();

After it has been "filled" with features (it seems to stop after 500) the individual features can be extracted by transforming it to an array (where each element of the array is a feature.

mTargetKeypoints.toArray()[0]; //NOTE: Not actual code, used in a print statement

When I print the above the result is:

KeyPoint [pt={82.0, 232.0}, size=31.0, angle=267.77094, response=0.0041551706, octave=0, class_id=-1]

The individual information can then be extracted with the inbuilt Keypoint functions, e.g.:

mTargetKeypoints.toArray()[0].pt.x //Printing outputs x location of feature.
mTargetKeypoints.toArray()[0].response // Printing outputs response of feature. 

This SO question indicates that the response indicates "how good" the keypoint is. Thus from here it is relatively simple to pick the best 30 features to use.

Community
  • 1
  • 1