聚类一组3D点

时间:2017-08-14 08:30:12

标签: java arrays algorithm 3d k-means

我有一个大小为n的2D数组,代表3D空间中的n个点数,{1}}用于XYZ(例如position[][]position[0][0]X为Y,position[0][1]为点0的Z坐标。

我需要做的是对点进行群集,以便拥有position[0][2]个大小为n/k的群集,以便每个群集都包含最近的k 点在3D空间中。例如,如果kn=100,我希望有20个5点的簇,它们是空间中最近的邻居。

我怎样才能实现这一目标? (我需要伪代码。对于最好用Java的代码片段)

到目前为止,我所做的是基于每个组件的简单排序。但这确实 NOT 给了我最近的邻居。

  1. 基于X(k=5
  2. 排序
  3. 然后根据Y(position[0][0]
  4. 排序
  5. 然后根据Z(position[0][1]
  6. 排序


    position[0][2]

    我认为我的问题与使用kd-trees 的最近邻搜索略有不同,因为每次迭代中的邻居不应与其他迭代重叠。我想我们可能需要将它作为一个组件使用,但这是怎么回事。

2 个答案:

答案 0 :(得分:1)

一开始你没有八叉树,而是点数列表,而不是:

float position[n][3];

因此,为了简化群集和八叉树创建,您可以使用3D点密度贴图。它类似于创建直方图:

  1. 计算积分O(n)

    的边界框

    所以处理所有点并确定最小和最大坐标。

  2. 创建密度图O(max(m^3,n))

    因此,将使用过的空间(bbox)划分为一些3D体素网格(使用您想要/需要的分辨率),可以像以下一样进行密度映射:

    int map[m][m][m]`
    

    用零清除它。

    for (int x=0;x<m;x++)
     for (int y=0;y<m;y++)
      for (int z=0;z<m;z++)
       map[x][y][z]=0;
    

    然后处理所有点从x,y,z确定其单元格位置并递增它。

    for (int i=0;i<n;i++)
     {
     int x=(m-1)*(position[i][0]-xmin)/(xmax-xmin);
     int y=(m-1)*(position[i][1]-ymin)/(ymax-ymin);
     int z=(m-1)*(position[i][2]-zmin)/(zmax-zmin);
     map[x][y][z]++;
     // here you can add point i into octree belonging to leaf representing this cell
     }
    

    这将为您提供低密度密度图。单元格map[x][y][z]中的数字越大,其中的点越多,这意味着群集就在那里,您也可以将点移动到八叉树中的该群集。

  3. 对于具有足够点的单元格,可以递归地重复此操作。要使您的八叉树创建密度图2x2x2并递归地拆分每个单元格,直到其计数较小,则阈值或单元格大小太小。

    有关详细信息,请参阅类似的 QAs

答案 1 :(得分:0)

你不是什么聚类。根据你的说法,我认为你想要将你的N点划分为N / k组,每组有k个点,同时保持每个簇中的点在3D空间中最接近。

想想一个简单的例子,如果你想在一维上做同样的事情,也就是说,只是对数字进行排序,第一个k点进入集群1,第二个k指向集群2,依此类推。 / p>

然后返回3D空间问题,答案是一样的。首先找到具有最小x轴,y轴和z轴的点,总共将其最接近的k-1点放入簇1中。然后对于最小点,找到最小x轴,y轴和z-轴点和k-1最近点未聚集到群集2中,依此类推。

上面的过程会得到你的结果,但这在实践中可能没有意义,也许集群算法如k-means可以帮助你。