【发布时间】:2020-04-27 11:59:43
【问题描述】:
我想通过将基于坐标质心的强度拆分到相邻像素来将浮点坐标添加到 numpy 数组。
以整数为例:
import numpy as np
arr = np.zeros((5, 5), dtype=float)
coord = [2, 2]
arr[coord[0], coord[1]] = 1
arr
>>> array([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
但是,当coord 是浮点数据时,我想在相邻像素之间分配强度,例如。 coord = [2.2, 1.7].
我考虑过使用高斯,例如:
grid = np.meshgrid(*[np.arange(i) for i in arr.shape], indexing='ij')
out = np.exp(-np.dstack([(grid[i]-c)**2 for i, c in enumerate(coord)]).sum(axis=-1) / 0.5**2)
效果很好,但对于 3d 数据和数千个点来说会变得很慢。
任何建议或想法将不胜感激,谢谢。
根据@rpoleski 的建议,取一个局部区域并按距离应用权重。这是一个好主意,虽然我的实现没有保持坐标的原始质心,例如:
from scipy.ndimage import center_of_mass
coord = [2.2, 1.7]
# get region coords
grid = np.meshgrid(*[range(2) for i in coord], indexing='ij')
# difference Euclidean distance between coords and coord
delta = np.linalg.norm(np.dstack([g-(c%1) for g, c, in zip(grid, coord)]), axis=-1)
value = 3 # pixel value of original coord
# create final array by 1/delta, ie. closer is weighted more
# normalise by sum of 1/delta
out = value * (1/delta) / (1/delta).sum()
out.sum()
>>> 3.0 # as expected
# but
center_of_mass(out)
>>> (0.34, 0.63) # should be (0.2, 0.7) in this case, ie. from coord
有什么想法吗?
【问题讨论】:
-
所以你有一个解决方案,但你想更快?
-
是的,我的想法确实有效,但对于实际使用来说太慢了。对数组进行切片可能会更快,并且只在该点周围评估一个小切片的高斯,可能是 3 或 4 sigma。我想知道是否有其他人遇到过这个问题,或者它是否有一个好的解决方案,因为我想它已经遇到了很多次,但我在搜索中找不到任何东西。
-
你没有说高斯是必需的。如果不是,那么您可以仅将强度分布到 4 个邻居:
arr[int(c[0]), int(c[1])]、arr[int(c[0])+1, int(c[1])]等,其值与与c的距离成正比。在您的解决方案中,我认为您的代码很慢,因为您将信号分布在整个阵列上并且np.exp()计算很慢。仅取附近的点并计算-distance_from_coords**2/2并将其用作np.exp()的参数。 -
@gnodab 是的,欧几里得距离不保持输入坐标的 CoM,但是,正如@rpoleski 所示,使用出租车或曼哈顿距离可以。
scipy库中还有cityblock函数,任何感兴趣的人都可以使用此功能。我以前不知道这件事,传递新信息总是好的:docs.scipy.org/doc/scipy/reference/generated/…
标签: python arrays numpy multidimensional-array