簡體   English   中英

加速算法以在兩個二維點數據集中找到最接近的項目

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

嗨,我希望改進這個非常慢的算法。 它應該只返回一個點,該點是兩個數據集中兩個最接近的點之一。

我使用的方法只是蠻力,清楚地測試每組點之間的距離。 一定會有更好的辦法。

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),並使用另一組中的所有點查詢它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM