等距样条线评估scipy

时间:2018-09-26 10:02:04

标签: python scipy interpolation spline smoothing

我正在使用scipy构建带有splprepsplev的曲线(类似于椭圆形)的双变量样条曲线。目的是平滑点。

问题是,我要平滑的点在路径上分布不均匀,当我尝试评估样条线时,我会得到不均匀的分布,但是我希望样条线上的点均匀分布。

这是一个示例,显示了我的数据的样子和类似的结果(就我而言,这种效果实际上更为明显):

t = np.r_[0:2*np.pi:100.j, 0.142:np.pi+0.1:100j, 0.07+np.pi/2:0.23+np.pi:200j]
t = np.random.normal(t, 0.01)
t = np.unique(t)
# plt.plot(t)
r = np.asarray([1.0, 1.01] * (len(t) // 2)) # np.random.normal() # 1, 0.005, size=len(t))
xy = np.asarray([np.cos(t) * r, np.sin(t) * r]).T
# plt.plot(*xy.T, '.')
# plt.axis('equal')

tck, _ = splprep(xy.T, s=0, per=True)
xi, yi = splev(np.linspace(0, 1, 200), tck)
plt.subplots(figsize=(10, 10))
plt.plot(xi, yi, '.')
plt.axis('equal')

从下面的图中可以看到,有一个区域的点密度更高:我想避免这种影响,并具有均匀间隔的点(如果它们相对于形心以固定角度间隔甚至更好) ,例如每0.5度1点)。

Non uniform distribution of points after spline eval

我认为其原因是点在密集区域中导致“锯齿状”图案:例如,请参见此图,该图显示了点在圆顶部的频率如何变化。

Jagged edges

我认为这与usee doc)splprep的计算方式有关,我认为可以通过调整u参数来解决此问题,但是我不知道不知道如何:目前,它的计算方式似乎还不错,我无法提出更好的策略:

v = [0]
for i in range(1, len(xy)):
    vi = v[i - 1] + sum((xy[i] - xy[i - 1]) ** 2) ** 0.5
    v.append(vi)
u = [v[i] / v[-1] for i in range(1, len(xy))]

考虑到使用样条线我试图从数据集中(xy删除多余点的方法,我唯一的想法是重新计算{{1 }}以某种方式获得预期的效果,但我不知道如何。

如何使数据平滑以确保样条上的评估点彼此之间的距离大致相同?

编辑

我意识到,我基本上必须将u设置为每个点的角度(除以2pi,以在0和1内进行归一化)。我尝试过,各点看起来均匀分布,但是由于某些原因,我得到了一些离群值

u

Outliers after changing U

问题是,我不知道它们来自何处。我怀疑这取决于样条的计算方式,但无法弄清楚如何解决此问题。我现在唯一可以使用的解决方案是使用平滑,但这是我不愿意采用的非常反复试验的方法。

1 个答案:

答案 0 :(得分:2)

强制u=t会使插值器过分艰苦,因为某些t值彼此非常接近,而相应的点由于r的变化而不太接近。这会导致插值曲线与数据的较大偏差,即第二个图的离群值。

相反,请使用默认的u计算样条曲线,然后与极角成比例地重新设置参数。为此,我首先在参数域中以等间距的值评估样条曲线(如您的第一次尝试),用unwrap(arctan2)找到每个结果点的极角,然后找到u->的倒数。带线性插值的角度函数。插入样条中的该反函数会根据极角将点均匀隔开。

xx, yy = splev(np.linspace(0, 1, 200), tck)
s = np.unwrap(np.arctan2(yy, xx))
s_inv = np.interp(np.linspace(s[0], s[-1], len(s)), s, np.linspace(0, 1, len(s))) 
xi, yi = splev(s_inv, tck)

better