[英]Compute center-of-mass in numpy
我正在寻找一种有效的方法来使用原生 python 和numpy
计算二维numpy
阵列的质心。 ( scipy.ndimage.measurements.center_of_mass
可以完成这项工作,但我只能使用 numpy)
# sample data
a = np.array([[0, 0, 0],
[0, 4, 4],
[0, 0, 0]])
center_of_mass(a)
>>> (1., 1.5) # expected output
(scipy.ndimage.measurements.center_of_mass 完成这项工作,但我只能使用 numpy)
然后听起来是时候阅读源代码了。 阅读后,对我而言,它看起来应该符合您的限制(仅使用 numpy ),因为它显然仅使用 python 内置插件和numpy
。 需要使用numpy.sum
的替换sum
。 编辑:根据@Ricoter 的评论添加了替换sum
的注释。
质心是sum(mi * xi)/m
, sum(mi * yi)/m
其中mi
是质量(= 数组的元素), xi
, yi
是坐标(数组的索引)。 m
是总质量,即sum(mi)
。
a = np.array([[0,1,2],[3,4,5]])
示例:
mi*xi
和mi*yi
我们通过将质量(即数组)与从mgrid
获得的坐标网格相乘得到:
a * np.mgrid[0:a.shape[0], 0:a.shape[1]]
这使
array([[[ 0, 0, 0],
[ 3, 4, 5]],
[[ 0, 1, 4],
[ 0, 4, 10]]])
其中上半部分为mi*yi
下半部分为mi*xi
,其总和为
(a * np.mgrid[0:a.shape[0], 0:a.shape[1]]).sum(1).sum(1)
这给出了array([12, 19])
。
将其除以总和a.sum()
我们得到array([0.8, 1.26666667])
的最终结果。
综上所述,我们有:
(a * np.mgrid[0:a.shape[0], 0:a.shape[1]]).sum(1).sum(1)/a.sum()
Scipy 执行相同的操作,但使用开放网格和广播而不是完整(密集)网格,因此对于较大的 arrays 更快,因为它不需要为媒体查找器结果分配 ZCD69B4957F06CD818D7ZBF3D61980E29。
一个更便宜的解决方案。 memory 和使用矩阵乘法的计算时间:
import numpy as np
def center_of_mass(array: np.ndarray):
total = array.sum()
# alternatively with np.arange as well
x_coord = (array.sum(axis=1) @ range(array.shape[0])) / total
y_coord = (array.sum(axis=0) @ range(array.shape[1])) / total
return x_coord, y_coord
a = np.asarray([[0, 0, 0],
[0, 4, 4],
[0, 0, 0]])
b = np.asarray([[0, 1, 2],
[3, 4, 5]])
print(center_of_mass(a)) # (1.0, 1.5)
print(center_of_mass(b)) # (0.8, 1.2666666666666666)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.