Python 大numpy阵列的球面插值
我有一个numpy数组,它有8个字段,有2000万个样本 这些字段是Python 大numpy阵列的球面插值,python,numpy,interpolation,nan,Python,Numpy,Interpolation,Nan,我有一个numpy数组,它有8个字段,有2000万个样本 这些字段是[时间,X,Y,Z,QW,QX,QY,QZ] 其中x,y,z是空间点,QW,QX,QY,QZ是四元数 有两种不同的样本,一种包含[时间,X,Y,Z]数据,另一种包含[时间,QW,QX,QY,QZ]。由于数组是同质的,第一种类型的样本看起来像[时间,X,Y,Z,nan,nan,nan,nan],第二种类型的样本看起来像[时间,nan,nan,nan,nan,QW,QX,QY,QZ]。还有更多的[time,X,Y,Z,nan,nan
[时间,X,Y,Z,QW,QX,QY,QZ]
其中x,y,z是空间点,QW,QX,QY,QZ是四元数
有两种不同的样本,一种包含[时间,X,Y,Z]
数据,另一种包含[时间,QW,QX,QY,QZ]
。由于数组是同质的,第一种类型的样本看起来像[时间,X,Y,Z,nan,nan,nan,nan]
,第二种类型的样本看起来像[时间,nan,nan,nan,nan,QW,QX,QY,QZ]
。还有更多的[time,X,Y,Z,nan,nan,nan,nan]类型的示例。阵列中只有20000个[时间、nan、nan、nan、QW、QX、QY、QZ]
类型的样本
因此,该数组看起来像:
[time,nan,nan,nan,QW,QX,QY,QZ]
[time,X,Y,Z,nan,nan,nan,nan]
[time,X,Y,Z,nan,nan,nan,nan]
[time,X,Y,Z,nan,nan,nan,nan]
...
[time,X,Y,Z,nan,nan,nan,nan]
[time,nan,nan,nan,QW,QX,QY,QZ]
[time,X,Y,Z,nan,nan,nan,nan]
...
[time,nan,nan,nan,QW,QX,QY,QZ]
我的问题是,如何使用pyquaternion中的SLERP(球面线性插值)来插值观测值之间的QW、QX、QY、QZ值
四元数插值函数采用参数(四元数1、四元数2、比率)
其中比率为(时间点时间四元数1)/(时间四元数2时间四元数1)
问题是,对于给定的时间点x、y、z,如何快速搜索最近的上下四元数观测值
例如,我尝试过1000000点:
data.shape=(20000000,8)
quat1=Quaternion(数据[np.where((数据[1000000,0]>=data[:,0])和(~np.isnan(数据[:,4]))[0][1],4:8])
quat2=四元数(data[np.其中((data[1000000,0])我通常不使用四元数,因此我没有任何可用的实现。但是,由于问题似乎是如何找到要插值的点,这与四元数没有直接关系
该方法迭代成对的可用观测值,并插值介于两者之间的所有样本:
# Column 0: time
# Columns 1 - 3: quaternion (well, not really, but it should get the idea across)
x = np.array([[0, 0, 1, 1],
[1, np.nan, np.nan, np.nan],
[2, np.nan, np.nan, np.nan],
[3, 1, 0, 0],
[4, np.nan, np.nan, np.nan],
[5, 0, 1, 0],
[6, np.nan, np.nan, np.nan],
[7, np.nan, np.nan, np.nan],
[8, np.nan, np.nan, np.nan],
[9, 0, 0, 0]], dtype=float)
qidx = np.flatnonzero(~np.isnan(x[:, -1]))
for a, b in zip(qidx[:-1], qidx[1:]):
ta, tb = x[a, 0], x[b, 0]
qa, qb = x[a, 1:], x[b, 1:]
xi = x[a+1:b]
ratio = (xi[:, 0] - ta) / (tb - ta)
# perform linear interpolation
# should be replaced with quaternion interpolation
xi[:, 1:] = qa + (qb - qa) * ratio[:, np.newaxis]
应该可以很容易地调整数组布局并插入一个四元数插值函数,该函数采用两个四元数(qa
和qb
和一个比率
)。如果函数未矢量化(它不采用比率数组),则需要在比率中的元素上循环
使用表格中的测试数据进行定时测试(此版本vs)
n = 2000000
k = 1500
x = np.concatenate([np.arange(n).reshape(-1, 1), np.zeros((n, 3)) + np.nan], axis=1)
x[0, 1:] = [0, 0, 0]
x[-1, 1:] = [0, 0, 0]
x[np.random.randint(n, size=k), 1:] = np.random.rand(k, 3)
结果:
n/k | old | new | speedup
---------------+---------+--------+------------
20000/15 | 6 ms | 2 ms | x3
200000/150 | 313 ms | 23 ms | x13
2000000/1500 | 34 s | 250 ms | x136
20000000/15000 | memory error
观察结果1的可能重复:您不需要搜索每个样本,因为许多样本将共享相同的上下四元数。观察结果2:可能最好改变方法,在两个给定四元数之间插值所有点-无需搜索。@kazemakase这两个好点。有没有办法创建大型逻辑m请求搜索?这是可行的,但掩码仍然存在速度问题。每个循环需要0.2秒,15000个x2点和2000万-15000个x1点。创建大型逻辑掩码仅需0.14秒。2*15000=50分钟计算时间您有大量数据,不要期望计算时间可以减少到零;)但是,您是对的,逻辑掩码有点浪费,因为它是在x1
上全局构建的,而我们只需要几个局部元素。@Ianampbellmoore我已经更新了答案以避免掩码。它现在快得多,并且可以更好地扩展到更大的数组。但是,我不知道四元数插值的性能如何。我t肯定会比线性插值慢,可能会成为新的瓶颈。我实际上是通过从scipy.interpolate.interp1d中剥离代码来解决这个问题的,它使用np.searchsorted来查找在现有数组中应该放置新样本的位置。这让我在不到2秒内找到上下四元数解。我进一步优化了它通过剥离slerp函数并对其进行矢量化。但正是您的建议使我找到了此解决方案,所以我进行了投票。我将在稍后清理代码时发布我的代码
n/k | old | new | speedup
---------------+---------+--------+------------
20000/15 | 6 ms | 2 ms | x3
200000/150 | 313 ms | 23 ms | x13
2000000/1500 | 34 s | 250 ms | x136
20000000/15000 | memory error