【问题标题】:find the k nearest neighbours of a point in 3d space with python numpy用python numpy在3d空间中找到一个点的k个最近邻居
【发布时间】:2018-06-26 23:44:13
【问题描述】:

我有一个 np.array((n,3)) 格式的 3d 点云。例如,这可能是这样的:

P = [[x1,y1,z1],[x2,y2,z2],[x3,y3,z3],[x4,y4,z4],[x5,y5,z5],.....[xn,yn,zn]]

我希望能够获得每个点的 K 最近邻。

例如,P1 的 k 个最近邻可能是 P2、P3、P4、P5、P6,而 P2 的 KNN 可能是 P100、P150、P2 等。

如何在 python 中做到这一点?

【问题讨论】:

标签: python numpy knn


【解决方案1】:

@marijn-van-vliet 的解决方案在大多数情况下都可以满足。但是,它被称为 brute-force 方法,如果点云相对较大或者如果您有计算/时间限制,您可能需要考虑构建 KD-Trees 以快速检索 K - 一个点的最近邻。

在 python 中,sklearn 库在这里提供了一个易于使用的实现:sklearn.neighbors.KDTree

from sklearn.neighbors import KDTree
tree = KDTree(pcloud)

# For finding K neighbors of P1 with shape (1, 3)
indices, distances = tree.query(P1, K)

(有关更详细的用法和输出,请参见另一篇文章中的以下答案:https://stackoverflow.com/a/48127117/4406572

许多其他库都实现了基于 KD-Tree 的 KNN 检索,包括 Open3D (FLANN based)scipy

【讨论】:

    【解决方案2】:

    这可以用scipy.spatial.distance.pdist巧妙地解决。

    首先,让我们创建一个在 3D 空间中存储点的示例数组:

    import numpy as np
    N = 10  # The number of points
    points = np.random.rand(N, 3)
    print(points)
    

    输出:

    array([[ 0.23087546,  0.56051787,  0.52412935],
           [ 0.42379506,  0.19105237,  0.51566572],
           [ 0.21961949,  0.14250733,  0.61098618],
           [ 0.18798019,  0.39126363,  0.44501143],
           [ 0.24576538,  0.08229354,  0.73466956],
           [ 0.26736447,  0.78367342,  0.91844028],
           [ 0.76650234,  0.40901879,  0.61249828],
           [ 0.68905082,  0.45289896,  0.69096152],
           [ 0.8358694 ,  0.61297944,  0.51879837],
           [ 0.80963247,  0.1680279 ,  0.87744732]])
    

    我们计算每个点到所有其他点的距离:

    from scipy.spatial import distance
    D = distance.squareform(distance.pdist(points))
    print(np.round(D, 1))  # Rounding to fit the array on screen
    

    输出:

    array([[ 0. ,  0.4,  0.4,  0.2,  0.5,  0.5,  0.6,  0.5,  0.6,  0.8],
           [ 0.4,  0. ,  0.2,  0.3,  0.3,  0.7,  0.4,  0.4,  0.6,  0.5],
           [ 0.4,  0.2,  0. ,  0.3,  0.1,  0.7,  0.6,  0.6,  0.8,  0.6],
           [ 0.2,  0.3,  0.3,  0. ,  0.4,  0.6,  0.6,  0.6,  0.7,  0.8],
           [ 0.5,  0.3,  0.1,  0.4,  0. ,  0.7,  0.6,  0.6,  0.8,  0.6],
           [ 0.5,  0.7,  0.7,  0.6,  0.7,  0. ,  0.7,  0.6,  0.7,  0.8],
           [ 0.6,  0.4,  0.6,  0.6,  0.6,  0.7,  0. ,  0.1,  0.2,  0.4],
           [ 0.5,  0.4,  0.6,  0.6,  0.6,  0.6,  0.1,  0. ,  0.3,  0.4],
           [ 0.6,  0.6,  0.8,  0.7,  0.8,  0.7,  0.2,  0.3,  0. ,  0.6],
           [ 0.8,  0.5,  0.6,  0.8,  0.6,  0.8,  0.4,  0.4,  0.6,  0. ]])
    

    你读这个距离矩阵是这样的:点 1 和 5 之间的距离是distance[0, 4]。还可以看到每个点与自身的距离为0,例如distance[6, 6] == 0

    我们argsort距离矩阵的每一行,为每个点获取最近的点列表:

    closest = np.argsort(D, axis=1)
    print(closest)
    

    输出:

    [[0 3 1 2 5 7 4 6 8 9]
     [1 2 4 3 7 0 6 9 8 5]
     [2 4 1 3 0 7 6 9 5 8]
     [3 0 2 1 4 7 6 5 8 9]
     [4 2 1 3 0 7 9 6 5 8]
     [5 0 7 3 6 2 8 4 1 9]
     [6 7 8 9 1 0 3 2 4 5]
     [7 6 8 9 1 0 3 2 4 5]
     [8 6 7 9 1 0 3 5 2 4]
     [9 6 7 1 8 4 2 0 3 5]]
    

    再次,我们看到每个点都离自己最近。所以,不管这个,我们现在可以选择 k 个最近的点:

    k = 3  # For each point, find the 3 closest points
    print(closest[:, 1:k+1])
    

    输出:

    [[3 1 2]
     [2 4 3]
     [4 1 3]
     [0 2 1]
     [2 1 3]
     [0 7 3]
     [7 8 9]
     [6 8 9]
     [6 7 9]
     [6 7 1]]
    

    例如,我们看到对于点 4,k=3 最接近的点是 1、3 和 2。

    【讨论】:

    • 昨晚我自己也找到了相同的解决方案,但非常感谢您提供详细的解决方案。我相信将来有人会觉得这很有帮助。
    猜你喜欢
    • 2021-04-29
    • 2019-06-04
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多