![8080e660e6abac16030f0f07b6eafd99.png](https://i-blog.csdnimg.cn/blog_migrate/6c2577045ae4ba4013e8b2cc0bc4b620.jpeg)
B-Spline
Beizer Curve
在之前我写过一篇关于 Beizer Curve 的文章,即使现在看起来依旧觉得 Beizer Curve 按照interpolation 定义推导出来结果真是美啊:
![71bfd1f8d57884294700d6b8106b7519.png](https://i-blog.csdnimg.cn/blog_migrate/98610c79260359eb9d9016d4167a54d6.png)
解:
这个有好几种看到方式,比如我们把
![9fafd8f3dc23f00f49c90436e8d8fa31.png](https://i-blog.csdnimg.cn/blog_migrate/998701591c340f729b7aa5ebb72de70d.png)
或者把它写成:
本质上也就是多项式,而且可以验证:
- t = 0,
- t = 1,
曲线并不过
![903af7ea9a31477a0ff09d82f3f3d58f.png](https://i-blog.csdnimg.cn/blog_migrate/22ca996894446674dcd38a02559c687b.png)
其实我的最爱还是写成矩阵形式:
B-Spline
样条的定义是: (n+1)个点, 包含
样条为了美观我们需要满足两个条件:
-
连续
- 曲线应该跟坐标系选择无关
由以上两个条件我们可以解得样条每一段的函数表示:
依旧可以模仿 Beizer Curve 我们把它写成:
![33183b1c4a6a59c023ca32f1d7a1b9aa.png](https://i-blog.csdnimg.cn/blog_migrate/314ec27e7471ce2868ea5a79b14ab63d.png)
同时我们可以算出开始点和结束点:
不同于 Bezier Curve,这里是完全不过控制点的:
![b0b50d0e47f0954451e8067b36983ee8.png](https://i-blog.csdnimg.cn/blog_migrate/8e19626eb473e6ea9de2c3026551386e.png)
问题在于大部分情况我们并不是给出了控制点,给出的是曲线上的点(如上图的knots),给出knots我们想求B-Spline,假设我们有 n+1 个 knots:
![06d553343d483181e98837fd159b9643.png](https://i-blog.csdnimg.cn/blog_migrate/02e0aadfbb3eb3cf981ff4061b7f2915.png)
或者:
![85cae33b2a0225beea4ac76afd118ef4.png](https://i-blog.csdnimg.cn/blog_migrate/bc934ba097c449313f699d5126b47679.png)
Scipy 库
我们也先来看一下用样条的原因,假设我这里有6个点,其实当然也可以用6次多项式来拟合:
![841016788e570d6847ae26642baf1625.png](https://i-blog.csdnimg.cn/blog_migrate/8fc1e9ff1e910304e3f4fcb1e1240a3d.png)
高次多项式的不好之处在于它波动太大了。
interp1d
使用 interp1d
import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate
points = [[0,1], [1, 1.1],[2, 1.2],[3,3],[4,2.9],[5,2.8],[6,2.7]]
x = [point[0] for point in points]
y = [point[1] for point in points]
f = np.polyfit(x, y, deg=6)
p = np.poly1d(f)
ls = interpolate.interp1d(x, y, kind = 'linear')
qs = interpolate.interp1d(x, y, kind = 'quadratic')
cs = interpolate.interp1d(x, y, kind = 'cubic')
x_new = np.linspace(x[0], x[-1], 100)
plt.scatter(x, y, label='data')
plt.plot(x_new, p(x_new), label = 'polynomial p6')
plt.plot(x_new, ls(x_new), label = 'linear spline')
plt.plot(x_new, qs(x_new), label = 'quadratic spline')
plt.plot(x_new, cs(x_new), label = 'cubic spline')
plt.legend(loc = 'upper left')
![4f948bc181fb40378b354ced88a2b9ee.png](https://i-blog.csdnimg.cn/blog_migrate/1796480409e171304fc805b913e39b77.png)
可以看到使用 interp1d
的 linear, quadratic, cubic
的不同效果,其实 quadratic 在这里也还表现不错。
发现还有一个scipy.interpolate.CubicSpline
, 效果基本等同于 interpolate.interp1d(x, y, kind = 'cubic')
.
Akima1DInterpolator
用这个 Akima1DInterpolator 来看这个例子的话:
![ce6d5ece5bd7affaef646673831d59b0.png](https://i-blog.csdnimg.cn/blog_migrate/58fba943a374fd68846a4bd5657a0942.png)
(⊙o⊙)…,不过大概是这个例子比较特殊,如果我们用最常用的正弦函数的话表现还可以,真是o(╯□╰)o:
![bb63cebca5d28cb7549252b82df770e3.png](https://i-blog.csdnimg.cn/blog_migrate/bb3aa9380814dfacb44e65b5129a0060.png)
splprep
然后发现 Scipy 还有一个 interpolate.splXXX, 按照官方的 doc 说法要用 spline interpolation需要两步:
- a spline representation of the curve is computed
- the spline is evaluated at the desired points
使用
spl = interpolate.splrep(x,y)
spline = interpolate.splev(x_new,spl)
和 cubic spline 的效果依旧类似,但是如果我们使用interpolate.splprep
看起来就不一样了,(๑˘ ˘๑)
tck,u = interpolate.splprep([x,y], k = 3, s = 0)
spline = interpolate.splev(np.linspace(0,1,100),tck)
plt.scatter(x, y, label='data')
plt.plot(x_new, cs(x_new), label = 'cubic spline')
plt.plot(x_new, f(x_new), label = 'Akima Interpolator')
plt.plot(spline[0], spline[1], label = "splprep")
plt.legend(loc = 'upper left')
![4451b6ac9ff27eba91064feb5606f615.png](https://i-blog.csdnimg.cn/blog_migrate/12ca35a3ba3ecfe54ce20fe5167d4cc0.jpeg)
Σ(っ °Д °;)っ 神奇! 感觉这个绿色的 splprep
看起来更自然一点啊,文档上:
- splprep: Find the B-spline representation of an N-dimensional curve.
- splrep: Find the B-spline representation of 1-D curve.
N-dimensional vs 1-D,感觉这个地方我看的也不是很懂(´◔ω◔)
使用 splprep 还有的附加好处是如果我们的点并不是向右的,我们传入的x不是递增的,那么 CubicSpline 会报错 ‘x
must be strictly increasing sequence’, 而 splprep 在这种情况下依旧能过输出合理的结果。
参考:
- pythonでxy座標上の離散点をスプライン補間
- <Curves and Surfaces for Computer Graphics>
- <Mathematics for 3D Game Programming and Computer Graphics, Third Edition>