我有一个numpy二维热图和两个重叠的掩码(大小不同)。我想用每个掩码唯一的numpy数组乘以这些掩码中的元素。首先,我从其中一个遮罩中移除重叠的坐标。然后我想在不使用循环的情况下提取每个掩码的热图元素。
原因是,事实上,我有超过10000个口罩,其中有一个可变的数字重叠。此外,我还有25张热图,大小为80000*80000。挑战在于创建一个快速且不需要太多内存的对数。
热图示例:
heatmap = array([[236, 235, 225, 226, 215],
[214, 217, 220, 215, 228],
[238, 227, 209, 210, 220],
[251, 224, 225, 220, 229],
[ 0, 226, 231, 233, 240]], dtype=uint64)
布尔掩码:
bool1=array([[ True, True, True, True, False],
[ True, True, True, True, False],
[ True, True, True, True, False],
[ True, True, True, False, False],
[False, False, False, False, False]], dtype=bool)
bool2=array([[False, False, False, False, False],
[False, False, False, True, False],
[False, False, True, True, True],
[False, False, True, True, True],
[False, False, True, True, True]], dtype=bool)
从第二个掩码中删除重叠坐标:
bool2[bool1]=False
现在,我按如下方式选择每个口罩的热图元素:
combined_bool=[bool1,bool2]
multiply_array1=np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])
multiply_array2=np.array([1,2,3,4,5,6]) #only 6 Trues in bool2 after duplicate cell removal
combined_mult= [multiply_array1,multiply_array2]
for i in range(0,len(combined_bool)):
mask=combined_bool[i]
heatmap[mask]=heatmap[mask]*combined_mult[i]
#output
array([[ 236, 470, 675, 904, 215],
[1070, 1302, 1540, 1720, 228],
[2142, 2270, 2299, 2520, 220],
[3263, 3136, 3375, 440, 687],
[ 0, 226, 924, 1165, 1440]], dtype=uint64)
在不使用for循环的情况下,如何对每个掩码进行乘法运算?
以下是一种使用NumPy broadcasting
和其他几种方法的矢量化方法-
# Concatenate all input multiply_arrays
combined_mult_arr = np.hstack((multiply_array1,multiply_array2))
# Concatenate all input boolean arrays
B = np.dstack((bool1,bool2))
# 3D mask with the uniqueness set
unqmask = (B.argmax(2) == np.arange(B.shape[2])[:,None,None]) & B.any(2)
# Get True indices in each 3D slice. Index into 1D version of heatmap & multiply
R,C = np.where(unqmask.reshape(unqmask.shape[0],-1))
heatmap.ravel()[C] *= combined_mult_arr
现在,为了验证代码,让我们再引入一个输入布尔和乘法数组。因此,让我们有一个与bool2
相同的附加bool3
,并将(0,4)元素设置为True
。因此,让我们将额外的multiply_array3
作为np.array([10])
。因此,经过这样修改的示例运行将如下图所示。
1) 输入:
In [126]: heatmap
Out[126]:
array([[ 236, 470, 675, 904, 2150],
[1070, 1302, 1540, 1720, 228],
[2142, 2270, 2299, 2520, 220],
[3263, 3136, 3375, 440, 687],
[ 0, 226, 924, 1165, 1440]])
In [127]: bool1
Out[127]:
array([[ True, True, True, True, False],
[ True, True, True, True, False],
[ True, True, True, True, False],
[ True, True, True, False, False],
[False, False, False, False, False]], dtype=bool)
In [128]: bool2
Out[128]:
array([[False, False, False, False, False],
[False, False, False, True, False],
[False, False, True, True, True],
[False, False, True, True, True],
[False, False, True, True, True]], dtype=bool)
In [129]: bool3
Out[129]:
array([[False, False, False, False, True],
[False, False, False, True, False],
[False, False, True, True, True],
[False, False, True, True, True],
[False, False, True, True, True]], dtype=bool)
In [130]: multiply_array1=np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])
...: multiply_array2=np.array([1,2,3,4,5,6])
...: multiply_array3=np.array([10])
...:
2) 运行代码:
In [133]: combined_mult_arr = np.hstack((multiply_array1,
...: multiply_array2,multiply_array3))
...: B = np.dstack((bool1,bool2,bool3))
...: unqmask = (B.argmax(2) == np.arange(B.shape[2])[:,None,None]) & B.any(2)
...: R,C = np.where(unqmask.reshape(unqmask.shape[0],-1))
...: heatmap.ravel()[C] *= combined_mult_arr
...:
3) 检查输出:
In [136]: heatmap
Out[136]:
array([[ 236, 470, 675, 904, 2150],
[1070, 1302, 1540, 1720, 228],
[2142, 2270, 2299, 2520, 220],
[3263, 3136, 3375, 440, 687],
[ 0, 226, 924, 1165, 1440]])
可以看出,当与具有两个输入情况的输出进行比较时,该输出中的唯一差异是(0,4)
处的2150
与之前的215
。这是因为元素为10
的第三个布尔数组和第三个乘法数组负责将(0,4)
元素缩放为10
。