Numpy 点云中的局部极大值
我有一个点云C,其中每个点都有一个关联的值。假设点在二维空间中,所以每个点都可以用三元组(x,y,v)表示 我想找到局部极大值点的子集。也就是说,对于一些半径R,我想找到C中点S的子集,这样对于S中的任何点Pi(值为vi),在Pi的R距离内C中没有点Pj,其值vj大于vi 我知道如何在O(N^2)时间内完成这项工作,但这似乎是浪费。有没有一种有效的方法可以做到这一点Numpy 点云中的局部极大值,numpy,computational-geometry,sparse-matrix,kdtree,sparse-array,Numpy,Computational Geometry,Sparse Matrix,Kdtree,Sparse Array,我有一个点云C,其中每个点都有一个关联的值。假设点在二维空间中,所以每个点都可以用三元组(x,y,v)表示 我想找到局部极大值点的子集。也就是说,对于一些半径R,我想找到C中点S的子集,这样对于S中的任何点Pi(值为vi),在Pi的R距离内C中没有点Pj,其值vj大于vi 我知道如何在O(N^2)时间内完成这项工作,但这似乎是浪费。有没有一种有效的方法可以做到这一点 旁注: 这个问题的根源是我试图在稀疏矩阵中找到局部极大值,所以在我的例子中,x,y是有序整数索引-如果这简化了问题,请告诉我
旁注:
- 这个问题的根源是我试图在稀疏矩阵中找到局部极大值,所以在我的例子中,x,y是有序整数索引-如果这简化了问题,请告诉我李>
- 如果解决方案只针对曼哈顿距离或其他地方,我会非常高兴
- 我是python的,所以如果有一种很好的矢量化numpy方法来实现这一点,那就太好了
使用二维树(图形的二维实例)。经过N.Log(N)时间预处理后,它将允许您在大约Log(N)+K时间(平均找到K个邻居)内围绕所有点执行固定半径的近邻搜索,总共N.Log(N)+K.N。它将与曼哈顿距离完美匹配。根据Yves的建议,下面是一个使用scipy的答案:
谢谢但问题更为普遍。这解决了点在矩形网格中排列时的问题,并且由于掩蔽(尽管使用切片可能会更快),时间为O(N^2)。在我的问题中,这些点位于任意(x,y)位置。编辑速度比O(N^2)快,可以处理任意位置。谢谢,但仍然是N^2,因为对于每个点,您都会检查每个其他点是否在形成遮罩的半径内。看起来亚N^2解决方案需要使用K-D树或一些巧妙的排序。好的,我明白了。。。我还没有进入
kdtree
,所以我现在已经完成了!祝你好运你似乎自相矛盾。如果一个点在一个规则的网格上,完全改变了问题,但在commemt中你说它们是任意的,我不知道怎么做。在第一个解决方案中,将点表示为密集阵列,即矩形网格,这只是任意位置更一般情况下的一个特定实例。在特定矩阵情况下,您只需要搜索附近的索引。这简化了事情的顺序。注意——如果你想提高速度,不要使用SciPy的KDTree——而是使用SKLearn的,它快了300倍。这个答案仍然是金黄色的!非常适合:“from sklearn.KDTree;kdtree=kdtree(坐标);邻居=kdtree.query_半径(坐标,r=5)'
import numpy as np
# generate test data
n = 10
foo = np.random.rand(n,n)
# fixed test data for visual back-checking
# foo = np.array([[ 0.12439309, 0.88878825, 0.21675684, 0.21422532, 0.7016789 ],
# [ 0.14486462, 0.40642871, 0.4898418 , 0.41611303, 0.12764404],
# [ 0.41853585, 0.22216484, 0.36113181, 0.5708699 , 0.3874901 ],
# [ 0.24314391, 0.22488507, 0.22054467, 0.25387521, 0.46272496],
# [ 0.99097341, 0.76083447, 0.37941783, 0.932519 , 0.9668254 ]])
# list to collect local maxima
local_maxima = []
# distance in x / y to define region of interest around current center coordinate
# roi = 1 corresponds to a region of interest of 3x3 (except at borders)
roi = 1
# give pseudo-coordinates
x,y = np.meshgrid(range(foo.shape[0]), range(foo.shape[1]))
for i in range(foo.shape[0]):
for j in range(foo.shape[1]):
x0 = x[i,j]
y0 = y[i,j]
z0 = foo[i,j]
# index calculation to avoid out-of-bounds error when taking sub-matrix
mask_x = abs(x - x0) <= roi
mask_y = abs(y - y0) <= roi
mask = mask_x & mask_y
if np.max(foo[mask]) == z0:
local_maxima.append((i, j))
print local_maxima
import numpy as np
# generate test data
# points = np.random.rand(10,3)
points = np.array([[ 0.08198248, 0.25999721, 0.07041999],
[ 0.19091977, 0.05404123, 0.25826508],
[ 0.8842875 , 0.90132467, 0.50512316],
[ 0.33320528, 0.74069399, 0.36643752],
[ 0.27789568, 0.14381512, 0.13405309],
[ 0.73586202, 0.4406952 , 0.52345838],
[ 0.76639731, 0.70796547, 0.70692905],
[ 0.09164532, 0.53234394, 0.88298593],
[ 0.96164975, 0.60700481, 0.22605181],
[ 0.53892635, 0.95173308, 0.22371167]])
# list to collect local maxima
local_maxima = []
# distance in x / y to define region of interest around current center coordinate
radius = 0.25
for i in range(points.shape[0]):
# radial mask with radius radius, could be beautified via numpy.linalg
mask = np.sqrt((points[:,0] - points[i,0])**2 + (points[:,1] - points[i,1])**2) <= radius
# if current z value equals z_max in current region of interest, append to result list
if points[i,2] == np.max(points[mask], axis = 0)[2]:
local_maxima.append(tuple(points[i]))
local_maxima = [
(0.19091976999999999, 0.054041230000000003, 0.25826507999999998),
(0.33320527999999999, 0.74069399000000002, 0.36643752000000002),
(0.73586202000000001, 0.44069520000000001, 0.52345838),
(0.76639731, 0.70796546999999999, 0.70692904999999995),
(0.091645320000000002, 0.53234393999999996, 0.88298593000000003),
(0.53892635, 0.95173308000000001, 0.22371167)
]
from scipy.spatial.kdtree import KDTree
import numpy as np
def locally_extreme_points(coords, data, neighbourhood, lookfor = 'max', p_norm = 2.):
'''
Find local maxima of points in a pointcloud. Ties result in both points passing through the filter.
Not to be used for high-dimensional data. It will be slow.
coords: A shape (n_points, n_dims) array of point locations
data: A shape (n_points, ) vector of point values
neighbourhood: The (scalar) size of the neighbourhood in which to search.
lookfor: Either 'max', or 'min', depending on whether you want local maxima or minima
p_norm: The p-norm to use for measuring distance (e.g. 1=Manhattan, 2=Euclidian)
returns
filtered_coords: The coordinates of locally extreme points
filtered_data: The values of these points
'''
assert coords.shape[0] == data.shape[0], 'You must have one coordinate per data point'
extreme_fcn = {'min': np.min, 'max': np.max}[lookfor]
kdtree = KDTree(coords)
neighbours = kdtree.query_ball_tree(kdtree, r=neighbourhood, p = p_norm)
i_am_extreme = [data[i]==extreme_fcn(data[n]) for i, n in enumerate(neighbours)]
extrema, = np.nonzero(i_am_extreme) # This line just saves time on indexing
return coords[extrema], data[extrema]