python 贝塞尔曲线_python – 使用多段三次贝塞尔曲线和距离以及曲率约束逼近数据...

我找到了满足我的criterea的解决方案.解决方案是首先找到近似于最小二乘意义的点的B样条,然后将该样条转换为多段贝塞尔曲线. B样条确实具有以下优点:与贝塞尔曲线相比,它们不会通过控制点以及提供指定近似曲线的期望“平滑度”的方式.生成这样的样条线所需的功能在FITPACK库中实现,scipy为其提供了python绑定.让我假设我将数据读入列表x和y,然后我可以这样做:

import matplotlib.pyplot as plt

import numpy as np

from scipy import interpolate

tck,u = interpolate.splprep([x,y],s=3)

unew = np.arange(0,1.01,0.01)

out = interpolate.splev(unew,tck)

plt.figure()

plt.plot(x,y,out[0],out[1])

plt.show()

结果如下所示:

如果我想让曲线更平滑,那么我可以将s参数增加到splprep.如果我希望近似值更接近数据,我可以减小s参数,以减少平滑度.通过以编程方式遍历多个参数,我可以找到符合给定要求的良好参数.

但问题是如何将该结果转换为贝塞尔曲线. Zachary Pincus在this email年的答案.我将在这里复制他的解决方案,以完整回答我的问题:

def b_spline_to_bezier_series(tck,per = False):

"""Convert a parametric b-spline into a sequence of Bezier curves of the same degree.

Inputs:

tck : (t,c,k) tuple of b-spline knots,coefficients,and degree returned by splprep.

per : if tck was created as a periodic spline,per *must* be true,else per *must* be false.

Output:

A list of Bezier curves of degree k that is equivalent to the input spline.

Each Bezier curve is an array of shape (k+1,d) where d is the dimension of the

space; thus the curve includes the starting point,the k-1 internal control

points,and the endpoint,where each point is of d dimensions.

"""

from fitpack import insert

from numpy import asarray,unique,split,sum

t,k = tck

t = asarray(t)

try:

c[0][0]

except:

# I can't figure out a simple way to convert nonparametric splines to

# parametric splines. Oh well.

raise TypeError("Only parametric b-splines are supported.")

new_tck = tck

if per:

# ignore the leading and trailing k knots that exist to enforce periodicity

knots_to_consider = unique(t[k:-k])

else:

# the first and last k+1 knots are identical in the non-periodic case,so

# no need to consider them when increasing the knot multiplicities below

knots_to_consider = unique(t[k+1:-k-1])

# For each unique knot,bring it's multiplicity up to the next multiple of k+1

# This removes all continuity constraints between each of the original knots,# creating a set of independent Bezier curves.

desired_multiplicity = k+1

for x in knots_to_consider:

current_multiplicity = sum(t == x)

remainder = current_multiplicity%desired_multiplicity

if remainder != 0:

# add enough knots to bring the current multiplicity up to the desired multiplicity

number_to_insert = desired_multiplicity - remainder

new_tck = insert(x,new_tck,number_to_insert,per)

tt,cc,kk = new_tck

# strip off the last k+1 knots,as they are redundant after knot insertion

bezier_points = numpy.transpose(cc)[:-desired_multiplicity]

if per:

# again,ignore the leading and trailing k knots

bezier_points = bezier_points[k:-k]

# group the points into the desired bezier curves

return split(bezier_points,len(bezier_points) / desired_multiplicity,axis = 0)

所以B-Splines,FITPACK,numpy和scipy救了我的一天:)

你可能感兴趣的:(python,贝塞尔曲线)