numpy-2d中的近点快速融合(没有for循环)

Wil*_*ren 5 python arrays numpy distance scipy

我有一个问题类似于这里提出的问题: 融合几个关键点的简单方法.我想用它们的坐标平均值替换彼此靠近的点.细胞的接近程度由用户指定(我说的是欧几里德距离).

在我的情况下,我有很多积分(约100万).这种方法很有效,但是因为它使用了双循环,所以非常耗时.

是否有更快的方法来检测和融合numpy 2d阵列中的近点?


为了完整,我添加了一个例子:

points=array([[  382.49056159,   640.1731949 ],
   [  496.44669161,   655.8583119 ],
   [ 1255.64762859,   672.99699399],
   [ 1070.16520917,   688.33538171],
   [  318.89390168,   718.05989421],
   [  259.7106383 ,   822.2       ],
   [  141.52574427,    28.68594436],
   [ 1061.13573287,    28.7094536 ],
   [  820.57417943,    84.27702407],
   [  806.71416007,   108.50307828]])
Run Code Online (Sandbox Code Playgroud)

下面可以看到点的散点图.红色圆圈表示彼此靠近的点(在这种情况下,阵列中最后两个点之间的距离为27.91).因此,如果用户指定最小距离为30,则应融合这些点.

在此输入图像描述

在熔丝功能的输出中,最后的点被融合.这看起来像:

#output
array([[  382.49056159,   640.1731949 ],
   [  496.44669161,   655.8583119 ],
   [ 1255.64762859,   672.99699399],
   [ 1070.16520917,   688.33538171],
   [  318.89390168,   718.05989421],
   [  259.7106383 ,   822.2       ],
   [  141.52574427,    28.68594436],
   [ 1061.13573287,    28.7094536 ],
   [  813.64416975,    96.390051175]])
Run Code Online (Sandbox Code Playgroud)

ali*_*i_m 7

如果您有大量的点,那么使用构建k -D树可能会更快scipy.spatial.cKDTree,然后查询它们比某个阈值更接近的点对:

import numpy as np
from scipy.spatial import cKDTree

tree = cKDTree(points)
rows_to_fuse = tree.query_pairs(r=30)    

print(repr(rows_to_fuse))
# {(8, 9)}

print(repr(points[list(rows_to_fuse)]))
# array([[ 820.57417943,   84.27702407],
#        [ 806.71416007,  108.50307828]])
Run Code Online (Sandbox Code Playgroud)

此方法的主要优点是您无需计算数据集中每对点之间的距离.

  • @Mehdi`rows_to_fuse`是包含`(i,j)`元组的Python`set`,其中`i`和`j`是`points`中距离为<`r`的一对行的索引.`rows_to_fuse.pop()`从集合中删除一个任意元组并返回它(在这种情况下,集合中只有一个元组),然后我会转换一个列表并使用索引到`pairs`的行来检索该对的x,y坐标.最后的结果是`(2,2)`numpy数组,但`rows_to_fuse`是一个集合.如果我将`rows_to_fuse`直接转换为列表可能会更清楚. (2认同)