使用curve_fit拟合悬链线出现异常大参数的问题求助
悬链线拟合参数异常问题
我拍摄了一条链条的照片,采样了每个链环的像素位置,想要拟合悬链线模型 a*cosh((x-x0)/a)+c 的最优参数(a、c、x0为待求参数)。采样点绘制到原图上与链条完全重合,但拟合得到的参数却比预期大数千倍。我尝试减少采样点数量、调整初始参数,但问题仍未解决。
问题原因
核心问题是图像坐标系的y轴方向与数学模型相反:
- 图像中y值越大表示位置越靠下(原点在左上角)
- 标准悬链线模型
c + a*cosh((x-x0)/a)的y值越大表示位置越靠上,且在x=x0处取得最小值(链条的最低点)
你的采样数据中,链条最低点对应图像的最高y值(约2624),这与模型的趋势完全相反,导致拟合算法收敛到错误的参数值。
解决方法
方法1:反转y轴数据
将采样的y值反转,使其符合模型的y轴方向:
y_max = y.max() y_inverted = y_max - y
然后用y_inverted代替原y值进行拟合。
方法2:修改悬链线模型
调整模型以适配图像的y轴方向,让模型在x=x0处取得最大值(对应链条最低点):
def cat(x, a, c, x0): return c - a * np.cosh((x - x0) / a)
修正后的完整代码
以下是包含y轴反转的修正代码,同时修复了未加载图像的问题:
from matplotlib import pyplot as plt from scipy.optimize import curve_fit import numpy as np fname = "C:/Users/marti/OneDrive/Desktop/Pier/Catenaria.txt" # 加载图像(替换为你的实际图像路径) img = plt.imread("your_image_path_here.jpg") plt.xlabel("x [pixels]") plt.ylabel("y [pixels]") plt.imshow(img) x, y = np.loadtxt(fname, unpack=True) # 反转y轴数据 y_max = y.max() y_inverted = y_max - y sigma_y = 3. plt.errorbar(x, y, sigma_y, fmt=".") def cat(x, a, c, x0): return c + a * np.cosh((x - x0) / a) # 基于反转后的数据设置合理初始参数 popt, pcov = curve_fit(cat, x, y_inverted, p0=(1000., 0., 2052.)) a_hat, c_hat, x0_hat = popt sigma_a, sigma_c, sigma_x0 = np.sqrt(pcov.diagonal()) print(f"a: {a_hat:.2f} ± {sigma_a:.2f}, c: {c_hat:.2f} ± {sigma_c:.2f}, x0: {x0_hat:.2f} ± {sigma_x0:.2f}") # 将拟合结果转换回原图像坐标系 y_fit = y_max - cat(x, a_hat, c_hat, x0_hat) plt.plot(x, y_fit, color='red', label='拟合悬链线') plt.legend() plt.show()
额外说明
- 初始参数的选择仍需合理:反转后的y值最小值为0(链条最低点),因此c的初始值可设为0,a的初始值可根据链条跨度估算(跨度约为3291像素,a值通常为跨度的1/4~1/2)
- 代码中修复了
img未加载的问题,需替换为你的实际图像路径
内容的提问来源于stack exchange,提问作者PIERGIORGIO GRECO
相关产品推荐
相关产品推荐

