我需要在python中計算3D bspline曲線。我查看了scipy.interpolate.splprep和其他一些scipy模塊,但找不到任何能給我所需的東西。所以我寫下了自己的模塊。代碼工作正常,但速度很慢(測試函數運行在0.03s,這似乎很多,考慮到我只要求具有6個控制頂點的100個樣本)。numpy/scipy的快速b樣條算法
有沒有一種方法可以簡化下面的幾個scipy模塊調用的代碼,這可能會加快速度?如果不是,我可以通過我的代碼來改善其性能?
import numpy as np
# cv = np.array of 3d control vertices
# n = number of samples (default: 100)
# d = curve degree (default: cubic)
# closed = is the curve closed (periodic) or open? (default: open)
def bspline(cv, n=100, d=3, closed=False):
# Create a range of u values
count = len(cv)
knots = None
u = None
if not closed:
u = np.arange(0,n,dtype='float')/(n-1) * (count-d)
knots = np.array([0]*d + range(count-d+1) + [count-d]*d,dtype='int')
else:
u = ((np.arange(0,n,dtype='float')/(n-1) * count) - (0.5 * (d-1))) % count # keep u=0 relative to 1st cv
knots = np.arange(0-d,count+d+d-1,dtype='int')
# Simple Cox - DeBoor recursion
def coxDeBoor(u, k, d):
# Test for end conditions
if (d == 0):
if (knots[k] <= u and u < knots[k+1]):
return 1
return 0
Den1 = knots[k+d] - knots[k]
Den2 = knots[k+d+1] - knots[k+1]
Eq1 = 0;
Eq2 = 0;
if Den1 > 0:
Eq1 = ((u-knots[k])/Den1) * coxDeBoor(u,k,(d-1))
if Den2 > 0:
Eq2 = ((knots[k+d+1]-u)/Den2) * coxDeBoor(u,(k+1),(d-1))
return Eq1 + Eq2
# Sample the curve at each u value
samples = np.zeros((n,3))
for i in xrange(n):
if not closed:
if u[i] == count-d:
samples[i] = np.array(cv[-1])
else:
for k in xrange(count):
samples[i] += coxDeBoor(u[i],k,d) * cv[k]
else:
for k in xrange(count+d):
samples[i] += coxDeBoor(u[i],k,d) * cv[k%count]
return samples
if __name__ == "__main__":
import matplotlib.pyplot as plt
def test(closed):
cv = np.array([[ 50., 25., -0.],
[ 59., 12., -0.],
[ 50., 10., 0.],
[ 57., 2., 0.],
[ 40., 4., 0.],
[ 40., 14., -0.]])
p = bspline(cv,closed=closed)
x,y,z = p.T
cv = cv.T
plt.plot(cv[0],cv[1], 'o-', label='Control Points')
plt.plot(x,y,'k-',label='Curve')
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()
test(False)
真棒,非常感謝!在我的應用程序中完美地工作,其中有兩個結束的三維座標和一堆已知的三維控制點。它非常好地繪製樣條曲線! BRAVO!我正在使用三維圖像數據的ndarrays。 – kabammi
太棒了!你提示我編輯我的答案,並在最後刪除不需要的for循環。我還在最後提出了一個附錄,提到在scipy中添加的官方BSpline函數0.19.0 – Fnord
嗯......我遇到scipy_bspline函數的錯誤。我將一個列表作爲CV傳遞,因此cv = np.asarray(cv)對您的原始函數有幫助。然後我使用degree = 5,新函數會拋出一個錯誤,並告訴我需要至少12節...舊代碼不關心,只是工作。所以舊代碼爲我贏得勝利。 :) – kabammi