【问题标题】:Equally spaced spline evaluation in scipyscipy中的等间距样条评估
【发布时间】:2019-03-02 01:48:21
【问题描述】:

我正在使用 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 个点)。

我认为这是因为点会在密集区域产生“锯齿状”图案:例如,请参见此图,显示圆顶部的点频率如何变化。

我认为这与usplprep (see doc) 中的计算方式有关,我想我可以通过调整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),我唯一的想法是在某些情况下重新计算 u达到预期效果的方法,但我不知道如何。

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

编辑

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

uu = t / (2 * np.pi) # u1# 2
tck, _ = splprep(xy.T, u=uu, 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')

问题是,我不明白这些是从哪里来的。我怀疑这取决于样条曲线的计算方式,但无法弄清楚如何解决这个问题。我现在可以使用的唯一解决方案是使用平滑,但这是一种非常试错的方法,我宁愿不采用。

【问题讨论】:

    标签: python scipy interpolation spline smoothing


    【解决方案1】:

    强制u=t 使插值器的工作变得过于艰难,因为一些t 值彼此非常接近,而由于r 的变化,对应点并没有那么接近。这会导致插值曲线与数据的较大偏差,即第二个图上的异常值。

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

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多