Ask Your Question
4

Set a threshold on FAST feature detection?

asked 2013-04-24 09:37:46 -0500

MysticBE gravatar image

updated 2014-03-01 14:27:20 -0500

Rui Marques gravatar image

When I use the FAST detector on an image of the size 960 x 720, I get about 9000 points with the current method. I was wondering if there is a technique to set a limit on the number of points that are being detected? Like the 500 best points only? I know that reducing the resolution gives less points, but I want to know if there is another way with a higher resolution?

FeatureDetector fast = FeatureDetector.create(FeatureDetector.FAST);

fast.detect(mIntermediateMat, points);

// gives +9000 points

This would help me in the description phase to reduce the calculation time to describe all these points. (takes about 0.8 seconds at the moment, and the descriptor is bigger then the original image when looking at the Mb). I don't use the native part, but the Java code and the OpenCV Library 2.4.4.

EDIT: I found this article on how to describe ORB parameters, and was wondering if it might work for FAST.

I added

FeatureDetector fast = FeatureDetector.create(FeatureDetector.FAST);

    String filename = "mnt/sdcard/fast_params.yml";
                    WriteFile(filename, "%YAML:1.0\nimage: mIntermediateMat\nkeypoints: points\nthreshold : 300 \nnonmaxSupression : true\ntype : FastFeatureDetector::TYPE_9_16\n");
                    DescriptorExtractor extractor = null;
                    extractor.read(filename);
    fast.detect(mIntermediateMat, points);

The string is based upon information i found here but it is giving back a NullPointerException and I'm not use it even works for FAST. Anyone?

edit retag flag offensive close merge delete

Comments

1

For your EDIT: Guess this results in the first solution @alexander-pacha gave to you, which should work fine if you do it like in http://answers.opencv.org/question/3167/java-how-to-set-parameters-to-orb-featuredetector/?answer=17296#post-id-17296

Guanta gravatar imageGuanta ( 2014-03-02 07:25:40 -0500 )edit

The method proposed here is valid, but I can barely imagine the reading operation in RT scenarios. As for configuration itself, please see my config applied to the code working under OpenCV 3.0

String fastConfig = "%YAML:1.0\nthreshold: 10\nnonmaxSuppression: 1\ntype : 1\n";

The last parameter - type - is defined as enum in features2d,hpp as

enum
{
**TYPE_5_8 = 0, TYPE_7_12 = 1, TYPE_9_16 = 2,**
THRESHOLD = 10000, NONMAX_SUPPRESSION=10001, FAST_N=10002,
}; )
oleg kleiman gravatar imageoleg kleiman ( 2015-08-07 18:17:58 -0500 )edit

4 answers

Sort by ยป oldest newest most voted
3

answered 2013-04-24 09:59:53 -0500

Guanta gravatar image

For C++ this would work with

cv::KeyPointsFilter::retainBest(keypoints, 5000);

which would retain the 5000 best features, maybe it's also wrapped for Java. If not you can easily do it by yourself checking the response-values of your keypoints, i.e. sort them according to the response-values and take the x highest ones.

edit flag offensive delete link more

Comments

There is no Java version to do this (not that I have found at least). How do I check these response-values? And wouldn't it take a lot of calculation time to do this (working on Android phone, so it's not unimportant)

MysticBE gravatar imageMysticBE ( 2013-04-25 11:16:02 -0500 )edit
1

Sorting is in O(n log n), so it depends on your image size and how many keypoints will be found.

Where is your exact problem? You have your MatOfKeypoints, now you need to sort it according to the response which is a field of the class KeyPoint, see http://docs.opencv.org/java/org/opencv/features2d/KeyPoint.htm: convert the MatOfKeypoints to a list, write a comparator-class for a Keypoint that compares the response value, then call Collections.sort()-method with that comperator. Take the 5000 best ones.

Guanta gravatar imageGuanta ( 2013-04-25 16:18:40 -0500 )edit

I have no idea how to convert the MatOfKeypoints to a list (i had no real Java training or anything). Are there any good examples out there on how to do this? I've only found some about converting the MatofKeypoints to MatOfPoint2f.

MysticBE gravatar imageMysticBE ( 2013-04-26 10:17:17 -0500 )edit
1

MatOfKeyPoint has a method toList() , see http://docs.opencv.org/java/org/opencv/core/MatOfKeyPoint.html

Guanta gravatar imageGuanta ( 2013-04-26 14:28:51 -0500 )edit

Hey Guanta, I did everything you said (convert the MatofKeypoints to a list, write the comparator class for the response values and then sort them), but how do I take the best ones? Another Question I have is, are the keypoints with the highest response rate (like 19) the best ones compared to others (like a respons of 10)?

