我有一个(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)
结果是:
可以看出,在原始点分布密集的图形部分中,红点更接近。
我需要一种方法在x,y中根据给定的步长值(比如0.1)生成插值点 equispaced
正如 askewchan 正确指出的那样,当我的意思是“ equispaced in x,y”时,我的意思是曲线中的两个连续插值点应该彼此远离(欧几里得直线距离)的值相同。
我尝试了unubtu的答案,它适用于平滑的曲线,但似乎打破了不那么顺利的曲子:
这是因为代码以欧氏方式而不是直接在曲线上计算点距离,我需要点之间的距离在点之间相同。这个问题可以以某种方式解决吗?
答案 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)
让我们首先考虑一个简单的案例。假设您的数据看起来像蓝线, 下面。
如果要选择距离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()
注意:我将纵横比设置为'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()
答案 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中,但我可以描述一般的想法。有三种可能性。
首先,就简单的欧几里德距离而言,与邻居真正等距的点是什么?这样做将涉及在曲线上的任何点处找到具有固定半径的圆的交点。然后沿着曲线走。
接下来,如果您想要距离曲线本身的距离,如果曲线是分段线性曲线,则问题再次容易实现。只需沿着曲线走,因为线段上的距离很容易测量。
最后,如果你打算让曲线成为一个三次样条曲线,那么这也不是一件令人难以置信的困难,但需要更多的工作。这里的诀窍是:
因此,一个整合
sqrt((x')^2 + (y')^2)
同样,在MATLAB中,ODE45可以设置为识别函数跨越某些指定点的那些位置。
如果您的MATLAB技能可以胜任,您可以查看interparc中的代码以获得更多解释。这是一个相当好的评论代码。