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

将二维点集分离为两条样条曲线以实现拐点检测

解决方案:分离双样条曲线、插值及拐点检测

1. 点集分离(基于K-Means聚类)

针对两条间距不固定的曲线,用K-Means指定2个聚类簇,可自动将点划分到两组,不受间距变化影响。

import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

# 假设points_on_edges为你的二维点数组(shape: (N,2))
kmeans = KMeans(n_clusters=2, random_state=42, n_init='auto')
labels = kmeans.fit_predict(points_on_edges)

# 分离两组点
group1 = points_on_edges[labels == 0]
group2 = points_on_edges[labels == 1]

# 可视化验证分离效果
plt.scatter(group1[:,0], group1[:,1], label='曲线1', c='red')
plt.scatter(group2[:,0], group2[:,1], label='曲线2', c='blue')
plt.xlabel('y-Koordinate')
plt.ylabel('z-Koordinate')
plt.legend()
plt.grid(True)
plt.show()

# 区分上下侧曲线(取z均值更小的为下侧)
lower_group = group1 if np.mean(group1[:,1]) < np.mean(group2[:,1]) else group2
upper_group = group2 if lower_group is group1 else group1

2. 样条插值(平滑样条)

使用UnivariateSpline生成平滑样条曲线,支持后续求导操作,更适合拐点检测:

from scipy.interpolate import UnivariateSpline

# 下侧曲线插值(先按y坐标排序,插值要求x单调)
lower_group_sorted = lower_group[np.argsort(lower_group[:,0])]
y_lower, z_lower = lower_group_sorted[:,0], lower_group_sorted[:,1]
# s为平滑参数,s=0严格过所有点,s越大曲线越平滑,可按需调整
spline_lower = UnivariateSpline(y_lower, z_lower, s=5)

# 上侧曲线同理
upper_group_sorted = upper_group[np.argsort(upper_group[:,0])]
y_upper, z_upper = upper_group_sorted[:,0], upper_group_sorted[:,1]
spline_upper = UnivariateSpline(y_upper, z_upper, s=5)

# 生成高密度点可视化
y_new = np.linspace(min(y_lower.min(), y_upper.min()), max(y_lower.max(), y_upper.max()), 500)
z_new_lower = spline_lower(y_new)
z_new_upper = spline_upper(y_new)

plt.scatter(lower_group[:,0], lower_group[:,1], label='下侧原始点', c='orange')
plt.plot(y_new, z_new_lower, label='下侧样条曲线', c='darkorange')
plt.scatter(upper_group[:,0], upper_group[:,1], label='上侧原始点', c='cyan')
plt.plot(y_new, z_new_upper, label='上侧样条曲线', c='darkcyan')
plt.xlabel('y-Koordinate')
plt.ylabel('z-Koordinate')
plt.legend()
plt.grid(True)
plt.show()

3. 拐点检测(基于二阶导数)

拐点对应曲线二阶导数为0且符号改变,通过样条求导找符合条件的点:

# 求下侧样条的二阶导数
spline_lower_second_deriv = spline_lower.derivative(n=2)

# 获取二阶导数的零点(拐点候选)
inflection_candidates_y = spline_lower_second_deriv.roots()

# 验证零点附近二阶导数符号变化,排除非拐点的极值点
valid_inflection_points = []
for y in inflection_candidates_y:
    y_left = y - 1e-4
    y_right = y + 1e-4
    if y_left >= y_lower.min() and y_right <= y_lower.max():
        deriv_left = spline_lower_second_deriv(y_left)
        deriv_right = spline_lower_second_deriv(y_right)
        if np.sign(deriv_left) != np.sign(deriv_right):
            valid_inflection_points.append(y)

# 转换为(y,z)坐标
inflection_points = np.array([[y, spline_lower(y)] for y in valid_inflection_points])

# 可视化拐点
plt.plot(y_new, z_new_lower, label='下侧样条曲线', c='darkorange')
plt.scatter(inflection_points[:,0], inflection_points[:,1], label='拐点', c='red', s=100, marker='x')
plt.xlabel('y-Koordinate')
plt.ylabel('z-Koordinate')
plt.legend()
plt.grid(True)
plt.show()

# 输出拐点坐标
print("下侧曲线拐点坐标:")
print(inflection_points)

关键调整说明

  • 若K-Means聚类效果不佳,可替换为DBSCAN密度聚类,只需调整eps和min_samples参数适配点集密度。
  • 样条平滑参数s需根据数据噪声程度调整,噪声大时增大s,需保留细节时设s=0。
  • 拐点检测的微小偏移量1e-4可根据坐标尺度调整,避免边界计算误差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 21:08:28