每个掩码分别选择和相乘numpy二维元素(无循环)



我有一个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

最新更新