如何使用 Python 在一组点上绘制多边形(部分向内弯曲)边缘?

Posted

技术标签:

【中文标题】如何使用 Python 在一组点上绘制多边形(部分向内弯曲)边缘?【英文标题】:How to draw a polygon (parts was bent inward) edge on a group of points with Python? 【发布时间】:2019-11-01 23:56:48 【问题描述】:

我正在尝试在如下所示的 K-Means 集群上绘制多边形(凹)边(图 1)。

在@ypnos 的帮助下,这段代码绘制了除边缘之外的所有内容。

df = pd.read_csv('https://raw.githubusercontent.com/MachineIntellect/dataset.ml/master/watermelon/watermelon_4_0.csv')
X = df.iloc[:,1:].to_numpy()
m0 = X[5]
m1 = X[11]
m2 = X[23]
centroids = np.array([m0, m1, m2])
labels = pairwise_distances_argmin(X, centroids)
m0 = X[labels == 0].mean(0)
m1 = X[labels == 1].mean(0)
m2 = X[labels == 2].mean(0)
new_centroids = np.array([m0, m1, m2])
plt.xlim(0.1,0.9)
plt.ylim(0, 0.8)
plt.scatter(X[:,0], X[:,1])
plt.scatter(new_centroids[:,0], new_centroids[:,1], c='r', marker = '+')
for i in range(3):    
    points = X[labels == i]
    hull = ConvexHull(points)
    for simplex in hull.simplices:
        plt.plot(points[simplex, 0], points[simplex, 1], 'r-')

(图_2)

The scikit-learn doc 似乎很鼓舞人心

问题是图1中箭头所指的边与图2中对应的边不同。

箭头所指的多边形边缘向内弯曲(感谢@dwilli)。

感谢@ImportanceOfBeingErnest 的提醒,scipy.spatial.ConvexHull 可能无法出凹。

有没有其他模块/包可以做到这一点(凹)?

任何提示将不胜感激。

【问题讨论】:

要检查 fig1 和 fig2,您需要向我们提供 fig1 的代码/输入 凸包是凸的,它们不会产生凹线。 您试图重现的图形可能是用户绘制的多边形... 一些相关链接:Method for determining if a line segment is an external edge of a Delauney triangulation?, How to deal with the (undesired) triangles that form between the edges of my geometry when using Triangulation in matplotlib building-concave-hulls-alpha-shapes-with-pyqt-shapely-and-arcpy 【参考方案1】:

您的灵感展示的是 Voronoi 图。图中任何坐标的颜色显示,它将关联到哪个集群。

您在第一个图中显示的多边形是集群成员凸包的粗略近似值。您可以使用 scipy.spatial.ConvexHullcv2.convexHull()(来自 OpenCV)来计算它。前者的文档也给出了example on how to plot it。

【讨论】:

感谢您的回答。我们就快到了。我刚刚更新了这个问题。请你抽空看看吗?【参考方案2】:

要生成多边形,您可以尝试以下步骤

在每个集群周围生成多边形,将每个集群视为绘图的单独部分。

您可以使用@ypnos 提到的凸包方法创建一个粗糙的多边形,但要获得更好的结果,请查看Delaunay triangulation method

您将根据设置的阈值在点之间生成三角形区域。阈值将确保最佳拟合。

使用此数据,您可以使用极值点绘制凹壳。由于您不希望将极值点作为多边形的顶点包含在内,因此您应该添加一个缓冲区以通过设定值绕过这些点。

一些样本数据的预期结果

获得结果需要相当多的代码,here 是生成示例图的综合指南的链接。

【讨论】:

感谢您的回答。这是鼓舞人心的。但它似乎太复杂了,we can tighten up that convex hull 部分已经杀死了笔记本。你自己运行笔记本吗?

以上是关于如何使用 Python 在一组点上绘制多边形(部分向内弯曲)边缘?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用一个 VBO 绘制一组点?

包含一组点的多边形

python+opencv2快速找出一组点包围的区域中的所有点

将R中一组点的边界作为多边形返回?

如何在Scatter Series谷歌图表上绘制自定义多边形?

地图上绘制多边形