如何设置SciPy插值器以最高精度保留车辆位置数据?
解决方案:基于曲率的自适应采样实现
你要的「在曲线变化剧烈区域密集采样、平缓区域稀疏采样」的需求,完全可以用SciPy实现,不需要机器学习算法。核心思路是基于曲线的曲率分配采样点——曲率越大(曲线越弯曲)的地方,采样点越密集;曲率越小(接近直线)的地方,采样点越稀疏。
具体实现代码
import numpy as np from scipy.interpolate import CubicSpline import matplotlib.pyplot as plt from matplotlib import cm def adaptive_reduce_dataset(x_list, y_list, num_interpolation_points): # 1. 用弧长参数化原始曲线,消除原始采样间隔的影响 points = np.array([x_list, y_list]).T segment_distances = np.sqrt(np.sum(np.diff(points, axis=0)**2, axis=1)) arc_lengths = np.insert(np.cumsum(segment_distances), 0, 0) t = arc_lengths / arc_lengths[-1] # 归一化到[0,1]区间 # 2. 用三次样条拟合出连续曲线,方便计算导数和曲率 cs_x = CubicSpline(t, x_list) cs_y = CubicSpline(t, y_list) # 3. 在密集采样点上计算曲率,衡量曲线弯曲程度 dense_t = np.linspace(0, 1, 1000) # 计算一阶导数(切线斜率) dx_dt = cs_x(dense_t, 1) dy_dt = cs_y(dense_t, 1) # 计算二阶导数(曲率相关) d2x_dt2 = cs_x(dense_t, 2) d2y_dt2 = cs_y(dense_t, 2) # 曲率公式:|x’*y'' - y’*x''| / (x’² + y’²)^(3/2) curvature = np.abs(dx_dt * d2y_dt2 - dy_dt * d2x_dt2) / (dx_dt**2 + dy_dt**2)**(3/2) curvature += 1e-6 # 避免曲率为0导致权重失效 # 4. 根据曲率生成自适应采样的参数点 cumulative_weight = np.cumsum(curvature) cumulative_weight /= cumulative_weight[-1] # 归一化累积权重 # 用均匀分布的权重映射到曲线参数t,实现曲率大的区域采样更密 target_weights = np.linspace(0, 1, num_interpolation_points) adaptive_t = np.interp(target_weights, cumulative_weight, dense_t) # 5. 用自适应参数点插值得到最终采样结果 new_xs = cs_x(adaptive_t) new_ys = cs_y(adaptive_t) return new_xs, new_ys # 替换为你的原始车辆位置数据(xs, ys) # xs, ys = ... # 生成50个自适应采样点 xs_adaptive, ys_adaptive = adaptive_reduce_dataset(xs, ys, 50) # 可视化结果 colors = cm.rainbow(np.linspace(0, 1, len(ys_adaptive))) plt.figure(figsize=(8,6)) for x, y, c in zip(xs_adaptive, ys_adaptive, colors): plt.scatter(x, y, color=c) plt.title("自适应采样结果") plt.show()
方法说明
- 弧长参数化:确保曲线参数的变化和实际车辆移动的距离一致,避免原始采样间隔不均带来的偏差。
- 三次样条拟合:将离散点转换为连续可导的曲线,为计算曲率提供基础。
- 曲率驱动采样:曲率直接反映曲线的弯曲程度,通过累积曲率权重的方式,把均匀分布的采样权重映射到曲线参数上,自动在弯曲区域分配更多采样点。
- 严格控制点数:通过
num_interpolation_points参数精准控制最终采样点数量,满足你的需求。
优化建议
- 如果原始数据存在噪声,可先对
xs和ys用scipy.signal.savgol_filter做平滑处理,避免曲率计算出现异常波动。 - 若想让弯曲区域的采样更密集,可将曲率替换为
curvature ** 2,放大高曲率区域的权重占比。
内容的提问来源于stack exchange,提问作者Java Weenis
相关产品推荐
相关产品推荐

