加速算法在两个2D点数据集中寻找最接近的项

Speeding up algorithm to find the closest items in two data sets of 2D points

本文关键字:集中 数据集 数据 寻找 最接近 2D 算法 两个 加速      更新时间:2023-10-16

嗨,我想改进这个算法,它真的很慢。它应该返回一个点它是两个数据集中最近的两个点中的一个。

我使用的方法只是蛮力,清楚地测试每组点之间的距离。一定有更好的办法。

cv::Point FindClosesedValue(std::vector<cv::Point> & point_a, std::vector<cv::Point> point_b)
{
  double lowest_distance = std::numeric_limits<double>::max();
  cv::Point best_point;
  for (cv::Point & a : point_a)
  {
    for (cv::Point & b : point_b)
    {
      double distance = CvFunctions::DistanceSquared(b, a);
      if (distance < lowest_distance)
      {
        lowest_distance = distance;
        best_point = a;
      }
    }
  }
  return best_point;
}

请有人指出我在正确的方式来加快这个代码,希望数量级。

我曾经处理过一个类似的问题,我设法获得了100倍的加速,但这取决于数据。

如果你可以将一组点预先排序到一个瓦片网格中,你可以利用瓦片大小来缩小你需要测试的点。给定的点与特定贴图中的任何点之间都有最小和最大距离。您可以使用这些最小和最大距离来绑定要检查的瓷砖,从而避免检查远处瓷砖中的点。

一旦点被划分成贴图,你可以查找一个新的点会落在哪个贴图中,并从那里开始。根据您的数据,该平铺可能没有预先排序的点。最初你只想检查第一个贴图和周围的贴图,直到你找到任何一个点。这个点会给出最小距离的近似值。一旦你知道了你选择的点和找到的点之间的最小距离,你就可以继续检查贴图中的所有点,直到你选择的点和给定贴图中任何点之间的最小距离大于你找到的最小距离。任何更远的点都不能比你已经找到的点更近。如果你发现新的更近的点,这个最小距离当然会更新。

排序步骤是O(n),查找步骤在n和n^2之间有界,所以期望时间应该最多为O(n^2),如果你有一个合适的点分布,可能会更好,可能接近线性。

至于贴图大小,我发现选择每个贴图中的点数量大致等于覆盖数据集的贴图数量可以产生最佳运行时间。您可能可以使用分层块来做得更好,但我的解决方案从来没有那么复杂。

这是一个很好的问题。通常的递归最接近点对算法显然是行不通的,因为两个点集可能聚集在空间的不同区域。

你仍然可以在O(nlogn)时间解决这个问题。只需创建一个集合中所有点的kd-tree (k=2),并使用另一个集合中的所有点进行查询。