Ask Your Question
1

How to filter FREAK+BruteForceMatcher result?

asked 2012-12-03 05:35:09 -0600

Mohamed Gad-Elrab gravatar image

I have 2 questions about FREAK implementation in opencv I really need to know to continue:

  1. I cannot get what the 64 values (columns) returned for each keypoint ? FREAK should return binary values as I understand?

  2. I used BruteForceMatcher<hamming> like in FREAK_demo.cpp in opencv samples. however it always give matches that may be wrong .. so I want to filter result ... I want to use the distance variable in the DMatch object returned but I cannot get what it representing in case of Hamming distance?.. should I take the big distances or small ?? what is the expected range for it ? I cannot find in any documentation

edit retag flag offensive close merge delete

Comments

Hamming distance is the summed XOR between two bit strings. Its value is is a non-negative integer and cannot exceed the length of the strings.With FREAK you ought to be using the BFMatcher with NORM_HAMMING and crossCheck set to true. Read the FREAK paper, it is easy to find.

Der Luftmensch gravatar imageDer Luftmensch ( 2014-11-17 19:04:34 -0600 )edit

2 answers

Sort by » oldest newest most voted
3

answered 2012-12-03 05:49:46 -0600

Geppertm gravatar image

updated 2014-11-11 07:41:45 -0600

Doombot gravatar image

Hi there, I´m using BruteForceMatcher.knnMatch

My results are filtered this way.

for(int i = 0; i < matches2.size(); ++i)
{
    if (matches2[i].size() < 2)
        continue; 



    if((matches2[i][0].distance < 0.59*(matches2[i][1].distance)) && ((int) matches2[i].size()<=2 && (int) matches2[i].size()>0))//Surf detector 0.56 StarFeatureDetector 0.59 Brisk 0.6
       good_matches.push_back(matches2[i][0]);

    if((matches2[i][0].distance <0.675*(matches2[i][1].distance)) && ((int) matches2[i].size()<=2 && (int) matches2[i].size()>0))//Surf detector 0.56 StarFeatureDetector 0.59 Bris 0.675
        out_matches.push_back(matches2[i][0]);


}

After I filtered the matches, I´m checking the ratio:

    if(out_matches.size()!=0)
    { 
      double x=((double)good_matches.size()/(double)out_matches.size());
      cout<<"x:"<<x<<endl;
      if(0.2<x && good_matches.size()>=6 && out_matches.size()>2) 
      {
             //found
      }
edit flag offensive delete link more

Comments

1st, thank you 2nd, I cannot get the difference between out matches and good matches why you count both. Also I cannot see the x threshold is it 0.2?

Mohamed Gad-Elrab gravatar imageMohamed Gad-Elrab ( 2012-12-06 08:42:54 -0600 )edit

Hi, the difference betwenn out and good matches is only the faktor (059 and 0.675), tah gives me the ratio good/out =x, the threshold of x is 0.2. I´ve tried a little with static matches recognition like if good_matches.size()>10, but i figuered out that the ratio way gives me better solution.

Geppertm gravatar imageGeppertm ( 2012-12-10 02:01:43 -0600 )edit

Just to be more precise, you place in the "out_matches" the good AND the bad matches, since in the first case it is <0.59 and next <0.675. So when you divide good_matches/out_matches, you still get a ratio, but it is the ratio of the good matches on the number of matches (good or out) that are below a certain threshold. So maybe "out_matches" was not the best name but the strategy is not wrong per se.

Doombot gravatar imageDoombot ( 2014-11-11 07:48:02 -0600 )edit
0

answered 2018-08-13 08:50:23 -0600

pierre_w gravatar image

To answer this question more completely, it is worth mentionning that FREAK is a local binary descriptor, that is to say it represents the surrounding of a keypoint in the form of the results of binary tests on the neighboring pixels of the keypoint. In the case of FREAK, the tests are chosen to mimic the behavior of a human retina (see the original paper for more info).

The result of the feature extraction is a u8 matrix with 64 columns because the FREAK descriptor uses 512 binary tests (64*8).

Now, binary descriptors are compared using the Hamming distance, which measures the number of bits with different values between two binary strings. For instance, computing the Hamming distance between "01110101" and "1111011" yields 2. Hence, the possible distance range when comparing two 512-bits strings is between 0 (the two strings are identical) and 512 (the strings are the exact opposites of one another).

To filter out "bad" matches, a distance threshold can be applied : if the Hamming distance between the query point and its nearest neighbor is more than a certain value (say 128, for a FREAK descriptor), then discard it.

Another solution is to perform crosscheck : matchings are done from query descriptors to train descriptors and the other way around. Then, only matches that are found in both directions are kept. To use crosscheck, just set the crosscheck argument of the matching function to true (see documentation).

Lastly, as suggested in the other answer, you can use the 2-nn matching method : instead of looking for the nearest neighbor for each keypoints, take the two nearest neighbors and compare their distances to the query keypoint. If they are not different enough (for instance if distance(query, 2nd best) > 0.8 distance(query, best) ), discard the keypoint. This allows to discard abiguous matches (when two possible matches are too similar to each other).

It is possible to use any combination of these three criteria.

Below is a code example for OpenCV 3.4.1+ :

Mat descriptors1;
edit flag offensive delete link more

Question Tools

Stats

Asked: 2012-12-03 05:35:09 -0600

Seen: 3,559 times

Last updated: Aug 13 '18