Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Splines with Python (using control knots and endpoints)

I'm trying to do something like the following (image extracted from wikipedia)

spline

#!/usr/bin/env python
from scipy import interpolate
import numpy as np
import matplotlib.pyplot as plt

# sampling
x = np.linspace(0, 10, 10)
y = np.sin(x)

# spline trough all the sampled points
tck = interpolate.splrep(x, y)
x2 = np.linspace(0, 10, 200)
y2 = interpolate.splev(x2, tck)

# spline with all the middle points as knots (not working yet)
# knots = x[1:-1]  # it should be something like this
knots = np.array([x[1]])  # not working with above line and just seeing what this line does
weights = np.concatenate(([1],np.ones(x.shape[0]-2)*.01,[1]))
tck = interpolate.splrep(x, y, t=knots, w=weights)
x3 = np.linspace(0, 10, 200)
y3 = interpolate.splev(x2, tck)

# plot
plt.plot(x, y, 'go', x2, y2, 'b', x3, y3,'r')
plt.show()

The first part of the code is the code extracted from the main reference but it's not explained how to use the points as control knots.

The result of this code is the following image.

enter image description here

The points are the samples, the blue line is the spline taking into account all the points. And the red line is the one that is not working for me. I'm trying to take into account all the intermediate points as control knots but I just can't. If I try to use knots=x[1:-1] it just doesn't work. I'd appreciate any help.

Question in short: how do I use all the intermediate points as control knots in the spline function?

Note: this last image is exactly what I need, and it's the difference between what I have (spline passing all the points) and what I need (spline with control knots). Any ideas? enter image description here

like image 607
silgon Avatar asked Feb 02 '15 13:02

silgon


People also ask

What are spline knots?

towardsdatascience.com. Splines. Splines are simply parts of the whole polynomial line. The line is split into few knots where every two knots are connected by a polynomial line which is determined by the user. This essentially eliminates the influence of a single data point on the global polynomial curve.

What is the use of control points in a spline curve?

In computer-aided geometric design a control point is a member of a set of points used to determine the shape of a spline curve or, more generally, a surface or higher-dimensional object. are nonnegative and sum to one. This property implies that the curve lies within the convex hull of its control points.

What is TCK in spline?

tck stands for knots t + coefficients c + curve degree k .

What is spline in Python?

WHAT IS A SPLINE? A Spline is essentially a piecewise regression line. Trying to fit one regression line over a very dynamic set of data can let to a lot of compromise. You can tailor your line to fit one area well, but then can often suffer from overfitting in other areas as a consequence.


1 Answers

If what you want is to evaluate a bspline, you need to figure out the appropriate knot vector for your spline and then manually rebuild tck to fit your needs.

tck stands for knots t + coefficients c + curve degree k. splrep calculates tck for a cubic curve that passes through the given control points. So you can't use it for what you want.

The function below will show you my solution for a similar question I asked some time ago., adapted for what you want.

Fun fact: the code works for curves of any dimension (1D,2D,3D,...,nD)

import numpy as np
import scipy.interpolate as si


def bspline(cv, n=100, degree=3):
    """ Calculate n samples on a bspline

        cv :      Array ov control vertices
        n  :      Number of samples to return
        degree:   Curve degree
    """
    cv = np.asarray(cv)
    count = cv.shape[0]

    # Prevent degree from exceeding count-1, otherwise splev will crash
    degree = np.clip(degree,1,count-1)

    # Calculate knot vector
    kv = np.array([0]*degree + range(count-degree+1) + [count-degree]*degree,dtype='int')

    # Calculate query range
    u = np.linspace(0,(count-degree),n)

    # Calculate result
    return np.array(si.splev(u, (kv,cv.T,degree))).T

Test it:

import matplotlib.pyplot as plt
colors = ('b', 'g', 'r', 'c', 'm', 'y', 'k')

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

plt.plot(cv[:,0],cv[:,1], 'o-', label='Control Points')

for d in range(1,5):
    p = bspline(cv,n=100,degree=d,periodic=True)
    x,y = p.T
    plt.plot(x,y,'k-',label='Degree %s'%d,color=colors[d%len(colors)])

plt.minorticks_on()
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.xlim(35, 70)
plt.ylim(0, 30)
plt.gca().set_aspect('equal', adjustable='box')
plt.show()

Result:

An opened spline of various degrees

like image 167
Fnord Avatar answered Oct 15 '22 17:10

Fnord