私はPythonで3D bspline曲線を計算する必要があります。私はscipy.interpolate.splprepといくつかの他のscipyモジュールを調べましたが、私が必要とするものを簡単に私に与えたものは見つかりませんでした。だから私は自分の下に自分のモジュールを書きました。コードは正常に動作しますが、遅いです(テスト関数は0.03秒で実行されますが、これは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)
以下の二つの画像は、私のコードは、閉じた状態の両方で返すものを示しています データをプロファイリングすることなく、最適化のヒントを与える
素晴らしい、本当にありがとうございました!私のアプリケーションで完璧に動作します。ここでは、2つの終わりの3次元座標と、既知の3次元制御点があります。それは非常によくスプラインをプロットします!ブラボ!!!私は3D画像データのndarraysを使って作業しています。 – kabammi
素晴らしい!あなたは私の答えを編集し、不要な最後のfor-loopを削除するように促しました。私はまた、scipyで追加された公式のBSpline関数について言及するために、最後に補遺を作成しました。0.19.0 – Fnord
Hmmm ...あなたのscipy_bspline関数でエラーが発生しました。私はCVとしてリストを渡すので、cv = np.asarray(cv)は元の関数に役立ちました。次にdegree = 5を使用して、新しい関数がエラーをスローし、少なくとも12ノットが必要であることを私に伝えます。古いコードは気にせず、ちょうどうまくいきました。だから古いコードが私にとって勝ちます。 :) – kabammi