本篇文章將從以下幾個方面對Python貝塞爾曲線擬合進行闡述。
一、什麼是貝塞爾曲線
貝塞爾曲線是一種矢量圖形曲線,由兩個端點和一組控制點描述,曲線由這些點定義並插值。貝塞爾曲線常用於計算機輔助設計、製造和動畫等領域。
在計算機上,通常使用De Casteljau算法來計算貝塞爾曲線。簡單地說,該算法將一個貝塞爾曲線分解為一系列線性插值。通過遞歸地執行該過程,可以得到曲線上的任何點。
import numpy as np
def bezier(points, t):
"""
計算從控制點和時間值計算貝塞爾曲線
"""
n_points = len(points)
for i in range(1, n_points):
for j in range(n_points - i):
points[j] = (1 - t) * points[j] + t * points[j + 1]
return points[0]
points = np.array([[0, 0], [1, 1], [2, -1], [3, 0]])
for i in range(11):
t = i / 10
print(bezier(points, t))
二、Python實現貝塞爾曲線擬合
Python中可以使用SciPy庫中的optimize.curve_fit()函數來實現貝塞爾曲線擬合。該函數使用非線性最小二乘法來擬合一組數據,因此可以使用該函數來擬合任意形狀的曲線。
import numpy as np
from scipy.optimize import curve_fit
def bezier(t, *args):
"""
貝塞爾曲線函數
"""
n = len(args) // 2
points = np.array(args).reshape(n, 2)
for i in range(1, n):
for j in range(n - i):
points[j] = (1 - t) * points[j] + t * points[j + 1]
return points[0]
def fit_bezier_curve(x, y):
"""
通過擬合貝塞爾曲線來近似給定的一組數據
"""
n = len(x)
p0 = np.zeros(n * 2)
p0[::2] = x
p0[1::2] = y
popt, pcov = curve_fit(bezier, np.linspace(0, 1, n), p0)
return popt.reshape(n, 2)
x = np.array([0, 1, 2, 3])
y = np.array([0, 1, -1, 0])
points_fit = fit_bezier_curve(x, y)
print(points_fit)
三、擬合多條曲線
除了擬合一條曲線外,我們還可以使用同樣的方法擬合多條曲線。下面是一個示例,使用不同顏色的曲線來擬合一組數據。
import matplotlib.pyplot as plt
def fit_bezier_curves(x, y, n_curves):
"""
通過擬合多條貝塞爾曲線來近似給定的一組數據
"""
n = len(x)
t = np.linspace(0, 1, n)
p0 = np.zeros(n * 2)
p0[::2] = x
p0[1::2] = y
popt, pcov = curve_fit(bezier, t, p0)
points = popt.reshape(n, 2)
points_list = [points]
for i in range(1, n_curves):
dist = np.power(np.linalg.norm(points - points.mean(axis=0), axis=1), 2)
idx = np.argmax(dist)
t_left, t_right = t[:idx + 1], t[idx:]
points_left, points_right = points[:idx + 1], points[idx:]
p0 = np.zeros((n - idx - 1) * 2)
p0[::2] = x[idx + 1:]
p0[1::2] = y[idx + 1:]
popt, pcov = curve_fit(bezier, t_right, p0)
points_new = popt.reshape(n - idx - 1, 2)
points = np.vstack((points_left, points_new))
points_list.append(points)
return points_list
x = np.array([0, 1, 2, 3])
y = np.array([0, 1, -1, 0])
points_fit = fit_bezier_curves(x, y, 3)
plt.plot(x, y, 'o')
colors = ['r', 'g', 'b']
for i in range(len(points_fit)):
points = points_fit[i]
plt.plot(points[:, 0], points[:, 1], '-', color=colors[i])
plt.show()
四、總結
如上所述,Python中可以使用SciPy庫來擬合任意形狀的貝塞爾曲線。除了擬合一條曲線外,還可以使用相同的方法擬合多條曲線。在計算機輔助設計、製造和動畫等領域,貝塞爾曲線的應用廣泛。
原創文章,作者:ZJBCE,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/373537.html