MysticBE gravatar imageMysticBE ( 2013-04-29 10:39:19 -0500 )edit

Jep, exactly, the higher the better. If you have sorted them in ascending order, then create a new List of Keypoints with the last X ones, otherwise (i.e. descending) the first X ones, e.g. X = 5000 (I don't know how many you like to have). This list you convert back to a MatOfKeypoint via the method fromList() (see link of my last comment) and this you can then use for your descriptorExtractor-class.

Guanta gravatar imageGuanta ( 2013-04-29 12:47:23 -0500 )edit

I did it descending (best ones first) and I need the best 500 points, but I have no idea how to make this new list with the first 500 keypoints in it. I made a new topic for it with more information: http://answers.opencv.org/question/12670/how-to-keep-the-best-500-keypoints-from-an/ maybe you could check it out? thank you!

MysticBE gravatar imageMysticBE ( 2013-04-29 13:36:29 -0500 )edit

I guess you have already solved your problem since the question is deleted. In the case you haven't: You can use subList(), see http://docs.oracle.com/javase/1.5.0/docs/api/java/util/List.html#subList(int,%20int) to create a smaller list.

Guanta gravatar imageGuanta ( 2013-04-30 04:14:21 -0500 )edit
5

answered 2013-08-04 18:52:29 -0500

updated 2013-08-04 18:54:30 -0500

One way to reduce the number of keypoints detected is to increase the threshold. To do this, take a look at this post. You can replace the writeLine()-call with

writeToFile(outputFile, "%YAML:1.0\nthreshold: 30 \nnonmaxSupression: true\n");

to set the parameter for the FAST feature detector.

The other way is to get the best Keypoints is by sorting them according to their response and then pick only the n best ones:

// Detect the features with you Feature Detector
FeatureDetector fastDetector = FeatureDetector.create(FeatureDetector.FAST);
MatOfKeyPoint matrixOfKeypoints;
fastDetector.detect(imageMat, matrixOfKeypoints);

// Sort and select 500 best keypoints
List<KeyPoint> listOfKeypoints = matrixOfKeypoints.toList();
Collections.sort(listOfKeypoints, new Comparator<KeyPoint>() {
    @Override
    public int compare(KeyPoint kp1, KeyPoint kp2) {
        // Sort them in descending order, so the best response KPs will come first
        return (int) (kp2.response - kp1.response);
    }
});

List<KeyPoint> listOfBestKeypoints = listOfKeypoints.subList(0, 500);

One final remark: Gauglitz et al. 2011 showed that it is important for visual tracking, that keypoints are spatially well distributed, so keep in mind, that you might also want to select the best keypoints according to a grid, so make sure your points are spatially well distributed.

edit flag offensive delete link more

Comments

This is the best answer for Java, very complete.

Rui Marques gravatar imageRui Marques ( 2014-03-01 14:30:57 -0500 )edit
1

answered 2013-04-25 01:40:33 -0500

Nyenna gravatar image

Still in C++, but specifically for FAST, you can specify the threshold used by the algorithm:

cv::FastFeatureDetector detector(50);

Here, the threshold is set to 50. By increasing the threshold, you become less tolerant on the definition of a corner. It means that a candidate will need more contrast with its neighbors in order to be considered as a corner.

In other words, the higher the threshold, the smaller the number of corners you detect. You might use this as a first filter, and then retain the best of the remaining corner using cv::KeyPointsFilter::retainBest(keypoints, numberOfKeypointsToKeep) as suggested by Guanta.

edit flag offensive delete link more

Comments

I don't think there is a retainBest function when you do it with Java, is there any other way I can do this myself?

MysticBE gravatar imageMysticBE ( 2013-04-25 09:59:02 -0500 )edit

Hi. i tried using this algorithm in my program but i received some errors which says :

  • "object of abstract class type "cv::FastFeatureDetector" is not allowed "
  • "function "cv::FastFeatureDetector :: setThreshold" is a pure virtual function"

Please help... Thank you :(

tommy gravatar imagetommy ( 2016-01-29 03:55:15 -0500 )edit
0

answered 2013-07-29 01:49:11 -0500

Justin WK gravatar image

How about List<keypoint> retainbest = new ArrayList<keypoint>(pointstext.subList(0, 5000));

edit flag offensive delete link more

Comments

1

This would not work, because the keypoints returned by the FAST detector are not sorted, so you would end up taking 500 (more or less) random points instead of the 500 best points.

Alexander Pacha gravatar imageAlexander Pacha ( 2013-08-10 07:31:25 -0500 )edit
Login/Signup to Answer

Question Tools

3 followers

Stats

Asked: 2013-04-24 09:37:46 -0500

Seen: 11,257 times

Last updated: Mar 01 '14