c++ - 具有 k = 2 的 knnMatch 返回 0 最近邻,即使图像经过训练

标签 c++ opencv feature-detection sift surf

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

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

向我的匹配器添加新的关键点

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

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

过了一会儿,我得到了一个最近邻为 0 的 vector :

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 返回一个空 vector

另请注意,如果我将 .knnMatch 更改为简单的 .match,则匹配器会正常返回所有 DMatch!代码仅在使用 knnMatch 时失败

- OpenCV:2.4.5

最佳答案

我认为这是错误。我写了一个简单的脚本来测试这个。如果有人想确认,请帮忙。

此脚本提取图像上的前 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 失败了!

关于c++ - 具有 k = 2 的 knnMatch 返回 0 最近邻,即使图像经过训练,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16868031/

相关文章:

c++ - Visual C++ 说 void 函数需要返回一个值

python - OpenCV 立体置信度

opencv - 卡尔曼滤波器 3D 实现

c++ - 是否可以实现 std::move-and-clear 函数?

c++ - 在不重复的情况下选择随机字符 C++

c++ - 我在这部分 C++ 代码中找不到第二个 const 的实用程序,有人可以解释一下吗?

c++ - 如何使用 C++ 从 OpenCV 中的框架中删除黑色边框?

css - 检测浏览器对选择器支持的最佳 CSS 属性是什么

image - 在 MATLAB 中绘制两个图像之间的匹配点

opencv - 有没有在 GPU 上实现并且缩放/旋转不变的检测器?