"ConvexHull", "alpha_shape" in python 为什么生成不同的面积值?

"ConvexHull", "alpha_shape" in python generate different area values why?

我正在尝试计算不规则多边形的面积。

我使用了“ConvexHull”和“alpha_shape”但是表面(面积)的输出不一样。

有什么建议吗?

您将在下面找到数据和用于计算面积的代码:

###################################################################

data = [(1.866200,4.379100),
(1.128700,4.814700),
(2.036000,3.074600),
(1.077500,6.100000),
(1.833300,7.126600),
(2.061200,8.399900),
(2.710500,9.418000),
(3.426000,9.141000),
(2.795400,2.644300),
(2.773300,1.400700),
(3.554100,1.084300),
(4.338900,2.025600),
(4.365600,9.981400),
(5.284800,9.657300),
(6.305400,10.194400),
(6.829000,9.124800),
(5.889000,4.120900),
(4.884500,1.854300),
(5.694300,2.821400),
(6.825100,6.487400),
(6.698000,5.189600),
(7.676500,8.884200),
(7.670500,7.610700)]

####################################################

import numpy as np

from shapely.geometry import Polygon

from scipy.spatial import ConvexHull, convex_hull_plot_2d

####################################################

hull = ConvexHull(data)

print('area of the surface = ', hull.volume)

####################################################

polygon = Polygon(data)

print('area of the surface = ', polygon.area)

你的形状多边形不是船体图形(它甚至不是凸面),所以它的面积较小也就不足为奇了:

import numpy as np    
from shapely.geometry import Polygon    
from scipy.spatial import ConvexHull, convex_hull_plot_2d
from matplotlib import pyplot as plt
   
hull = ConvexHull(data)    
print('area of the surface = ', hull.volume)
    
polygon = Polygon(data)    
print('area of the surface = ', polygon.area)

fig, ax = plt.subplots()
convex_hull_plot_2d(hull, ax=ax)
x, y = polygon.exterior.xy
ax.plot(x, y, c="red", ls="--", label="shapely")
ax.legend()
plt.show()

如果我们按照凸包对数据点进行排序,

data_shapely = [
    (2.710500,9.418000),
    (4.365600,9.981400),
    (6.305400,10.194400),
    (7.676500,8.884200),
    (7.670500,7.610700),
    (6.698000,5.189600),
    (5.694300,2.821400),
    (4.884500,1.854300),
    (3.554100,1.084300),
    (2.773300,1.400700),
    (1.128700,4.814700),
    (1.077500,6.100000),
    (2.061200,8.399900)    
    ]

polygon = Polygon(data_shapely)

那么面积是一样的:

area of the surface =  41.115790855
area of the surface =  41.11579085500001

您还误解了 shapely 如何计算 non-convex 多边形的面积。

data_shapely = [
    (0,0),
    (0,1),
    (1,1),
    (1,0)    
    ]

面积为 1 不足为奇。人们可能会认为

data_shapely = [
    (0,0),
    (1,1),
    (0,1),
    (1,0)    
    ]

根据其形状,面积为 0.5。然而,结果为 0,因为 non-convex 多边形中看似“翻转”的区域被计为负值。

如果您的点表现良好,并且您希望获得与通过相同点的多边形具有大致相同面积的凸包,则需要重新排序这些点。例如,您可以按关于重心的角度对它们进行排序:

data = np.array(data)
center = data.mean(0)
angle = np.arctan2(*(data - center).T[::-1])
index = np.argsort(angle)
polygon2 = Polygon(data[index])

剧情现在看起来好多了:

fig, ax = plt.subplots(1, 2)

ax[0].set_title("Original")
convex_hull_plot_2d(hull, ax=ax[0])
ax[0].plot(*polygon.exterior.xy, 'r--')

ax[1].set_title("Untangled")
convex_hull_plot_2d(hull, ax=ax[1])
ax[1].plot(*polygon2.exterior.xy, 'r--')
ax[1].plot(*center, 'kx')

plt.show()

事实上,您现在知道外壳仅比多边形大 10%:

>>> polygon2.area
37.25662339499999
>>> hull.volume
41.115790855
>>> polygon2.area / hull.volume * 100
90.61390434247064
>>> (hull.volume / polygon2.area - 1) * 100
10.35833929200876