使用SIFT描述符的OpenCV(C ++)增加了检测到的功能的数量?

时间:2012-03-21 11:22:46

标签: c++ opencv feature-detection sift

使用OpenCV中的 SIFT描述符实现时,我有点混乱。

我正在尝试测试各种特征检测器+描述符计算方法,因此我使用cv::FeatureDetectorcv::DescriptorExtractor接口的组合,这使我可以在不同的检测器方法和描述符之间进行简单的更改。 / p>

当调用cv::DescriptorExtractor::compute(...)(单个图像的变体)时,文档说如果不可能的话,给予算法的关键点的数量可能减少计算他们的描述符,我理解如何以及为什么这样做。

但是,我发生的事情是,描述符计算后的关键点实际上增加了。显然是这样,我并不是想阻止它发生,我只是希望解释为什么(只是一个直观的描述会很酷,尽管我更感谢那些)。

我在实际的OpenCV周围有多层包装层没有任何代码(只是设置一些本地非OpenCV标志),所以这里是在其底部调用的OpenCV代码:

cv::Ptr<cv::FeatureDetector> dect = cv::FeatureDetector::create("MSER");
cv::Mat input = cv::imread("someImg.ppm", 0);
std::vector<cv::KeyPoint> keypoints;
dect->detect(input, keypoints);

cv::Ptr<cv::DescriptorExtractor>deEx=cv::DescriptorCalculator::create("SIFT");

std::cout << "before computing, feats size " << keypoints.size() << std::endl;
// code to print out 10 features

cv::Mat desc;
deEx->compute(input, keypoints, desc);

std::cout << "after computing, feats size " << keypoints.size() << std::endl;
// code to print out 10 features

我在描述符计算之前和之后打印出前10个关键点,所以这里有一些具体的数字作为例子:

before computing, feats size 379
feat[0]: 10.7584 39.9262 176.526 0 12.5396
feat[1]: 48.2209 207.904 275.091 0 11.1319
feat[2]: 160.894 313.781 170.278 0 9.63786
feat[3]: 166.061 239.115 158.33 0 19.5027
feat[4]: 150.043 233.088 171.887 0 11.9569
feat[5]: 262.323 322.173 188.103 0 8.65429
feat[6]: 189.501 183.462 177.396 0 12.3069
feat[7]: 218.135 253.027 171.763 0 123.069
feat[8]: 234.508 353.236 173.281 0 11.8375
feat[9]: 234.404 394.079 176.23 0 8.99652
after computing, feats size 463
feat[0]: 10.7584 39.9262 13.1313 0 12.5396
feat[1]: 48.2209 207.904 69.0472 0 11.1319
feat[2]: 48.2209 207.904 107.438 0 11.1319
feat[3]: 160.894 313.781 9.57937 0 9.63786
feat[4]: 166.061 239.115 166.144 0 19.5027
feat[5]: 150.043 233.088 78.8696 0 11.9569
feat[6]: 262.323 322.173 167.259 0 8.65429
feat[7]: 189.501 183.462 -1.49394 0 12.3069
feat[8]: 218.135 253.027 -117.067 3 123.069
feat[9]: 218.135 253.027 7.44055 3 123.069

我可以从这个示例中看到原始的feat[1]feat[7]分别跨越了两个新的关键点,但我没有看到compute方法的任何逻辑解释那样做:(

我在这里给出的打印输出是使用 MSER 来检测关键点,然后尝试计算 SIFT 描述符,但是同样的增加大小也会发生 STAR SURF SIFT (即DoG)关键点。我没有尝试将 SIFT 描述符更改为其他内容,但如果有人认为它与问题相关,我会尝试并在我的问题中对其进行编辑。

3 个答案:

答案 0 :(得分:5)

首先,您可以在documentation cv::DescriptorExtractor::compute中看到std::vector<cv::Keypoints>中的non const参数。这意味着可以通过cv::DescriptorExtractor::compute修改此向量。 实际上,KeyPointsFilter::runByImageBorderKeyPointsFilter::runByKeypointSize(两个non-const函数)将应用于向量,并将删除无法计算描述符的关键点。不会重新提取关键点。 您应该发布几行代码用于进一步诊断。

-

好吧,我终于找到了问题发生的地方:cv::SiftDescriptorExtractor::compute方法调用SIFT::operator(),其中(重新)计算要素的方向,并且还复制具有多个主导方向的点。 解决方案可能是将descriptorParams.recalculateAngles更改为false。

答案 1 :(得分:2)

看起来这是由于OpenCV使用Rob Hess的SIFT实现,有时会复制具有多个主导方向的关键点。

环顾OpenCV报告的漏洞就行了,问题报告here

这不是一个错误,新版本中的行为没有得到纠正,而只是记录在案。由于我不得不使用我现在正在使用的OpenCV版本(v2.1),因为newer documentation中描述的行为对old one有所了解,所以我没有看到{{3}}的其他行为。我。

答案 2 :(得分:0)

这不是错误,而是设计:

如果没有明显的单一主导方向,则SIFT在不同方向的同一位置返回多个兴趣点。通常,估计最多三个(取决于实际的图像补丁)方向。