【问题标题】:Finding the closest point from Point Cloud Data to point (0,0,0)查找从点云数据到点 (0,0,0) 的最近点
【发布时间】:2022-10-24 00:31:18
【问题描述】:

我编写了一个程序来根据点云数据绘制图形(x、y、z 坐标显示为列表 x_list、y_list、z_list)。现在,我必须找到最接近 (0,0,0) 的点。有人有这样做的想法吗?这是程序:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import math
from mpl_toolkits.mplot3d import axes3d


cloud = np.loadtxt('c1.txt')
rows = len(cloud)
columns = int(len(cloud[0])/5)

x_list = []
y_list = []
z_list = []

for i in range(rows):
    for j in range(columns):
    x_list.append(cloud[i][j])
    y_list.append(cloud[i][j+columns])
    z_list.append(cloud[i][j+2*columns])

#x_list = x_list[~pd.isnull(x_list)]


X = x_list
Y = y_list
Z = z_list

#Eliminating 'nan' values 
newlist_x = [X for X in x_list if math.isnan(X) == False]
newlist_y = [Y for Y in y_list if math.isnan(Y) == False]
newlist_z = [Z for Z in z_list if math.isnan(Z) == False]


display(newlist_x, newlist_y, newlist_z)


fig = plt.figure()
ax = fig.add_subplot(projection='3d')

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')


ax.scatter(newlist_x, newlist_y, newlist_z, c=newlist_z, cmap='plasma', linewidth=0.01) 
#3D plotting of points
plt.rcParams["figure.figsize"] = (12,15) #making plot more viewable

plt.show()

【问题讨论】:

  • 我还发现最小 Z 坐标是已知的(我可以从列表中轻松找到它),并且该坐标肯定来自最近的点。是否有可能找到知道 z 坐标的点的相应 x 和 y 值?
  • 如何计算到集合中每个点的距离,然后找到其中的最小值?你试过吗?
  • @ItaiDagan 你能写出它应该是什么样子吗?你的意思是d=sqrt(x2+y2+z2),d的最小值是最近点?是的,我正在考虑,但不确定如何在程序中实现它。
  • @ItaiDagan我找到了最小距离,但是由于该距离值,现在我如何找到坐标x,y,z?
  • distance = [] for i in range(len(newlist_x)): xa, ya, za = newlist_x[i], newlist_y[i], newlist_z[i] # 这些值相互对应 distance.append(((xa2)+(是的2)+(za**2))**(1/2)) #print(距离) min(距离)

标签: python pandas math point closest


【解决方案1】:

这应该可以解决问题。

def closest(X, Y, Z, P):
    """
        X: x-axis series
        Y: y-axis series
        Z: z-axis series
        P: centre point to measure distance from
        
        Returns: tuple(closest point, distance between P and closest point)
    """ 
    # Here we combine the X, Y, Z series to get a data struct. with all our points (similar to using the builtin's zip())
    points = np.column_stack((X, Y, Z))
    # Now we compute the distances between each of the points and the desired point
    distances = [np.linalg.norm(p) for p in (points - P)]
    # Finally we get the index of the smalles value in the array so that we can determine which point is closest and return it
    idx_of_min = np.argmin(distances)
    return (points[idx_of_min], distances[idx_of_min])

您可以这样拨打closest

X = [-1, -6, 8, 1, -2, -5, -1, 5, -3, -10, 6, 3, -4, 9, -5, -2, 4, -1, 3, 0]
Y = [-2, -1, -9, -6, -8, 7, 9, -2, -9, -9, 0, -2, -2, -3, 6, -5, -1, 3, 8, -5]
Z = [-1, 2, 3, 2, 6, -2, 9, 3, -10, 4, -6, 9, 8, 3, 3, -6, 4, 1, -10, 1]
closest_to_point(X, Y, Z, (0, 0, -100))

示例输出如下所示: (array([ 3, 8, -10]), 90.40464589831653)

【讨论】:

  • 谢谢,这也有效(我得到了与第一种方法相同的结果)
【解决方案2】:

这应该可以解决问题快很多

def closest_pythagoras(X, Y, Z, P):
    """
        X: x-axis series
        Y: y-axis series
        Z: z-axis series
        P: centre point to measure distance from
        
        Returns: tuple(closest point, distance between P and closest point)
    """ 
    # Compute the distances between each of the points and the desired point using Pythagoras' theorem
    distances = np.sqrt((X - P[0]) ** 2 + (Y - P[1]) ** 2 + (Z - P[2]) ** 2)
    # Get the index of the smallest value in the array to determine which point is closest and return it
    idx_of_min = np.argmin(distances)
    return (np.array([X[idx_of_min], Y[idx_of_min], Z[idx_of_min]]), distances[idx_of_min])

如果性能在您的应用程序中至关重要,请考虑对 Mieszko 的回答进行上述更改。 对于大型 X Y Z 数组,此代码的运行速度将提高几个数量级。

原始答案包含一个香草 python 循环,当points 的大小增加时,它会迅速破坏您的性能。移除循环并让 numpy 完成繁重的工作可以让成本随着输入大小线性增加,从而使其能够更好地扩展。最重要的是,使用毕达哥拉斯定理使性能大约比np.linalg.norm 提高了一倍。

  • 红色:Mieszko 的回答 / [np.linalg.norm(p) for p in (points - P)]
  • 橙色:Mieszko 答案的优化版 /np.linalg.norm(points - P, axis=1)
  • 绿色:好老毕达哥拉斯/np.sqrt((X - P[0]) ** 2 + (Y - P[1]) ** 2 + (Z - P[2]) ** 2)

所有测量均使用timeit 进行,在任何给定输入大小下进行 5 次运行中的最低值。 输入大小从 10 开始,并增加了一个数量级,直到函数执行时间超过 1 秒。 (在某些地方添加了中间值以保持图形整洁) 使用 Ryzen 9 5900X 的一根线进行测量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    • 2022-11-26
    相关资源
    最近更新 更多