Python 从鼠标坐标构建平滑曲线
在我正在进行的一个项目中,我每X毫秒获取一次鼠标坐标。我想画出这些坐标之间最可能的路径 举例来说: -在X ms之后,我可以得到这些(X,y)坐标:(0,0),(3,1),(5,4),(6,7) -在2*X毫秒后,我可以得到:(0,0),(3,1),(5,4),(6,7),(8,5),(11,-7) -等等 我想一步一步地在这些点之间画一条路径,一旦我画了一条路径,我就不能改变它(我迫不及待地要用所有的坐标来画这条线) 我开始考虑一个解决方案,通过计算多项式拟合在一对坐标之间画线:Python 从鼠标坐标构建平滑曲线,python,curve,points,smooth,Python,Curve,Points,Smooth,在我正在进行的一个项目中,我每X毫秒获取一次鼠标坐标。我想画出这些坐标之间最可能的路径 举例来说: -在X ms之后,我可以得到这些(X,y)坐标:(0,0),(3,1),(5,4),(6,7) -在2*X毫秒后,我可以得到:(0,0),(3,1),(5,4),(6,7),(8,5),(11,-7) -等等 我想一步一步地在这些点之间画一条路径,一旦我画了一条路径,我就不能改变它(我迫不及待地要用所有的坐标来画这条线) 我开始考虑一个解决方案,通过计算多项式拟合在一对坐标之间画线: import
import numpy as np
import matplotlib.pyplot as plt
def construct_path(points):
x = points[:,0]
y = points[:,1]
(x_new,y_new) = ([],[])
for i in range(0,len(x) - 2):
(x_tmp, y_tmp) = get_new_points(x[i:(i+3)], y[i:(i+3)], (i+3) == len(x))
(x_new,y_new) = (x_new + x_tmp.tolist(), y_new + y_tmp.tolist())
previous_points = [x_tmp,y_tmp]
return (x_new, y_new)
def get_new_points(x,y, end):
x = np.array(x)
y = np.array(y)
# calculate polynomial
z = np.polyfit(x, y, 2)
f = np.poly1d(z)
# calculate new x's and y's
if not end:
x_new = np.linspace(x[0], x[1], 11)
else:
x_new = np.linspace(x[0], x[1], 10, endpoint=False).tolist() + np.linspace(x[1], x[2], 11).tolist()
x_new = np.array(x_new)
y_new = f(x_new)
print(x_new, y_new)
return (x_new, y_new)
points = np.array([(0, 0), (3, 1), (5, 4), (6, 7), (8, 5), (11, -7) ])
x = points[:,0]
y = points[:,1]
(x_new, y_new) = construct_path(points)
plt.plot(x,y,'o',np.array(x_new),np.array(y_new))
plt.xlim([-2, 12])
plt.ylim([-10, 10])
plt.show()
结果还可以:
但当点具有接近的x或y(例如:(0,0)、(3,1)、(5.8,4)、(6,7)、(8,5)、(11,-7))时,它不起作用
编辑:找到了一些有趣的线索:
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate
def range_spline(x,y):
t = np.arange(x.shape[0], dtype=float)
t /= t[-1]
nt = np.linspace(0, 1, 100)
new_x = scipy.interpolate.spline(t, x, nt)
new_y = scipy.interpolate.spline(t, y, nt)
return (new_x,new_y)
def dist_spline(x,y):
t = np.zeros(x.shape)
t[1:] = np.sqrt((x[1:] - x[:-1])**2 + (y[1:] - y[:-1])**2)
t = np.cumsum(t)
t /= t[-1]
nt = np.linspace(0, 1, 100)
new_x = scipy.interpolate.spline(t, x, nt)
new_y = scipy.interpolate.spline(t, y, nt)
return (new_x, new_y)
x = np.array([ 0, 3, 6, 6, 8, 11, 8, 6, 6])
y = np.array([ 0, 1, 4, 7, 5, -7, -10, -10, -5])
#x = np.array([ 0, 2, 4])
#y = np.array([ 0, 2, 0])
(x1, y1) = range_spline(x,y)
(x2,y2) = dist_spline(x,y)
plt.plot(x,y, 'o')
plt.plot(x1, y1, label='range_spline')
plt.plot(x2, y2, label='dist_spline')
plt.legend(loc='best')
plt.show()
当有许多要点时,它工作得很好:
但当分数低于5分时(这是我想要的):
您可以尝试一些分段单调插值方法,如<代码>插值器在插值数据中保持单调性,并且如果数据不平滑,则不会超调。使用样条曲线而不是多项式拟合将使您受益,因为样条曲线也将匹配截面之间边界处的导数。我比较了不同的样条线方法(包括pchip),我认为这里可以使用相同的方法。