Трудности использования scipy.interpolate BSpline: «TypeError: объект 'list' не может быть интерпретирован как целое число» - PullRequest
0 голосов
/ 08 мая 2020

Из здесь :

  • splrep позволяет вычислять узлы, коэффициенты и градусы B-сплайна на основе пути и коэффициента сглаживания
  • splev включает интерполяцию с использованием полученного B-сплайна
  • BSpline позволяет построить сплайн непосредственно из узлов, коэффициентов и градусов

Затем мне должно быть разрешено выполнить:

import numpy as np
from scipy.interpolate import splev, splprep, BSpline
path =  [(2077.0, 712.0, 1136.6176470588234), (2077.0004154771536, 974.630482962754, 1313.735294117647), (2077.1630960823995, 1302.460574562254, 1490.8529411764707), (2078.1944091179635, 1674.693193015173, 1667.9705882352941), (2080.5096120056783, 2086.976611915444, 1845.0882352941176), (2085.1051468332066, 2711.054258877495, 2022.2058823529412), (1477.0846185328733, 2803.6223679691457, 2199.323529411765), (948.4693105162195, 2802.0390667447105, 2376.4411764705883), (383.8615403256207, 2804.843424134807, 2553.5588235294117), (-41.6669725172834, 2497.067373170676, 2730.676470588235), (-37.94311919744064, 1970.5155845437525, 2907.794117647059), (-35.97395938535092, 1576.713103381243, 3084.9117647058824), (-35.125016151504795, 1214.2319876178394, 3262.029411764706), (-35.000550767864524, 893.3910350913443, 3439.1470588235297), (-35.0, 631.2108462417168, 3616.264705882353), (-35.0, 365.60545190581837, 3793.3823529411766), (-35.0, 100.00005756991993, 3970.5)]
p = [[x for x,y,z in path], [y for x,y,z in path], [z for x,y,z in path]]
tck, u = splprep(p, k=3)
t, c0, k = tck
sp = BSpline(t, k, c0)

Цель состоит в том, чтобы настроить B-Spline . Но BSpline не доволен моими аргументами:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/lalebarde/anaconda3/lib/python3.7/site-packages/scipy/interpolate/_bsplines.py", line 184, in __init__
    self.k = operator.index(k)
TypeError: 'list' object cannot be interpreted as an integer

Если я проверю формы и типы переменных:

type(t)
<class 'numpy.ndarray'>
type(c0)
<class 'list'>
type(k)
<class 'int'>
t.shape
(21,)
np.array(c0).shape
(3, 17)

Мое использование BSpline не удается, из документация :

class scipy.interpolate.BSpline (t, c, k, extrapolate = True, axis = 0)

t: ndarray, shape ( n + k + 1,) -> узлов

c: ndarray, shape (> = n,…) -> spline коэффициенты - Для сплайна степени требуется не менее k + 1 коэффициентов k, так что n> = k + 1. Дополнительные коэффициенты c [j] с j> n игнорируются.

k: int -> B-spline order

, кроме коэффициентов c, которые должны быть одномерный вектор той же длины, что и мой путь p.

Например, sp = BSpline(t, c0[0], k) выполняется без ошибок, как с c0[1] или c0[2], но, конечно, я ожидаю, что все коэффициенты вычисляется как splprep для использования.

Из здесь , похоже, что руководство по scipy интерполяции сбивает с толку:

tck [1]: x и y координаты перемещенных контрольных точек

В руководстве написано:

(t, c, k) кортеж, содержащий вектор узлов, B-сплайн коэффициенты и степень сплайна.

В конце концов, я неправильно использовал BSpline, неправильно интерпретировав его параметр коэффициентов сплайна .

Итак, как я могу построить BSpline из узлов и коэффициентов, возвращаемых splprep с BSpline или другой функцией?

1 Ответ

1 голос
/ 09 мая 2020

BSpline(t, k, c0) должно быть BSpline(t, c0, k)

