Ask Your Question
3

knnMatch with k = 2 returns 0 nearest-neighbour with images with 1 keypoint

asked 2013-05-31 19:36:53 -0500

yes123 gravatar image

updated 2013-06-02 10:55:35 -0500

I am basically extracting many keypoints with SURF from similar images and adding them to the

BFMatcher(NORM_L2)

After I have calculate all descriptors from my keypoints and I have a

Mat descriptors;
vector<Mat> vectDesc;
vectDesc.push_back(descriptors);

I add them to the matcher->add(vectDesc);

Now when I add an image with only 1 keypoint/descriptor and I use knnMatch:

matcher->knnMatch(queryDesc,matches,2);

I get a vector with 0 Nearest-neighbour. If i do:

for(auto i = 0; i <matches.size(); i++) {
    cout << "matches size: "<<matches[i].size()<<endl;

I get printed

"matches size: 0"
"matches size: 0"
"matches size: 0"
...

This happens only when I have an image with only one keypoint/descriptor. Before the knnMatch works fine.

What it could be? (Version 2.4.5)
I have tried with SIFT and it happens the same thing

I have tried to check if matcher.getTrainDescriptors(); contains my descriptors and effectively it contains everything. To check this, if i do:

// (Get the size of the descriptors Mat associated to the first training image)
cout << matcher->getTrainDescriptors().at(0).size();

I get: [128 x 32]. This means that descriptors are there but the knnMatches return an empty vector

Also NOTE that If I change .knnMatch with a simple .match the matcher returns all DMatches normally! The code fails only with knnMatch

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
1

answered 2013-06-02 11:18:25 -0500

yes123 gravatar image

I think this is bug. I have wrote a simple script to test this. Please if someone want to confirm It would help.

This script extract first 100 keypoints on an image then extract 1 keypoint. Both set of descriptors are stored inside the matcher with .add.

Then if you run it you will see that using .match the code works. Using knnMatch the matcher doesnt' return anything:

Ptr<FeatureDetector> d = new OrbFeatureDetector();  
Ptr<DescriptorExtractor> e = new OrbDescriptorExtractor();
Ptr<DescriptorMatcher> m = new BFMatcher(NORM_HAMMING);


//> The first iteration will extract 100 keypoints and store them
//> The second iteration will extract 1 keypoint
for(int i=100;i>0;i=i-99) {
    d = new OrbFeatureDetector(i);
    Mat image = imread("train.png",0);
    vector<KeyPoint> kp;
    d->detect(image,kp);
    cout << "detected: "<<kp.size()<<endl;

    Mat desc;
    e->compute(image,kp,desc);
    cout << "descriptor size: "<<desc.size()<<endl;

    vector<Mat> addDesc;
    addDesc.push_back(desc);
    m->add( addDesc );

}

//> Test match and knnMatch
d = new OrbFeatureDetector(100);
Mat image = imread("query.png",0);
vector<KeyPoint> kp;

d->detect(image,kp);
Mat queryDesc;
e->compute(image,kp,queryDesc);



vector<DMatch> matches;
m->match(queryDesc,matches);


cout << "Parsing matches: "<<matches.size()<<endl;
for(int i=0;i<matches.size();i++)
    cout << "Matches[i].distance: "<<matches[i].distance<<endl;


vector<vector<DMatch>> matches2;
m->knnMatch(queryDesc,matches2,2);


cout << "Parsing matches: "<<matches2.size()<<endl;
for(int i=0;i<matches2.size();i++)
    cout << "matches size: "<<matches2[i].size()<<endl; //> THIS SHOULDN'T OUTPUT size: 0!

With this code, the call to .match will return correct result. But knnMatch fails!

edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2013-05-31 19:36:53 -0500

Seen: 768 times

Last updated: Jun 02 '13