2015-02-02 9 views
12

aşağıdaki (wikipedia çıkarılan görüntünün) gibi bir şey yapmaya çalışıyorumSplaynlar

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

kodunun ilk bölümü kodudur (kontrol knot ve son noktalarını kullanarak) the main reference'dan çıkarıldı, ancak noktaları kontrol düğümü olarak nasıl kullanacağınız açıklanmadı.

Bu kodun sonucu, aşağıdaki görüntüdür.

enter image description here

puan örnekleridir, mavi çizgi dikkate tüm noktalar alır eğri olan. Ve kırmızı çizgi benim için çalışmıyor. tüm ara noktaları kontrol düğümleri olarak dikkate almaya çalışıyorum ama yapamam. knots=x[1:-1]'u kullanmaya çalışırsam işe yaramıyor. Herhangi bir yardım için minnettar olurum.

Soru: spline işlevindeki tüm ara noktaları nasıl kontrol düğümü olarak kullanırım?

Not: Bu son görüntü tam olarak ihtiyacım olan şeydir ve sahip olduğum (tüm noktaları geçme) ve ihtiyacım olan şey (kontrol düğümü ile spline) arasındaki farktır. Herhangi bir fikir? enter image description here

+0

Wow! NX (veya Unigrapics) kullanan bu toplulukta gördüğüm ilk kişi sizsiniz. :-) – fang

+0

Sadece ihtiyacım olan şeylerin temsili olarak kullanıyorum. Bunu python'da kodlamalıyım. =) – silgon

+0

Ne yapmak istediğiniz genel B-spline uygulamasıdır. Eğer scipy B-spline interpolasyonunu yapabilirse, halihazırda genel bir B-spline uygulamasına sahip olmalıdır. Bu, uygun API ile müşterilere maruz kalsa da bilinmemektedir. – fang

cevap

1

this link numaralı telefondan bir bézier ile ihtiyacım olan yanıtla gerçekten ilginç bir şey buldum. Sonra kendim denemek için kodu kullandım. Görünüşe göre iyi çalışıyor. Bu benim uygulamam:

#! /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() 

Örnek için bir görüntü. bézier implementation

Kırmızı noktalar kontrol noktalarını temsil eder.bu kadar =) Bir B-spline eğrisi, hem de de Boor algoritmasının Python uygulaması oluşturmada rol oynayan verilerin ayrıntılı bir açıklamasını bulabilirsiniz http://nbviewer.ipython.org/github/empet/geom_modeling/blob/master/FP-Bezier-Bspline.ipynb Bu ipython Notebook'lar

0

senin örneğin fonksiyonu periyodik olduğunu ve interpolate.splrep yöntemine per=True seçeneği eklemek gerekir.

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) 

Bu aşağıdaki give me:

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

Edit: Bu dizi olmayan bir periyodik alt kümesidir knots = x[-2:2] ile çalışma yaptı neden Bu aynı zamanda açıklıyor.

+0

Üzgünüz, kontrol etmedim, yarın sabah bir atış yapacağım. Yine de, spline'ın son noktasını gördüğüm şey gerçekten son nokta değil ve uygulamada gerçekten önemli bir şey. – silgon

+0

sadece bilgisayarımda test edildi, bu, verilerin son noktalarını splineların uç noktaları olarak dikkate almıyor: /, yani ... – silgon

1

Sanırım sorun seninle düğüm vektör yapmaktır. Çok fazla düğüm seçerseniz sorunlara neden olur, düğümler arasında bazı veri noktalarına sahip olması gerekir. Bu soru artık, sorunu o 5 knot, 6 vermek garip sonuçlar seçerek çalışır gibi görünüyor 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() 

çözer hataları verir.

+0

Daha önce yorumda bulunmadığım için üzgünüz, ilk bakışta ona bir şey vereceğim sabah. – silgon

+0

Sadece çirkin bir hata alıyorum http://pastebin.com/GNVGLsmF, ve bu arada, orada olmaması gereken bir parantez önce 1 var =) – silgon

+0

Örneği yeni güncelledim. Makinemde çalışan kodu kesip yapıştırdım. –

5

.

+0

+1, hatta dahası, +10 bunun için! Bu gerçekten güzel görünüyor, ben kesinlikle bu hafta sonu kontrol edeceğim (bundan önce yapamam). Çok teşekkürler. ;) – silgon

1

Ne isterseniz bspline değerlendirmek istiyorsanız, spline için uygun düğüm vektörü anlamaya ve ihtiyaçlarınızı karşılamak için manuel olarak tck yeniden oluşturmanız gerekir.

tck knot t + katsayıları c + eğri derecesi k için duruyor. splrep, verilen kontrol noktalarından geçen bir kübik eğri için tck hesaplar. Yani istediğini için kullanamazsın.

Aşağıdaki işlev, istediğiniz şey için uyarlanmış olan a similar question I asked some time ago. için benim çözümümüzü gösterecektir.

Eğlenceli gerçek:

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

Sonuç:

kodu herhangi boyutun eğrileri (1D, 2D, 3D, ..., EnD)

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 

Testi bunun için çalışıyor

An opened spline of various degrees