You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python对多组相连线段集合进行曲线拟合?

针对线段集合的曲线拟合方案

核心思路

常规点回归方案不适用此类场景,需先将线段的几何信息转化为拟合可用的样本或约束,再通过非线性拟合方法逼近线段的整体趋势。

具体实现方案

1. 提取线段关键特征点

先从每条线段中提取能代表其位置与方向的点,作为拟合的基础样本集:

import numpy as np
from matplotlib.collections import LineCollection

# 输入线段格式:[[(x1,y1),(x2,y2)], ...]
def extract_sample_points(segments):
    samples = []
    for seg in segments:
        (x1,y1), (x2,y2) = seg
        # 添加线段中点
        mid_x, mid_y = (x1+x2)/2, (y1+y2)/2
        samples.append((mid_x, mid_y))
        # 可选:添加线段两端点,提升拟合精度
        samples.append((x1, y1))
        samples.append((x2, y2))
    return np.array(samples)

2. 非线性曲线拟合方法

方案A:B样条曲线拟合(推荐用于平滑趋势)

B样条能很好适配非线性平滑趋势,实现简单且效果稳定:

from scipy.interpolate import make_interp_spline
import matplotlib.pyplot as plt

# 替换为你的线段数据
your_segments = [...]

# 提取样本点并排序
samples = extract_sample_points(your_segments)
x, y = samples[:,0], samples[:,1]
sorted_idx = np.argsort(x)
x_sorted, y_sorted = x[sorted_idx], y[sorted_idx]

# 生成三次B样条曲线(k=3为平滑度较高的三次样条)
spl = make_interp_spline(x_sorted, y_sorted, k=3)
x_new = np.linspace(x_sorted.min(), x_sorted.max(), 500)
y_new = spl(x_new)

# 可视化结果
fig, ax = plt.subplots()
ax.add_collection(LineCollection(your_segments, color='gray', alpha=0.5))
ax.plot(x_new, y_new, color='red', linewidth=2, label='拟合曲线')
ax.legend()
plt.show()

方案B:多项式拟合(适合有明确趋势的非线性分布)

若线段整体趋势符合多项式特征,可使用最小二乘多项式拟合:

from numpy.polynomial.polynomial import Polynomial
import matplotlib.pyplot as plt

your_segments = [...]
samples = extract_sample_points(your_segments)
x, y = samples[:,0], samples[:,1]

# 拟合三次多项式(可根据趋势调整次数)
poly = Polynomial.fit(x, y, 3)
x_new = np.linspace(x.min(), x.max(), 500)
y_new = poly(x_new)

# 可视化
fig, ax = plt.subplots()
ax.add_collection(LineCollection(your_segments, color='gray', alpha=0.5))
ax.plot(x_new, y_new, color='blue', linewidth=2, label='多项式拟合曲线')
ax.legend()
plt.show()

方案C:基于线段距离最小化的拟合(精准贴合几何约束)

通过非线性优化,让拟合曲线到所有线段的距离之和最小,适合对拟合精度要求高的场景:

from scipy.optimize import minimize
import matplotlib.pyplot as plt

your_segments = [...]

# 定义三次多项式曲线模型
def curve_model(x, params):
    a, b, c, d = params
    return a*x**3 + b*x**2 + c*x + d

# 定义损失函数:曲线到所有线段的距离平方和
def loss(params, segments):
    total_dist = 0
    for seg in segments:
        (x1,y1), (x2,y2) = seg
        # 线段参数方程采样
        t_samples = np.linspace(0,1,10)
        for t in t_samples:
            sx = x1 + t*(x2-x1)
            sy = y1 + t*(y2-y1)
            cy = curve_model(sx, params)
            total_dist += (sy - cy)**2
    return total_dist

# 初始化参数并优化
init_params = np.random.rand(4)
result = minimize(loss, init_params, args=(your_segments,))
optimal_params = result.x

# 生成拟合曲线
x_min = min([min(seg[0][0], seg[1][0]) for seg in your_segments])
x_max = max([max(seg[0][0], seg[1][0]) for seg in your_segments])
x_new = np.linspace(x_min, x_max, 500)
y_new = curve_model(x_new, optimal_params)

# 可视化
fig, ax = plt.subplots()
ax.add_collection(LineCollection(your_segments, color='gray', alpha=0.5))
ax.plot(x_new, y_new, color='green', linewidth=2, label='距离最小化拟合曲线')
ax.legend()
plt.show()

方案选择建议

  • 线段趋势平滑时,优先选B样条拟合,实现简单且效果稳定;
  • 有明确多项式特征的趋势,用多项式拟合;
  • 需要严格贴合线段几何约束时,选距离最小化的非线性优化拟合,但计算量略大。

内容的提问来源于stack exchange,提问作者trent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 10:52:47