如何从scipy.interpolate.BSpline

时间:2017-08-28 22:05:08

标签: python numpy scipy

this question中,我向社群询问了scipy.interpolate.splev如何计算样条基础..我的目标是通过预先计算splev来比bspline basis更快地计算样条线并通过执行basiscontrol point点积生成曲线。

此后a new scipy.interpolate.BSpline interpolator被添加到scipyIt comes with a basis_element function,我认为可以用来返回用于计算样条曲线的基础。

例如,使用下面的输入代码from here

import numpy as np

# Control points
cv = np.array([[ 50.,  25., 0.],
       [ 59.,  12., 0.],
       [ 50.,  10., 0.],
       [ 57.,   2., 0.],
       [ 40.,   4., 0.],
       [ 40.,   14., 0.]])

kv = [0, 0, 0, 0, 1, 2, 3, 3, 3, 3] # knot vector
n = 10  # 10 samples (keeping it simple)
degree = 3 # Curve degree

我可以计算以下bspline基础:

[[ 1.          0.          0.          0.          0.          0.        ]
 [ 0.2962963   0.56481481  0.13271605  0.00617284  0.          0.        ]
 [ 0.03703704  0.51851852  0.39506173  0.04938272  0.          0.        ]
 [ 0.          0.25        0.58333333  0.16666667  0.          0.        ]
 [ 0.          0.07407407  0.54938272  0.36728395  0.00925926  0.        ]
 [ 0.          0.00925926  0.36728395  0.54938272  0.07407407  0.        ]
 [ 0.          0.          0.16666667  0.58333333  0.25        0.        ]
 [ 0.          0.          0.04938272  0.39506173  0.51851852  0.03703704]
 [ 0.          0.          0.00617284  0.13271605  0.56481481  0.2962963 ]
 [ 0.          0.          0.          0.          0.          1.        ]]

np.dotbasis上使用control points会在曲线上返回10个样本:

[[ 50.          25.           0.        ]
 [ 55.12654321  15.52469136   0.        ]
 [ 55.01234568  11.19753086   0.        ]
 [ 53.41666667   9.16666667   0.        ]
 [ 53.14506173   7.15432099   0.        ]
 [ 53.1882716    5.17901235   0.        ]
 [ 51.58333333   3.83333333   0.        ]
 [ 47.20987654   3.87654321   0.        ]
 [ 42.31790123   6.7345679    0.        ]
 [ 40.          14.           0.        ]]

问题:是否可以从scipy.interpolate.BSpline中提取上述基础?

显然我一定是错了,因为当我尝试时,我会得到这样的东西:

from scipy.interpolate import BSpline
b = BSpline.basis_element(kv)
print b(np.linspace(kv[0],kv[-1],n)) # i'm not sure what these values represent
[ 0.          0.00256299  0.04495618  0.16555213  0.28691315  0.28691315
  0.16555213  0.04495618  0.00256299  0.        ]

1 个答案:

答案 0 :(得分:2)

BSpline.basis_element内部结为参数。

在你的例子中,你填补了结,这没有按照你的想法做到:

In [3]: t = [0, 0, 0, 0, 1, 2, 3, 3, 3, 3]

In [4]: b = BSpline.basis_element(t)

In [5]: b.k
Out[5]: 8

所以它是一个8阶样条。

如果你想要一个二次样条,你可以

In [7]: b1 = BSpline.basis_element([0, 1, 2, 3])

In [8]: b1.k
Out[8]: 2

In [9]: b1.t
Out[9]: array([-1., -1.,  0.,  1.,  2.,  3.,  4.,  4.])

困惑?方法很简单:https://github.com/scipy/scipy/blob/v0.19.1/scipy/interpolate/_bsplines.py#L243-L302

BSpline.basis_element返回的可调用实际上是一个b样条函数。使用数组参数调用它的结果等同于直接运行{{1}中的示例代码在数组的每个元素的循环中使用docstring https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.BSpline.html

编辑:如果您在Cox-de Boor算法的变体后计算给定点的所有非零样条线,那么您可以查看BSpline函数,https://github.com/scipy/scipy/blob/v0.19.1/scipy/interpolate/_bspl.pyx#L161 (它本身只是一个C程序的包装器,可以完成所有繁重的工作;请注意, hard 可以击败后者的表现。)

但是,它不是公共功能,因此不保证在将来的版本中可用。如果您对它有很好的用处,并建议使用面向用户的API,请将讨论带到scipy bug跟踪器。