EDIT. Фактически, есть еще одна проблема: splprep возвращает список массивов, который несовместим с BSpline.

Обратите внимание на разницу между splrep и spl p rep:

В основном splrep / splev согласованы, splrep / BSpline согласованы, а spl p rep / BSpline - нет. Это известная бородавка, которую нельзя исправить обратно совместимым способом.

Если вы хотите использовать их вместе, вам нужно транспонировать массив c. Исходя из вашего примера OP:

In [1]: import numpy as np
   ...: from scipy.interpolate import splev, splprep, BSpline
   ...: path =  [(2077.0, 712.0, 1136.6176470588234), (2077.0004154771536, 974.6
   ...: 30482962754, 1313.735294117647), (2077.1630960823995, 1302.460574562254,
   ...:  1490.8529411764707), (2078.1944091179635, 1674.693193015173, 1667.97058
   ...: 82352941), (2080.5096120056783, 2086.976611915444, 1845.0882352941176), 
   ...: (2085.1051468332066, 2711.054258877495, 2022.2058823529412), (1477.08461
   ...: 85328733, 2803.6223679691457, 2199.323529411765), (948.4693105162195, 28
   ...: 02.0390667447105, 2376.4411764705883), (383.8615403256207, 2804.84342413
   ...: 4807, 2553.5588235294117), (-41.6669725172834, 2497.067373170676, 2730.6
   ...: 76470588235), (-37.94311919744064, 1970.5155845437525, 2907.794117647059
   ...: ), (-35.97395938535092, 1576.713103381243, 3084.9117647058824), (-35.125
   ...: 016151504795, 1214.2319876178394, 3262.029411764706), (-35.0005507678645
   ...: 24, 893.3910350913443, 3439.1470588235297), (-35.0, 631.2108462417168, 3
   ...: 616.264705882353), (-35.0, 365.60545190581837, 3793.3823529411766), (-35
   ...: .0, 100.00005756991993, 3970.5)]
   ...: p = [[x for x,y,z in path], [y for x,y,z in path], [z for x,y,z in path]
   ...: ]
   ...: tck, u = splprep(p, k=3, s=0)      # ADDED s=0 for clarity
   ...: 

In [2]: t, c, k = tck

In [3]: c1 = np.asarray(c)

In [4]: spl = BSpline(t, c1.T, k)         # Note the transpose

In [5]: spl(u) - path                     # these should match, and they do
Out[5]: 
array([[ -4.54747351e-13,  -1.13686838e-13,  -4.54747351e-13],
       [  0.00000000e+00,  -1.13686838e-13,   0.00000000e+00],
       [ -4.54747351e-13,   0.00000000e+00,   0.00000000e+00],
       [  0.00000000e+00,  -2.27373675e-13,  -2.27373675e-13],
       [ -4.54747351e-13,   0.00000000e+00,   4.54747351e-13],
       [ -4.54747351e-13,   0.00000000e+00,  -6.82121026e-13],
       [  2.27373675e-13,   0.00000000e+00,   0.00000000e+00],
       [ -1.13686838e-13,  -4.54747351e-13,  -4.54747351e-13],
       [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00],
       [  4.26325641e-14,  -9.09494702e-13,   0.00000000e+00],
       [  1.42108547e-14,  -4.54747351e-13,   0.00000000e+00],
       [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00],
       [  7.10542736e-15,   0.00000000e+00,  -4.54747351e-13],
       [  0.00000000e+00,  -3.41060513e-13,   0.00000000e+00],
       [ -7.10542736e-15,  -1.13686838e-13,   0.00000000e+00],
       [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00],
       [  0.00000000e+00,   0.00000000e+00,   0.00000000e+00]])

Этот ответ основан на https://github.com/scipy/scipy/issues/10389. Применяется общее предложение: если вы хотите интерполяцию, предпочитайте make_interp_spline splrep и splprep. Если вы хотите сглаживания, на данный момент есть только FITPACK, либо splrep (который совместим с BSpline), либо splprep (где вам нужно транспонировать вручную).

...