2015-02-02 10 views
12

Ich versucheSplines mit Python (unter Verwendung von Steuer Knoten und Endpunkte)

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() 

des Codes in etwa wie folgt (aus Wikipedia extrahiert Bild) zu tun Der erste Teil ist der Code extrahiert aus the main reference aber es wird nicht erklärt, wie die Punkte als Steuerknoten zu verwenden.

Das Ergebnis dieses Codes ist das folgende Bild.

enter image description here

Die Punkte sind die Proben, die blaue Linie ist die Spline unter Berücksichtigung aller Punkte. Und die rote Linie ist diejenige, die nicht für mich funktioniert. Ich versuche zu berücksichtigen alle Zwischenpunkte als Steuer Knoten aber ich kann einfach nicht. Wenn ich versuche, knots=x[1:-1] zu verwenden, um es funktioniert einfach nicht. Ich würde mich über jede Hilfe freuen.

Frage kurz: Wie benutze ich alle Zwischenpunkte als Kontrollknoten in der Spline-Funktion?

Hinweis: Dieses letzte Bild ist genau das, was ich brauche, und es ist der Unterschied zwischen dem, was ich habe (Spline alle Punkte) und was ich brauche (Spline mit Kontrollknoten). Irgendwelche Ideen? enter image description here

+0

Wow! Du bist die erste Person, die ich in dieser Community sehe, die NX (oder Unigrapics) benutzt. :-) – fang

+0

Ich benutze es nur als Darstellung dessen, was ich brauche. Ich muss das in Python programmieren. =) – silgon

+0

Was Sie tun möchten, ist die generische B-Spline-Implementierung. Wenn scipy B-Spline-Interpolation ausführen kann, müssen sie bereits eine generische B-Spline-Implementierung haben. Ob dies Clients mit der richtigen API offengelegt wird, ist jedoch unbekannt. – fang

Antwort

1

Ich habe gerade etwas wirklich interessant mit der Antwort, die ich mit einem bézier in this link benötigen. Dann habe ich den Code benutzt, um mich selbst zu testen. Es funktioniert offensichtlich gut. Dies ist meine Implementierung:

#! /usr/bin/python 
# -*- coding: utf-8 -*- 
import numpy as np 
import matplotlib.pyplot as plt 
from scipy.special import binom 

def Bernstein(n, k): 
    """Bernstein polynomial. 

    """ 
    coeff = binom(n, k) 

    def _bpoly(x): 
     return coeff * x ** k * (1 - x) ** (n - k) 

    return _bpoly 


def Bezier(points, num=200): 
    """Build Bézier curve from points. 

    """ 
    N = len(points) 
    t = np.linspace(0, 1, num=num) 
    curve = np.zeros((num, 2)) 
    for ii in range(N): 
     curve += np.outer(Bernstein(N - 1, ii)(t), points[ii]) 
    return curve 
xp = np.array([2,3,4,5]) 
yp = np.array([2,1,4,0]) 
x, y = Bezier(list(zip(xp, yp))).T 

plt.plot(x,y) 
plt.plot(xp,yp,"ro") 
plt.plot(xp,yp,"b--") 

plt.show() 

Und ein Bild für das Beispiel. bézier implementation

Die roten Punkte repräsentieren die Kontrollpunkte. Das ist es =)

0

Ihr Beispiel Funktion ist periodisch und Sie müssen die per=True Option zum interpolate.splrep Methode hinzuzufügen.

knots = x[1:-1] 
weights = np.concatenate(([1],np.ones(x.shape[0]-2)*.01,[1])) 
tck = interpolate.splrep(x, y, t=knots, w=weights, per=True) 

geben Sie mir dies:

results of your script with all internal knots and per=True option.

Edit: Dies erklärt auch, warum es mit knots = x[-2:2] tat Arbeit, die eine nicht-periodische Teilmenge des ganzen Bereichs ist.

+0

Sorry, ich habe es nicht überprüfen, werde ich ihm einen Schuss morgen früh geben. Nichtsdestotrotz ist der letzte Punkt des Splines nicht der eigentliche Endpunkt, und das ist eine wirklich wichtige Sache in der Anwendung. – silgon

+0

habe es gerade in meinem Computer getestet, es berücksichtigt nicht die Endpunkte der Daten als die Endpunkte der Splines: /, so ... – silgon

1

ich glaube, das Problem zu tun ist, mit Ihnen Vektor-Knoten. Es scheint Probleme zu verursachen, wenn Sie zu viele Knoten auswählen, es muss ein Datenpunkt zwischen den Knoten vorhanden sein. Diese Frage löst das Problem Bug (?) on selecting knots on scipy.insterpolate's splrep function

#!/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) 
print tck 
x2 = np.linspace(0, 10, 200) 
y2 = interpolate.splev(x2, tck) 

# spline with all the middle points as knots (not working yet) 
knots = np.asarray(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 
nknots = 5 
idx_knots = (np.arange(1,len(x)-1,(len(x)-2)/np.double(nknots))).astype('int') 
knots = x[idx_knots] 
print knots 

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() 

es scheint 5 Knoten zu arbeiten wählen, 6 geben wierd Ergebnisse gibt mehr die Fehler.

+0

Sorry für das nicht kommentieren vorher, ich werde es einen ersten Blick in die geben Morgen. – silgon

+0

Ich bekomme nur einen hässlichen Fehler http://pastebin.com/GNVGLsmF, und übrigens, es gibt eine 1 vor einer Klammer, die nicht da sein sollte =) – silgon

+0

Ich habe gerade das Beispiel aktualisiert. Ich habe den Code ausgeschnitten und eingefügt, der auf meinem Computer läuft. –

1

Wenn Sie eine bspline bewerten möchten, müssen Sie den entsprechenden Knotenvektor für Ihren Spline herausfinden und dann tck manuell nach Ihren Bedürfnissen neu erstellen.

tck steht für Knoten t + Koeffizienten c + Kurve Grad k. splrep berechnet tck für eine kubische Kurve, die die angegebenen Kontrollpunkte durchläuft. Sie können es also nicht für das verwenden, was Sie wollen.

Die folgende Funktion zeigt Ihnen meine Lösung für a similar question I asked some time ago., angepasst für was Sie wollen.

Fun Tatsache: Der Code funktioniert für Kurven in jeder 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 
    points = np.zeros((len(u),cv.shape[1])) 
    for i in xrange(cv.shape[1]): 
     points[:,i] = si.splev(u, (kv,cv[:,i],degree)) 

    return points 

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() 

Ergebnis:

An opened spline of various degrees

Verwandte Themen