Algorithm 基于网格划分的二维最近邻搜索
我在一个集合中有一个相当大的2D点集合(~20000),对于x-y平面中的每个点,我想确定该集合中最接近的点。(实际上,点的类型不同,我只想知道哪种类型最接近。x-y平面是位图,比如640x480。) 从到问题“”我有了制作网格的想法。我创建了N*M C++向量并将点放在向量中,这取决于它落入哪个容器。其思想是,您只需检查箱子中点的距离,而不是所有点的距离。如果存储箱中没有点,则以螺旋方式继续使用相邻的存储箱 不幸的是,我后来才读到奥利·查尔斯沃思的评论: 不幸的是,不只是相邻(考虑单元格中的两点) 向东可能比单元格中直接向东北的点更近, 例如,这个问题在更高的维度上变得更糟)。 另外,如果相邻的单元恰好少于10个呢 他们的分数是多少?在实践中,您需要“螺旋输出” 幸运的是,我已经找到了螺旋式代码(一个不错的解决方案,在同一个问题中还有其他版本)。但我仍然有一个问题:Algorithm 基于网格划分的二维最近邻搜索,algorithm,geometry,nearest-neighbor,Algorithm,Geometry,Nearest Neighbor,我在一个集合中有一个相当大的2D点集合(~20000),对于x-y平面中的每个点,我想确定该集合中最接近的点。(实际上,点的类型不同,我只想知道哪种类型最接近。x-y平面是位图,比如640x480。) 从到问题“”我有了制作网格的想法。我创建了N*M C++向量并将点放在向量中,这取决于它落入哪个容器。其思想是,您只需检查箱子中点的距离,而不是所有点的距离。如果存储箱中没有点,则以螺旋方式继续使用相邻的存储箱 不幸的是,我后来才读到奥利·查尔斯沃思的评论: 不幸的是,不只是相邻(考虑单元格中的两
- 如果我在一个单元格中发现命中,相邻单元格中可能会有更近的命中(黄色是我的探针,红色是错误的选择,绿色是实际的最近点):
- 如果我在相邻的一个牢房里发现了一个命中目标,那么在2步之外的一个牢房里可能会有一个命中目标,正如奥利·查尔斯沃思所说:
- 但更糟糕的是,如果我在两步之外的牢房里发现了一个命中目标,那么在三步之外的牢房里还有一个更近的命中目标!这意味着我必须考虑所有的细胞与DX,Dy=- 3…3或49个细胞!
那么,我如何确定何时停止“螺旋”或搜索呢?我听说有一种方法使用多个重叠网格,但我不太明白。有可能挽救这种网格技术吗?由于位图的尺寸不大,并且您希望计算每个
(x,y)
的最近点,因此可以使用动态编程
设V[i][j]
为从(i,j)
到集合中最近点的距离,但只考虑集合中位于“矩形”[(1,1),(i,j)]中的点
然后V[i][j]=0
如果(i,j)
中有一个点,或者V[i][j]=min(V[i'][j']+dist((i,j),(i',j'))
其中(i',j')
是(i,j)
的三个邻居之一:
i、 e
(i-1,j)
(i,j-1)
(i-1,j-1)
复杂度是O(平面大小),这是最优的。一个解决方案是用不同的网格大小构造多个分区 假设您在级别1,2,4,8创建分区 现在,搜索网格大小为1的点(基本上是在9个正方形中搜索)。如果搜索区域中有一个点,并且到该点的距离小于1,则停止。否则,请转到下一个网格大小
与只创建一级分区相比,您需要构建的网格数量大约是创建一级分区的两倍。对于您的任务,通常使用
点四叉树,尤其是当点分布不均匀时
要保存主内存,可以使用使用存储桶的PM或PMR四叉树
你在你的单元中搜索,在最坏的情况下,搜索围绕该单元的所有四元单元
您还可以使用k-d树
我正在尝试的解决方案
- 首先,制作一个网格,使每个框平均有1个点(如果需要更大的扫描,则更多)
- 选择中心框。继续以循环方式选择邻居框,直到找到至少一个邻居。此时,可以选择1个或9个左右的框
- 再选择一层相邻框
- 现在,您有了一个相当小的点列表,通常不超过10个点,您可以在距离公式中输入这些点以找到最近的邻居
由于每个框平均有1个点,因此您通常会选择9个框并比较9个距离。可以根据数据集属性调整网格大小,以获得更好的结果
此外,如果您的数据存在很大差异,您可以尝试两级网格(甚至更多),因此,如果选择有效并在单个查询中返回50个以上的点,请使用1/10大小的网格开始下一次网格搜索…您的点集是静态的还是动态的?对于一个点集执行了多少个“查找最近的”查询?是否有理由不使用现有的开发良好的库,例如内部使用kd树的ANN?还是出于好奇?k-d树专门处理这种情况,它考虑了拆分平面的其他方面: