【问题标题】:OpenCV (C++) using SIFT descriptors increases the number of detected features?使用 SIFT 描述符的 OpenCV (C++) 增加了检测到的特征的数量?
【发布时间】:2012-04-05 21:54:55
【问题描述】:

在使用 OpenCV 中的 SIFT 描述符 实现时,我遇到了一些令人困惑的情况。

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

当调用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 描述符,但是同样的 increase 在检测到 STARSURFSIFT(即 DoG)关键点时也会发生大小变化。我没有尝试将 SIFT 描述符更改为其他内容,但如果有人认为它与问题相关,我会尝试并在我的问题中进行编辑。

【问题讨论】:

  • 您可以添加您使用的部分代码吗?了解参数会很有用。
  • 呃...我实际上是在为 OpenCV 代码的包装器制作包装器,但我会尝试挖掘实际的 5 行代码,它们正在完成所有工作,并且编辑它。

标签: c++ opencv feature-detection sift


【解决方案1】:

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

--

好吧,我终于找到了问题所在:cv::SiftDescriptorExtractor::compute 方法调用了SIFT::operator(),它(重新)计算了特征的方向,并复制了具有几个主要方向的点。 解决方案可能是将descriptorParams.recalculateAngles 更改为false。

【讨论】:

  • 我知道为什么::compute 函数允许更改std::vector&lt;cv::Keypoints&gt; 以及non const 的含义。他们在文档中给出的原因是(我引用)“关键点。无法计算描述符的关键点被删除。”并且删除是好的。但是当我的关键点完成这个过程时,它们有更多,而不是更少,这就是我无法理解的。我还发布了一些真实的代码,以更好地理解打印输出的内容。
  • 我想弄清楚它以完全理解您的问题。没有代码很难诊断。我尝试了您编辑的代码,并更改为其他类型的 DesciptorExtractor。看来问题只发生在 Sift 描述符上。
  • 是的,我自己给出了一个答案,其中包含指向旧文档和新文档的链接以及报告问题的页面。一开始我没有发布代码,因为我对为什么会发生这种情况(提取 SIFT 描述符增加关键点的数量有什么意义)比在代码中的位置更感兴趣是不是真的发生了。
【解决方案2】:

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

查看 OpenCV 报告的错误就可以解决问题,该问题被报告为 here

这不是错误,该行为在较新的版本中并未得到纠正,而是仅记录在案。由于我必须使用我现在使用的 OpenCV 版本(v2.1),我没有想到查看newer documentation 的其他行为,因为old one 中描述的行为对我来说是有意义的。

【讨论】:

    【解决方案3】:

    这不是错误,而是设计使然:

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

    【讨论】:

      猜你喜欢
      • 2014-05-15
      • 2015-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-30
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      相关资源
      最近更新 更多