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

如何将ConvexHull凸包平滑为类椭圆形状,在Matplotlib散点图中绘制包围区域

平滑包围区域实现方案

这里分两种常用实现方式,你可以根据需求选择:


方案1:基于凸包的B样条平滑

该方案在你原有凸包逻辑的基础上做插值平滑,不会大幅偏离原始凸包的覆盖范围,适合需要严格贴合点集外围边界的场景。

额外依赖导入

需要补充导入以下库:

from scipy.spatial import ConvexHull
from scipy.interpolate import splprep, splev

改写后的encircle函数

def encircle(x, y, ax=None, smooth_level=0.5, sample_points=200, **kw):
    ax = ax or plt.gca()
    p = np.stack([x, y], axis=1)
    # 计算原始凸包
    hull = ConvexHull(p)
    # 提取凸包顶点并补全闭合路径
    hull_vertices = p[hull.vertices]
    hull_vertices = np.vstack([hull_vertices, hull_vertices[0]])
    # B样条插值生成平滑路径,per=True标识为闭合曲线
    tck, _ = splprep(hull_vertices.T, s=smooth_level, per=True)
    # 采样生成足够多的平滑点
    u_new = np.linspace(0, 1, sample_points)
    x_smooth, y_smooth = splev(u_new, tck)
    # 生成平滑多边形并添加到画布
    poly = patches.Polygon(np.c_[x_smooth, y_smooth], closed=True, **kw)
    ax.add_patch(poly)

参数说明:

  • smooth_level:平滑程度,数值越大平滑效果越强,数值越小越贴合原始凸包棱角,建议取值范围0.1~1
  • sample_points:平滑后采样的点数量,数值越高曲线越顺滑

方案2:正态分布置信椭圆

该方案直接基于点集的均值和协方差拟合椭圆,形状规则平滑,适合数据近似正态分布的场景。

改写后的encircle函数

def encircle(x, y, ax=None, n_std=2.2, **kw):
    ax = ax or plt.gca()
    p = np.stack([x, y], axis=1)
    # 计算点集均值、协方差矩阵
    mean = np.mean(p, axis=0)
    cov = np.cov(p, rowvar=False)
    # 计算特征值、特征向量确定椭圆长短轴方向
    vals, vecs = np.linalg.eigh(cov)
    order = vals.argsort()[::-1]
    vals, vecs = vals[order], vecs[:, order]
    # 计算椭圆旋转角度
    theta = np.degrees(np.arctan2(*vecs[:, 0][::-1]))
    # 计算长短轴长度,n_std为置信区间倍数,2对应95%数据覆盖范围
    width, height = 2 * n_std * np.sqrt(vals)
    # 生成椭圆并添加到画布
    ellipse = patches.Ellipse(xy=mean, width=width, height=height, angle=theta, **kw)
    ax.add_patch(ellipse)

参数说明:

  • n_std:控制椭圆覆盖范围,数值越大椭圆越大,建议设置为2~3保证所有目标点都在椭圆内

修改完encircle函数后直接运行你原有代码即可得到平滑的包围区域效果。

效果示意图

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 03:24:03