算法设计:跟踪3D空间中的移动点

时间:2018-05-02 04:56:04

标签: algorithm cluster-analysis

这是一个与语言无关的问题,更多的是面向算法设计。

想象一下,我们在3D空间中有两个点阵列(每个点都看起来像[(1, 0, 2), (2, 4, 32), ...]

第一个数组表示点的第一个状态,第二个数字表示稍后移动了一小部分(不一定每个都移动相同距离)的后一个状态。 注意:可能已删除了几个点,并在第二个状态中添加了一些新点。

问题:鉴于这两个数组,如何将每个移位点与其原始点匹配(达到合理的准确度),同时还要确定哪些点是新的并且不存在于第一个州?

想法:我认为可以应用某种k-means聚类,但我不确定如何处理某些点已被删除/添加的事实在州之间 - 所以我不认为这种方法会很好。

修改

不一定在数组中的任何特定位置添加点,并且不必为状态之间的持久点保持顺序。与独特点之间的距离相比,点在状态之间移动的距离应该相对较小 - 否则这个问题基本上是不可能的。

3 个答案:

答案 0 :(得分:1)

这取决于一个假设:与第一组和第二组之间的唯一点之间的距离相比,移位距离非常小(基本上是模糊测量)。

首先,点集的一般结构不受平移,旋转或缩放的显着影响。这为您提供了很多选择。

获取每个维度的最小值/最大值(x,y,z等)。翻译和重新缩放两个点集。确切的缩放并不重要,但您可以使用它,使得所有点都是正的,并且在每个维度中都在0到100之间。这允许您更一致地比较点。虽然可能不是严格需要的,但可能会被忽略

然后你应该在点集A和点集B之间创建一个双向映射(双向图),它将是O(| A | + | B |),其中| A |和| B |是集的大小。 双向映射示例: a_to_b[(1.001,2.001)] = [(1.005,1.995)] b_to_a[(1.005,1.995)] = [(1.001,2.001)]

如果a_to_bb_to_a相互映射,那么这是相同概率的相同点。

如果没有,那么您可能会看到类似的内容: a_to_b[(1.001,2.007)] = [(1.005,1.995)] b_to_a[(1.005,1.995)] = [(1.500, 2.004)]

a_to_b[(1.500, 2.004)] = [(1.495, 2.009)] b_to_a[(1.495, 2.009)] = [(1.500, 2.004)]

由于不再有1-1映射,这意味着已添加或删除了某些内容。由于a中的值未映射回来,因此可能已删除。在相反的情况下,可能会增加。如果添加了,您将需要重新运行算法以尝试确定原始最近点是什么。

这可以通过查看不同的点并查看它是否是1-1映射的一部分(并因此被考虑)来验证。基本上,你想要考虑所有的1-1映射点(它们具有相同点的高概率),然后尝试整理不匹配的点

您可能希望获得两个点集的Delaunay三角剖分,以便能够更快地查找所有点的最近邻居,因为知道哪些点在空间上与给定点相邻。如果我回想起右边的Delaunay图中的边数是O(V),那么每个顶点的平均边是O(1)。一旦找到最近的点。但是,您可能需要对delaunary图进行一些调整以考虑添加/删除的边缘。

答案 1 :(得分:1)

将每个点与其最近邻居匹配,除非距离超过阈值。

如果你有多个可能的匹配,你需要设计一个好的解决策略。

将不匹配的点视为已删除或添加。

为了加快速度,请在数据上放置八叉树或网格文件,这样您只需要测试相邻的网格单元格,而不是将每个点与其他每个点进行比较。

答案 2 :(得分:0)

根据以下假设:

  1. 点可能会随机移动角度和长度,
  2. 积分可能会随机消失,
  3. 可以随机添加点数,也可以随机添加点
  4. 点(在每个数组中)仅由它们的坐标定义,没有任何ID。
  5. 如果以上所有都是正确的,那么就没有能够提供合理水平可靠性的解决方案。

    我可以添加许多可以证实我的断言的例子,但它看起来很直观,因此并不是真的需要。

    修改

    在与Ted Hopp讨论后,我将基于两个INSERTED CRITICAL假设包含一种替代方法:

    1. 这些点只移动一次,
    2. 可以说任何两点之间的最小初始距离是已知的,让我们称之为Lmin,而任何移动的最大距离是<< LMin我们称之为Mmax
    3. 通过这两个额外的假设,你可以想到一个如下机制(类似JavaScript的代码 - 没有检查!):

      for (i = 0 ; i < Points.Count ; i++) {
          for (j = i + 1 ; j < Points.Count ; j++) {
      
              if ((ABS(Array1[i].x - Array2[j].x) > Mmax ) ||
                  (ABS(Array1[i].y - Array2[j].y) > Mmax ) ||
                  (ABS(Array1[i].z - Array2[j].z) > Mmax )    ) {
                 // Distance between two points is for sure equal or bigger than max.
                 continue ; // Meaning, go to check next point.
              }
      
              // The check of the distance is split into two stages
              // because, if the first if is true, the actual distance
              // calculation is not needed (and hence time is saved).
      
              if (Distance_Between_Points(Array1[i],Array2[j]) > Mmax) {
                 // Distance between two points is for sure bigger than max.
                 continue ; // Meaning, go to check next point.
              }
      
              // Points appear to be related!!!!!!
              ..........
          }
      }