Question

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

In runtime It can happen that I add new keypoints to my matcher with matcher->add(myNewDescriptors);

Now when I have added an image with only 1 keypoint/descriptor and I use knnMatch it returns no matches:

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

After a while I get a vector with 0 Nearest-neighbour:

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

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

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

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

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

- OpenCV:2.4.5

Was it helpful?

Solution

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!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top