【问题标题】:FLANN in opencv runs too slowopencv 中的 FLANN 运行速度太慢
【发布时间】:2016-03-11 23:24:12
【问题描述】:

我有一套积分cloub(积分cloub的数量≈200万)。我想为点 cloub 中的每个点找到最近的 k 邻居。我做了这样的事情

flann::Index flann_index(data_m, flann::KDTreeIndexParams(),cvflann::FLANN_DIST_EUCLIDEAN);// create the object of flann
    for (int i = 0; i < numberOfPointsInPointCloub; i++){
    flann_index.knnSearch(data_m.row(i), indices, dists,num_of_knn); //each row is a new set of point in 3D
    ..//save the results "dist" and "indices" in somewhere else
}

但这运行速度很慢。在 for 循环中,它在 20 秒内运行 1000 次,非常慢。我用错了吗?或者有什么方法可以加快速度?

更新: 我需要搜索的查询点正是用于构建树的点,我需要为树中的每个点找到最近的 k 个邻居,因此我从数据的每一行中获取点并执行 knnSearch。

【问题讨论】:

  • k-NN 算法可能会遭受所谓的“维度诅咒”,并且可能具有 O(kN^(1 -1/k))。如果您的点云实际上是随机的,那么您可能无法加快搜索速度。当您遍历大约 200 万个点中的每一个,然后执行 knnSearch 时,您正在创建一个将在超线性时间内运行的嵌套循环。如果不查看所有代码,很难确定可以进行哪些优化来加速您的代码。

标签: opencv flann


【解决方案1】:

我最近遇到了类似的问题。以下是一些想法:

首先,确保您处于发布模式。未优化的代码会严重影响性能。我最近的测试表明,从调试代码切换到发布代码后,性能提高了 70 倍。

其次,您正在使用 flann::KDTreeIndexParams() 的默认值,即 4 棵树。为了提高速度,您可以将其减少到 1。这可能会降低准确性,但有助于提高性能。

第三,至少在最近的 OpenCV 版本中,knnSearch 函数还有第五个参数,即 SearchParams()。它的构造函数的第一个参数“指定索引中的树应该被递归遍历的次数”,可以修改以平衡性能和准确性。详情请见OpenCV documentation

第四,您似乎一次搜索一个查询点的邻居。尝试一次运行多个查询点。返回参数“indices”和“dists”将是矩阵,其中每行 r 表示索引 r 处的点的邻居(每行的第一个元素表示查询点本身)。

最后,如果这还不够快,不妨看看VCG ibrary 中的 KdTree 实现。到目前为止,我已经看到发布模式的性能提升超过 OpenCV 的 FLANN 的 2 倍。您也可以尝试并行化,但只有在您从非并行版本中获得尽可能多的性能后,我才会走这条路。

【讨论】:

  • 实际上我想像 PCL link 中的那样执行统计 _outlier 删除,这就是为什么我需要构建一个 kd-tree,选择树中的每个元素并执行 KNN 搜索那个。
  • 您最初的问题是关于如何提高 OpenCV 的 flann::knnSearch 实现的性能,而您的更新更多是关于如何在统计异常值去除算法中使用 knnSearch,这是一个有点不同的问题。除非我误解了更新的意图,否则最好将其分解为自己的问题以保持重点。
  • 好的,我会具体说明的。
  • 如果我有多个查询点,我应该如何更改“indices”和“dists”的维度?
  • 看看Matrix类。在构建时,您提供数据以及行数和列数。请注意,您将数据分配到其他地方,这意味着您之后也必须注意释放它(我只是使用 std::vector 然后将指针传递给第一个元素)。对于索引和分布矩阵,每个查询点应该有一行,然后每个邻居应该有一个列。有关示例,请参阅FLANN manual
猜你喜欢
  • 2011-11-23
  • 1970-01-01
  • 2018-03-14
  • 2017-02-28
  • 2023-01-19
  • 2016-08-13
  • 2021-06-05
  • 2015-04-09
  • 2020-02-22
相关资源
最近更新 更多