即使受过训练的图像,k = 2的knnMatch也会返回0最近邻居

时间:2013-06-01 01:02:48

标签: c++ opencv feature-detection sift surf

我基本上从类似的图像中提取SURF的许多关键点并将它们添加到BFMatcher(NORM_L2)

在运行时我可能会使用matcher->add(myNewDescriptors);

向匹配器添加新的关键点

现在当我添加一个只有一个关键点/描述符的图像时,我使用knnMatch它返回没有匹配项:

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

过了一会儿,我得到了一个0邻近的向量:

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

仅当我插入仅包含1个关键点/描述符的图像时才会发生这种情况。在knnMatch工作正常之前。

我试图检查matcher.getTrainDescriptors();是否包含我的描述符,实际上它包含了所有内容。要检查这个,如果我这样做:

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

我得到:[128 x 32]。这意味着描述符在那里,但knnMatches返回一个空向量

另请注意,如果我使用简单的.match更改.knnMatch,匹配器会正常返回所有DMatches!代码仅使用knnMatch

失败

- 的OpenCV:2.4.5

1 个答案:

答案 0 :(得分:0)

我认为这是错误。我写了一个简单的脚本来测试它。如果有人想确认它会有所帮助。

此脚本在图像上提取前100个关键点,然后提取1个关键点。两组描述符都存储在匹配器中,带有.add。

然后,如果你运行它,你会看到使用.match代码可以工作。使用knnMatch匹配器不会返回任何内容:

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!

使用此代码,对.match的调用将返回正确的结果。但knnMatch失败了!