【问题标题】:How to extract the BSpline basis from scipy.interpolate.BSpline如何从 scipy.interpolate.BSpline 中提取 BSpline 基础
【发布时间】:2017-08-28 22:05:07
【问题描述】:

this question 中,我向社区询问了scipy.interpolate.splev 如何计算样条基。我的目标是通过预先计算bspline basis 来比splev 更快地计算样条并通过执行@ 生成曲线987654328@ 到 control 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.dotbasiscontrol 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.        ]

【问题讨论】:

    标签: python numpy scipy


    【解决方案1】:

    BSpline.basis_elementinternal 结作为其参数。

    在您的示例中,您填充了结,但这并没有达到您的预期:

    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 返回的 callable 实际上是一个 b-spline 函数。 使用数组参数调用它的结果相当于直接运行 BSpline 文档字符串中的示例代码数组中每个元素的循环,https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.BSpline.html

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

    但是,它不是公共功能,因此不能保证在未来的版本中可用。如果您对它有很好的用途,并且对面向用户的 API 提出了建议,请将讨论提交给 scipy 错误跟踪器。

    【讨论】:

    • 感谢您的澄清。我被术语弄糊涂了。
    猜你喜欢
    • 2016-05-20
    • 2011-12-14
    • 1970-01-01
    • 2023-02-07
    • 1970-01-01
    • 2017-11-04
    • 2011-05-12
    • 2018-01-03
    • 1970-01-01
    相关资源
    最近更新 更多