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

Python如何对二维形状进行重采样?工业机器轨迹计算场景

二维凸形曲线重采样的最优实现方案

针对你提到的二维凸形(闭合曲线)重采样需求,分两种核心场景给出落地实现,同时解释为什么时间序列工具不适合几何数据:


一、均匀弧长重采样(优先推荐)

核心逻辑

几何曲线的"均匀分布"指弧长维度的均匀,而非坐标空间的均匀。直接用时间序列插值会导致非圆曲线的点分布失衡(比如椭圆长轴点密、短轴点疏),正确步骤是:

  1. 计算原始点的累积弧长,把弧长作为曲线的参数
  2. 对x/y坐标做参数化样条插值(适配闭合曲线)
  3. 生成均匀间隔的弧长采样点,映射回坐标空间

代码实现

import numpy as np
from scipy.interpolate import splprep, splev

# 示例:原始25个点的椭圆凸形
theta = np.linspace(0, 2*np.pi, 25)
x = 2*np.cos(theta)
y = np.sin(theta)
original_points = np.vstack((x, y)).T

# 1. 计算每段弧长和累积弧长
dx = np.diff(x)
dy = np.diff(y)
seg_lengths = np.sqrt(dx**2 + dy**2)
cum_length = np.concatenate(([0], np.cumsum(seg_lengths)))
total_length = cum_length[-1]

# 2. 生成1000个均匀弧长采样点
num_new_points = 1000
new_lengths = np.linspace(0, total_length, num_new_points)

# 3. 闭合曲线参数化样条插值(s=0严格经过原始点)
tck, u = splprep([x, y], s=0, per=1)
# 把均匀弧长映射到样条参数u空间
new_u = np.interp(new_lengths, cum_length, u)
new_x, new_y = splev(new_u, tck)

# 最终重采样点集
resampled_points = np.vstack((new_x, new_y)).T

二、自适应密度重采样(尖锐处加密)

核心逻辑

针对圆角六边形这类有尖锐特征的凸形,需要在曲率大的区域(拐角)增加采样密度,步骤是:

  1. 通过样条导数计算原始曲线的曲率
  2. 生成与曲率成反比的采样间隔(曲率越大,间隔越小)
  3. 基于自适应间隔的弧长点做插值

代码实现

import numpy as np
from scipy.interpolate import splprep, splev
from scipy.ndimage import gaussian_filter1d

# 复用原始点和累积弧长(来自上一段代码)
x, y = original_points[:,0], original_points[:,1]
cum_length = cum_length
total_length = total_length

# 1. 计算并平滑曲率(闭合曲线)
tck, u = splprep([x, y], s=0, per=1)
dx_du, dy_du = splev(u, tck, der=1)
d2x_du2, d2y_du2 = splev(u, tck, der=2)
# 曲率公式:k = |x’ y'' - x'' y’| / (x’² + y’²)^(3/2)
curvature = np.abs(dx_du * d2y_du2 - d2x_du2 * dy_du) / (dx_du**2 + dy_du**2)**1.5
curvature_smoothed = gaussian_filter1d(curvature, sigma=1)

# 2. 生成自适应采样间隔(曲率越大,间隔越小)
min_step = total_length / 2000  # 最小间隔(保证尖锐处密度)
max_step = total_length / 500   # 最大间隔(避免平坦区过密)
# 调整系数100控制加密程度,按需修改
step_sizes = max_step / (1 + curvature_smoothed * 100)
step_sizes = np.clip(step_sizes, min_step, max_step)

# 3. 生成自适应弧长采样点
current_length = 0
new_lengths = [0]
while current_length < total_length - min_step:
    idx = np.argmax(cum_length >= current_length) - 1
    current_length += step_sizes[idx]
    new_lengths.append(current_length)
new_lengths[-1] = total_length  # 确保闭合
new_lengths = np.array(new_lengths)

# 4. 插值得到最终点集
new_u = np.interp(new_lengths, cum_length, u)
new_x, new_y = splev(new_u, tck)
adaptive_resampled_points = np.vstack((new_x, new_y)).T

为什么不推荐scipy.signal.resample?

这个工具是为时间序列设计的傅里叶插值,假设数据是随时间均匀采样的周期信号。但几何曲线的核心参数是弧长而非时间:

  1. 直接对x/y分别重采样会导致弧长分布失衡(比如椭圆长轴点密、短轴点疏)
  2. 针对闭合曲线,傅里叶插值会引入不必要的边界失真
  3. 无法实现基于曲率的自适应密度调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:40:19