Scipy:凸包的质心
Scipy: Centroid of convex hull
如何使用 python 和 scipy 计算凸包的质心?我找到的都是计算面积和体积的方法。
问候,坦率。
假设你已经使用 scipy.spatial.ConvexHull
构建了凸包,那么返回的对象应该有点的位置,所以质心可能很简单,
import numpy as np
from scipy.spatial import ConvexHull
points = np.random.rand(30, 2) # 30 random points in 2-D
hull = ConvexHull(points)
#Get centoid
cx = np.mean(hull.points[hull.vertices,0])
cy = np.mean(hull.points[hull.vertices,1])
你可以绘制如下,
import matplotlib.pyplot as plt
#Plot convex hull
for simplex in hull.simplices:
plt.plot(points[simplex, 0], points[simplex, 1], 'k-')
#Plot centroid
plt.plot(cx, cy,'x',ms=20)
plt.show()
scipy凸包是基于Qhull的,应该有centrum方法,来自Qhulldocs,
A centrum is a point on a facet's hyperplane. A centrum is the average of a facet's vertices. Neighboring facets are convex if each centrum is below the neighbor facet's hyperplane.
其中 centrum 与简单刻面的质心相同,
For simplicial facets with d vertices, the centrum is equivalent to the centroid or center of gravity.
因为 scipy 似乎没有提供这个,你可以在子 class 中定义你自己的 hull,
class CHull(ConvexHull):
def __init__(self, points):
ConvexHull.__init__(self, points)
def centrum(self):
c = []
for i in range(self.points.shape[1]):
c.append(np.mean(self.points[self.vertices,i]))
return c
hull = CHull(points)
c = hull.centrum()
要找到船体顶点的几何中心,只需使用,
# Calculate geometric centroid of convex hull
hull = ConvexHull(points)
centroid = np.mean(points[hull.vertices, :], axis=0)
尝试绘制船体,
import numpy as np
import pylab as pl
import scipy as sp
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d as a3
# Plot polyhedra
ax = a3.Axes3D(pl.figure())
facetCol = sp.rand(3)
for simplex in hull.simplices:
vtx = [points[simplex[0],:], points[simplex[1],:], points[simplex[2],:]]
tri = a3.art3d.Poly3DCollection([vtx], linewidths = 2, alpha = 0.8)
tri.set_color(facetCol)
tri.set_edgecolor('k')
ax.add_collection3d(tri)
# Plot centroid
ax.scatter(centroid0], centroid[1], centroid[2])
plt.axis('equal')
plt.axis('off')
plt.show()
如果船体周围的点分布不规则,或者至少会给出有偏差的答案,那么简单的 'mean' 方法是不正确的。我使用的最佳方法是计算船体点的 delaunay 三角形的质心。这将加权计算以将质心计算为形状的 COM,而不仅仅是顶点的平均值:
from scipy.spatial import ConvexHull, Delaunay
def _centroid_poly(poly):
T = Delaunay(poly).simplices
n = T.shape[0]
W = np.zeros(n)
C = 0
for m in range(n):
sp = poly[T[m, :], :]
W[m] = ConvexHull(sp).volume
C += W[m] * np.mean(sp, axis=0)
return C / np.sum(W)
poly = np.random.rand(30, 2)
# will calculate the centroid of the convex hull of poly
centroid_hull = _centroid_poly(poly)
像这样的东西应该有用。
如果船体周围有不规则间隔的点,此解决方案也是正确的。
import numpy as np
from scipy.spatial import ConvexHull
def areaPoly(points):
area = 0
nPoints = len(points)
j = nPoints - 1
i = 0
for point in points:
p1 = points[i]
p2 = points[j]
area += (p1[0]*p2[1])
area -= (p1[1]*p2[0])
j = i
i += 1
area /= 2
return area
def centroidPoly(points):
nPoints = len(points)
x = 0
y = 0
j = nPoints - 1
i = 0
for point in points:
p1 = points[i]
p2 = points[j]
f = p1[0]*p2[1] - p2[0]*p1[1]
x += (p1[0] + p2[0])*f
y += (p1[1] + p2[1])*f
j = i
i += 1
area = areaPoly(hull_points)
f = area*6
return [x/f, y/f]
# 'points' is an array of tuples (x, y)
points = np.array(points)
hull = ConvexHull(points)
hull_points = points[hull.vertices]
centroid = centroidPoly(hull_points)
如何使用 python 和 scipy 计算凸包的质心?我找到的都是计算面积和体积的方法。
问候,坦率。
假设你已经使用 scipy.spatial.ConvexHull
构建了凸包,那么返回的对象应该有点的位置,所以质心可能很简单,
import numpy as np
from scipy.spatial import ConvexHull
points = np.random.rand(30, 2) # 30 random points in 2-D
hull = ConvexHull(points)
#Get centoid
cx = np.mean(hull.points[hull.vertices,0])
cy = np.mean(hull.points[hull.vertices,1])
你可以绘制如下,
import matplotlib.pyplot as plt
#Plot convex hull
for simplex in hull.simplices:
plt.plot(points[simplex, 0], points[simplex, 1], 'k-')
#Plot centroid
plt.plot(cx, cy,'x',ms=20)
plt.show()
scipy凸包是基于Qhull的,应该有centrum方法,来自Qhulldocs,
A centrum is a point on a facet's hyperplane. A centrum is the average of a facet's vertices. Neighboring facets are convex if each centrum is below the neighbor facet's hyperplane.
其中 centrum 与简单刻面的质心相同,
For simplicial facets with d vertices, the centrum is equivalent to the centroid or center of gravity.
因为 scipy 似乎没有提供这个,你可以在子 class 中定义你自己的 hull,
class CHull(ConvexHull):
def __init__(self, points):
ConvexHull.__init__(self, points)
def centrum(self):
c = []
for i in range(self.points.shape[1]):
c.append(np.mean(self.points[self.vertices,i]))
return c
hull = CHull(points)
c = hull.centrum()
要找到船体顶点的几何中心,只需使用,
# Calculate geometric centroid of convex hull
hull = ConvexHull(points)
centroid = np.mean(points[hull.vertices, :], axis=0)
尝试绘制船体,
import numpy as np
import pylab as pl
import scipy as sp
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d as a3
# Plot polyhedra
ax = a3.Axes3D(pl.figure())
facetCol = sp.rand(3)
for simplex in hull.simplices:
vtx = [points[simplex[0],:], points[simplex[1],:], points[simplex[2],:]]
tri = a3.art3d.Poly3DCollection([vtx], linewidths = 2, alpha = 0.8)
tri.set_color(facetCol)
tri.set_edgecolor('k')
ax.add_collection3d(tri)
# Plot centroid
ax.scatter(centroid0], centroid[1], centroid[2])
plt.axis('equal')
plt.axis('off')
plt.show()
如果船体周围的点分布不规则,或者至少会给出有偏差的答案,那么简单的 'mean' 方法是不正确的。我使用的最佳方法是计算船体点的 delaunay 三角形的质心。这将加权计算以将质心计算为形状的 COM,而不仅仅是顶点的平均值:
from scipy.spatial import ConvexHull, Delaunay
def _centroid_poly(poly):
T = Delaunay(poly).simplices
n = T.shape[0]
W = np.zeros(n)
C = 0
for m in range(n):
sp = poly[T[m, :], :]
W[m] = ConvexHull(sp).volume
C += W[m] * np.mean(sp, axis=0)
return C / np.sum(W)
poly = np.random.rand(30, 2)
# will calculate the centroid of the convex hull of poly
centroid_hull = _centroid_poly(poly)
像这样的东西应该有用。
如果船体周围有不规则间隔的点,此解决方案也是正确的。
import numpy as np
from scipy.spatial import ConvexHull
def areaPoly(points):
area = 0
nPoints = len(points)
j = nPoints - 1
i = 0
for point in points:
p1 = points[i]
p2 = points[j]
area += (p1[0]*p2[1])
area -= (p1[1]*p2[0])
j = i
i += 1
area /= 2
return area
def centroidPoly(points):
nPoints = len(points)
x = 0
y = 0
j = nPoints - 1
i = 0
for point in points:
p1 = points[i]
p2 = points[j]
f = p1[0]*p2[1] - p2[0]*p1[1]
x += (p1[0] + p2[0])*f
y += (p1[1] + p2[1])*f
j = i
i += 1
area = areaPoly(hull_points)
f = area*6
return [x/f, y/f]
# 'points' is an array of tuples (x, y)
points = np.array(points)
hull = ConvexHull(points)
hull_points = points[hull.vertices]
centroid = centroidPoly(hull_points)