作为工作项目的一部分,我必须计算3D空间中一组点的质心。现在我以一种看似简单但天真的方式做到这一点 - 通过取每组点的平均值,如:
centroid = average(x), average(y), average(z)
其中x
,y
和z
是浮点数的数组。我似乎记得有一种方法可以获得更准确的质心,但我还没有找到一个简单的算法。任何人有任何想法或建议吗?我正在使用Python,但我可以调整其他语言的示例。
答案 0 :(得分:13)
不,这是点集合的质心的唯一公式。见维基百科:http://en.wikipedia.org/wiki/Centroid
答案 1 :(得分:11)
你含糊地提到“一种获得更准确的质心的方法”。也许你在谈论一个不受异常值影响的质心。例如,美国的平均家庭收入可能非常高,因为少数非常的富人倾向于平均水平;他们是“异常者”。因此,统计学家使用中位数。获得中位数的一种方法是对值进行排序,然后在列表中间选择值。
也许你正在寻找类似的东西,但对于2D或3D点。问题是,在2D和更高版本中,您无法排序。没有自然秩序。然而,有办法摆脱异常值。
一种方法是找到点的convex hull。凸包在点集的“外部”上具有所有点。如果你这样做,并扔出船体上的点,你将抛弃异常值,剩下的点将给出一个更“代表性”的质心。您甚至可以多次重复此过程,结果就像剥洋葱一样。事实上,它被称为“凸壳剥皮”。
答案 2 :(得分:8)
与此处的常见副词相反,有不同的方法来定义(和计算)点云的中心。您已经提出了第一个也是最常见的解决方案,我将不认为这有任何问题:
centroid = average(x), average(y), average(z)
这里的“问题”是它会根据你的分布点“扭曲”你的中心点。例如,如果你假设你的所有点都在一个立方体盒子或其他几何形状内,但大部分都恰好放在上半部分,你的中心点也会向那个方向移动。
作为替代方案,您可以使用每个维度中的数学中间值(极值的平均值)来避免这种情况:
middle = middle(x), middle(y), middle(z)
当你不太关心点数时,可以使用它,但更多关于全局边界框,因为这就是 - 你的点周围的边界框的中心。
最后,您还可以在每个维度中使用median
(中间的元素):
median = median(x), median(y), median(z)
现在,这将与middle
相反,实际上可以帮助您忽略点云中的异常值,并根据点的分布找到的中心点。
找到“好”中心点的更强大的方法可能是忽略每个维度中的最高和最低10%,然后计算average
或median
。如您所见,您可以通过不同方式定义中心点。下面我将向您展示2个2D点云的示例,并考虑到这些建议。
深蓝色点是平均(平均)质心。 中位数以绿色显示。 中间显示为红色。 在第二张图片中,您将看到我之前正在谈论的内容:绿点“更接近”点云的最密集部分,而红点距离它更远,考虑到最极端的边界。点云。
答案 3 :(得分:3)
你可以使用增加准确度求和 - Kahan求和 - 那是你的想法吗?
答案 4 :(得分:2)
可能效率更高:如果你多次计算,你可以通过保留两个常设变量来加快这一速度
N # number of points
sums = dict(x=0,y=0,z=0) # sums of the locations for each point
然后在创建或销毁点时更改N和求和。这会将事物从O(N)改变为O(1),以便在每次创建,移动或销毁点时以更多工作为代价进行计算。
答案 5 :(得分:0)
“更准确的质心”我相信质心是按照你计算的方式定义的,因此不会有“更准确的质心”。
答案 6 :(得分:0)
是的,这是正确的公式。
如果你有大量的点,你可以利用问题的对称性(无论是圆柱形,球形,镜面)。否则,您可以从统计数据中借用并平均随机数点,并且只是有一点误差。
答案 7 :(得分:0)
如果您的 n 维 向量在列表中 [[a0, a1, ..., an],[b0, b1, ..., bn],[c0 , c1, ..., cn]],只需将列表转换为数组,然后像这样计算质心:
import numpy as np
vectors = np.array(Listv)
centroid = np.mean(vectors, axis=0)
答案 8 :(得分:-1)
你明白了。你在计算的是质心或平均向量。