如何生成等间隔插值

时间:2013-10-01 13:35:18

标签: python numpy scipy interpolation

我有一个(x,y)值的列表,它们的间隔不均匀。 Here是此问题中使用的存档。

我能够在值之间进行插值,但我得到的不是等间距插值点。这是我的所作所为:

x_data = [0.613,0.615,0.615,...]
y_data = [5.919,5.349,5.413,...]

# Interpolate values for x and y.
t = np.linspace(0, 1, len(x_data))
t2 = np.linspace(0, 1, 100)
# One-dimensional linear interpolation.
x2 = np.interp(t2, t, x_data)
y2 = np.interp(t2, t, y_data)

# Plot x,y data.
plt.scatter(x_data, y_data, marker='o', color='k', s=40, lw=0.)

# Plot interpolated points.
plt.scatter(x2, y2, marker='o', color='r', s=10, lw=0.5)

结果是:

enter image description here

可以看出,在原始点分布密集的图形部分中,红点更接近。

我需要一种方法在x,y中根据给定的步长值(比如0.1)生成插值点 equispaced


正如 askewchan 正确指出的那样,当我的意思是“ equispaced in x,y”时,我的意思是曲线中的两个连续插值点应该彼此远离(欧几里得直线距离)的值相同。


我尝试了unubtu的答案,它适用于平滑的曲线,但似乎打破了不那么顺利的曲子:

non-smooth-curve

这是因为代码以欧氏方式而不是直接在曲线上计算点距离,我需要点之间的距离在点之间相同。这个问题可以以某种方式解决吗?

5 个答案:

答案 0 :(得分:13)

将xy数据转换为参数化曲线,即计算点之间的所有距离,并通过累积求和生成曲线上的坐标。然后相对于新坐标独立地插入x坐标和y坐标。

import numpy as np
from pylab import plot

data = '''    0.613   5.919
    0.615   5.349
    0.615   5.413
    0.617   6.674
    0.617   6.616
    0.63    7.418
    0.642   7.809
    0.648   8.04
    0.673   8.789
    0.695   9.45
    0.712   9.825
    0.734   10.265
    0.748   10.516
    0.764   10.782
    0.775   10.979
    0.783   11.1
    0.808   11.479
    0.849   11.951
    0.899   12.295
    0.951   12.537
    0.972   12.675
    1.038   12.937
    1.098   13.173
    1.162   13.464
    1.228   13.789
    1.294   14.126
    1.363   14.518
    1.441   14.969
    1.545   15.538
    1.64    16.071
    1.765   16.7
    1.904   17.484
    2.027   18.36
    2.123   19.235
    2.149   19.655
    2.172   20.096
    2.198   20.528
    2.221   20.945
    2.265   21.352
    2.312   21.76
    2.365   22.228
    2.401   22.836
    2.477   23.804'''

data = np.array([line.split() for line in data.split('\n')],dtype=float)

x,y = data.T
xd =np.diff(x)
yd = np.diff(y)
dist = np.sqrt(xd**2+yd**2)
u = np.cumsum(dist)
u = np.hstack([[0],u])

t = np.linspace(0,u.max(),20)
xn = np.interp(t, u, x)
yn = np.interp(t, u, y)

plot(x,y,'o')
plot(xn,yn,'gs')
xlim(0,5.5)
ylim(10,17.5)

答案 1 :(得分:7)

让我们首先考虑一个简单的案例。假设您的数据看起来像蓝线, 下面。

enter image description here

如果要选择距离r的等距点, 然后r会有一些临界值,其中(1,2)的尖点是第一个等距点。

如果你想要更大的点比这个临界距离更远,那么 第一个等距点将从(1,2)跳到一个非常不同的地方 - 由绿色弧线与蓝色线条的交点描绘。这种变化不是渐进的。

这个玩具案例表明,参数r的微小变化会对解决方案产生根本的,不连续的影响。

它还表明你必须知道第i个等距点的位置 在确定第(i + 1)个等距点的位置之前。

所以看起来需要一个迭代的解决方案:

import numpy as np
import matplotlib.pyplot as plt
import math

x, y = np.genfromtxt('data', unpack=True, skip_header=1)
# find lots of points on the piecewise linear curve defined by x and y
M = 1000
t = np.linspace(0, len(x), M)
x = np.interp(t, np.arange(len(x)), x)
y = np.interp(t, np.arange(len(y)), y)
tol = 1.5
i, idx = 0, [0]
while i < len(x):
    total_dist = 0
    for j in range(i+1, len(x)):
        total_dist += math.sqrt((x[j]-x[j-1])**2 + (y[j]-y[j-1])**2)
        if total_dist > tol:
            idx.append(j)
            break
    i = j+1

xn = x[idx]
yn = y[idx]
fig, ax = plt.subplots()
ax.plot(x, y, '-')
ax.scatter(xn, yn, s=50)
ax.set_aspect('equal')
plt.show()

enter image description here

注意:我将纵横比设置为'equal',以使得点更加明显是等距的。

答案 2 :(得分:2)

以下脚本将以x_max - x_min / len(x) = 0.04438

的相等步长插入点
import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt

data = np.loadtxt('data.txt')
x = data[:,0]
y = data[:,1]

f = interp1d(x, y)
x_new = np.linspace(np.min(x), np.max(x), x.shape[0])
y_new = f(x_new)

plt.plot(x,y,'o', x_new, y_new, '*r')
plt.show()

enter image description here

答案 3 :(得分:2)

通过@Christian K.扩展答案,以下是使用scipy.interpolate.interpn处理高维数据的方法。假设我们要重新采样到10个等距点:

import numpy as np
import scipy
# Assuming that 'data' is rows x dims (where dims is the dimensionality)
diffs = data[1:, :] - data[:-1, :]
dist = np.linalg.norm(diffs, axis=1)
u = np.cumsum(dist)
u = np.hstack([[0], u])
t = np.linspace(0, u[-1], 10)
resampled = scipy.interpolate.interpn((u,), pts, t)

答案 4 :(得分:0)

可以沿曲线生成等距点。但是,对于真正的答案,必须有更多的定义。对不起,但我为此任务编写的代码是在MATLAB中,但我可以描述一般的想法。有三种可能性。

首先,就简单的欧几里德距离而言,与邻居真正等距的点是什么?这样做将涉及在曲线上的任何点处找到具有固定半径的圆的交点。然后沿着曲线走。

接下来,如果您想要距离曲线本身的距离,如果曲线是分段线性曲线,则问题再次容易实现。只需沿着曲线走,因为线段上的距离很容易测量。

最后,如果你打算让曲线成为一个三次样条曲线,那么这也不是一件令人难以置信的困难,但需要更多的工作。这里的诀窍是:

  • 沿曲线从一点到另一点计算分段线性弧长。叫它t。
  • 生成一对三次样条,x(t),y(t)。
  • 将x和y区分为t的函数。由于这些是立方体段,因此这很容易。导数函数将是分段二次方。
  • 使用颂求解算器沿曲线移动,集成差分arclength函数。在MATLAB中,ODE45运行良好。

因此,一个整合

sqrt((x')^2 + (y')^2)

同样,在MATLAB中,ODE45可以设置为识别函数跨越某些指定点的那些位置。

如果您的MATLAB技能可以胜任,您可以查看interparc中的代码以获得更多解释。这是一个相当好的评论代码。