作为工作项目的一部分,我必须计算 3D 空间中一组点的质心。现在我正在以一种看似简单但天真的方式来做这件事——通过取每组点的平均值,如下所示:

centroid = average(x), average(y), average(z)

在哪里 x, yz 是浮点数数组。我似乎记得有一种方法可以获得更准确的质心,但我还没有找到一个简单的算法来做到这一点。有人有什么想法或建议吗?我使用 Python 来实现此目的,但我可以改编其他语言的示例。

有帮助吗?

解决方案

与这里常见的说法相反,有不同的方法来定义(和计算)点云的中心。您已经建议了第一个也是最常见的解决方案,我将 不是 认为这有什么问题:

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 点云的示例,并考虑到这些建议。

深蓝色点是平均质心。中位数以绿色显示。中间显示为红色。在第二张图片中,您将确切地看到我之前所说的内容:考虑到点云的最极端边界,绿点“更接近”点云最密集的部分,而红点距离点云最密集的部分更远。

enter image description here enter image description here

其他提示

不,这是点集合质心的唯一公式。参见维基百科: http://en.wikipedia.org/wiki/Centroid

您含糊地提到“一种获得更准确质心的方法”。也许您正在谈论不受异常值影响的质心。例如, 平均的 美国的家庭收入可能非常高,因为少数人 非常 富人扭曲了平均水平;他们是“异常值”。因此,统计学家使用 中位数 反而。获取中位数的一种方法是对值进行排序,然后选择列表中间的值。

也许您正在寻找类似的东西,但是是 2D 或 3D 点。问题是,在二维及更高维中,您无法排序。没有自然顺序。尽管如此,还是有一些方法可以消除异常值。

一种方法是找到 凸包 的点。凸包具有点集“外部”的所有点。如果您这样做,并丢弃船体上的点,您将丢弃异常值,而剩下的点将给出更具“代表性”的质心。你甚至可以重复这个过程几次,结果就像剥洋葱一样。事实上,这就是所谓的“凸壳剥离”。

您可以使用增加准确度求和 - Kahan 求和 - 这就是您的想法吗?

可能更有效:如果您多次计算此值,则可以通过保留两个常设变量来加快计算速度

N  # number of points
sums = dict(x=0,y=0,z=0)  # sums of the locations for each point

然后每当创建或销毁点时更改 N 和总和。这会将计算的复杂度从 O(N) 更改为 O(1),但每次创建、移动或销毁点时都会增加更多工作量。

“更准确的质心”我相信质心是按照您计算的方式定义的,因此不可能有“更准确的质心”。

是的,这是正确的公式。

如果你有大量的点,你可以利用问题的对称性(无论是柱面、球面、镜面)。否则,您可以借用统计数据并对随机数量的点进行平均,但只会有一点误差。

你说对了。您正在计算的是质心或平均向量。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top