如何创建一个包含n个参数的方程生成器,用于scipy



我正在将我的代码从MatLab移植到Python,有一个我做过但无法复制的巧妙技巧:

function [Equation, EquationComponents] = BezierEquation(n)
syms t x01 x02 x03 x04 x05 x06 x07 x08 x09 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 x38 x39 x40 x41;
xVar=[x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20,x21,x22,x23,x24,x25,x26,x27,x28,x29,x30,x31,x32,x33,x34,x35,x36,x37,x38,x39,x40,x41];
for i = 0:n
B(:,i+1)= nchoosek(n,i);
Pol(:,i+1)= (1-t)^(n-i)*t^i;
xVar2(:,i+1)=xVar(:,i+1);
end
EquationComponents=[xVar2;B;Pol];
Equation=sum(B.*xVar2.*Pol);
end

它所做的是生成一个具有n个参数的n阶贝塞尔方程。手动写出这个n=30或n=40的方程会很痛苦。

我目前正在尝试用scipy做同样的事情,并将其用于curve_filt,但我不知道如何创建一个可变参数的方程。我目前有一个n=5的手写示例。如何为任何n生成?curve_fit似乎不理解co不是标量。

import numpy as np
from scipy.special import comb
from scipy.optimize import curve_fit
class Bezier(object):
def __init__(self, n):
self.n = n
self.i = np.arange(0, n + 1)
self.n_minus_i = np.flip(self.i)
self.b = comb(n, self.i)
def generate_equation(self, x, co):
b = self.b
i = self.i
eq = []
for j, B in enumerate(b):
eq.append(B * (1 - x)**(self.n - i[j]) * x**i[j] * co[j])
return np.sum(eq)
def equation_5(self, x, a, b, c, d, e, f):
i = np.arange(0, 6)
B = comb(5, i)
return a*B[0]*(1-x)**(5-i[0])*x**i[0] + b*B[1]*(1-x)**(5-i[1])*x**i[1] + c*B[2]*(1-x)**(5-i[2])*x**i[2] + d*B[3]*(1-x)**(5-i[3])*x**i[3] + e*B[4]*(1-x)**(5-i[4])*x**i[4] + f*B[5]*(1-x)**(5-i[5])*x**i[5]

更新:

通过查看sympy库,我用它找到了一个简单的解决方案。我正在分享它,但我想为没有sympy的解决方案保留这个问题。也许使用numpy数组而不是变量,或者如果有一种方法可以通过拆包n个参数来创建lambda函数。类似于lambdify([x, *list_of_params], equation, 'numpy')中的拆包,但没有症状。

import numpy as np
from scipy.special import comb
from scipy.optimize import curve_fit
from sympy import symbols
from sympy import lambdify

def bezier_generator(n):
if n > 15:
return
i = np.arange(0, n + 1)
b = comb(n, i)
x, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15 = symbols(
"x, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15")
co = [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15]
eq = np.sum(b * (1 - x) ** (n - i) * x ** i * co[:n + 1])
func = lambdify([x, *co[:n + 1]], eq, 'numpy')
return func

如果我理解正确:

我想保留这个问题,以寻求一个没有症状的解决方案。也许使用numpy数组而不是变量

然后听起来你想从纯Python实现开始(将二项式函数外包给已经实现它的库,比如scipy(,并提升那些仍然不足以满足你最终使用它的部分:

from scipy.stats import binom
def evaluate_bezier_at(t, coords):
mt = 1 - t
sum = 0
n = len(coords)
for (i, w_i) in enumerate(coords):
sum += w_i * binom(n,i) * (mt ** (n-i)) * (t ** i)
return sum

(当然还有速度优化,但如果你使用的是30度以上的贝塞尔曲线,我有点假设你写的代码不是需要达到峰值性能的代码:没有人需要那么高的贝塞尔曲线=(

相关内容

  • 没有找到相关文章

最新更新