简体   繁体   English

Python:获取数组所有掩码的最快方法

[英]Python: Fastest way to get all masks for an array

Is there a faster way than looping through all components of a 2d array to get all possible masks in a specific range like: 有没有比遍历2d数组的所有组件来获得特定范围内所有可能的蒙版更快的方法,例如:

import numpy as np
numOfLabels = 80
array2D = np.random.choice(255,(512,512))
for i in range(1,numOfLabels):
    mask = array2D==i

Maybe something with broadcasting and creating a 3d array with all masks 广播和创建带有所有遮罩的3d阵列

EDIT: 编辑:

Thanks for the already written answers. 感谢您已经书面的答案。 For better explanation. 为了更好的解释。 What im trying to do: 我要做什么:

I have an 2d label matrix with components. 我有一个带有组件的二维标签矩阵。 The components are labeled with numbers, lets say 1 to 80. I have two images. 组件标有数字,例如1到80。我有两个图像。 Now i want to calculate the mean,max,min of those two images for all 80 compoents each. 现在,我想为所有80个组件分别计算这两个图像的平均值,最大值,最小值。 Maybe I had the totaly wrong idea to do that. 也许我有完全错误的想法去做。

EDIT2: EDIT2:

According to the comment I found a way with the following code: 根据评论,我找到了一种使用以下代码的方法:

from scipy import ndimage
import numpy as np

def calculateMeanMaxMin(val):
    return np.array([np.mean(val),np.max(val),np.min(val)])

def getTheStatsForComponents(array1,array2):
    ret, thresholded= cv2.threshold(array2, 50, 255, cv2.THRESH_BINARY)
    thresholded= thresholded.astype(np.uint8)
    numLabels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresholded, 8, cv2.CV_8UC1)
    allComponentStats=[]
    meanmaxminArray2 = ndimage.labeled_comprehension(array2, labels, np.arange(1, numLabels+1), calculateMeanMaxMin, np.ndarray, 0)
    meanmaxminArray1 = ndimage.labeled_comprehension(array1, labels, np.arange(1, numLabels+1), calculateMeanMaxMin, np.ndarray, 0)
    for position, label in enumerate(range(1, numLabels)):
        currentLabel = np.uint8(labels== label)
        _, contour, _ = cv2.findContours(currentLabel, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
        (side1,side2)=cv2.minAreaRect(contour[0])[1]
        componentStat = stats[label]
        allstats = {'position':centroids[label,:],'area':componentStat[4],'height':componentStat[3],
                              'width':componentStat[2],'meanArray1':meanmaxminArray1[position][0],'maxArray1':meanmaxminArray1[position][1],
                              'minArray1':meanmaxminArray1[position][2],'meanArray2':meanmaxminArray2[position][0],'maxArray2':meanmaxminArray2[position][1],
                              'minArray2':meanmaxminArray2[position][2]}
        allComponentStats.append(allstats)
    return allComponentStats

But I wonder if there is a faster way to get all Stats for all components written to a dictionary , because i dont know if ndimage.measurements.labeled_comprehension is fast, and if i somehow can avoid this loop? 但是我想知道是否有一种更快的方法来获取写入字典的所有组件的所有统计信息,因为我不知道ndimage.measurements.labeled_comprehension是否很快,并且是否可以避免这种循环?

You can use np.put_along_axis to create all masks at once. 您可以使用np.put_along_axis一次创建所有蒙版。 All non labeled points go to plane zero: 所有未标记的点都转到平面零:

all_masks = np.zeros((numOfLabels, *array2D.shape), bool)
np.put_along_axis(all_masks, array2D*(array2D<numOfLabels)[None], True, axis=0)

# check
for i in range(1,numOfLabels):
    assert (all_masks[i] == (array2D==i)).all()

This creates the 3-D array of masks, using broadcasting: 这将使用广播创建3D蒙版阵列:

mask = array2D == np.arange(1, numOfLabels)[:, None, None]

Eg 例如

In [26]: numOfLabels = 80                                                                                          

In [27]: array2D = np.random.choice(255, (512, 512))                                                               

In [28]: mask = array2D == np.arange(1, numOfLabels)[:, None, None]                                                

In [29]: mask.shape                                                                                                
Out[29]: (79, 512, 512)

In [30]: array2D[:10, :13]                                                                                         
Out[30]: 
array([[111, 161, 109, 235, 193, 224,  63,  78, 106, 245, 140,  64,  28],
       [245, 239, 225,  31, 239, 212, 137,  17, 130, 185, 110,  70,  55],
       [251,  65, 114, 199, 229, 241,  97,  84,  13,  10,   4, 114, 185],
       [217, 252, 205,  94,  93, 202,  99,  91,  65,  34,  86,  84, 233],
       [115,  51, 217, 105, 187,  61, 203,  30, 178, 178, 183, 193, 231],
       [ 75, 195,  21, 143, 180,  32,  38, 224, 188,  85,  80, 250,   4],
       [163, 174,  35,  49, 202, 110, 223, 209,  80,  38, 127,  31, 208],
       [137, 133,  41,  30, 193, 187, 182, 171,  72, 151, 180, 152,  14],
       [145, 108, 112, 254,  92,  87,  45, 173,  45,  28, 189, 248,  48],
       [147, 222,  37,  31, 198,  69,   8, 136,  85, 162, 225, 203,  68]])

Note: I copied the range of labels from your code, where you start the range with 1 . 注意:我从您的代码中复制了标签范围,从1开始。 That means the mask for the label 4 will be at index 3 : 这意味着标签4的掩码将在索引3

In [31]: mask[3, :10, :13].astype(int)  # Display bools as ints for compact output                                                                               
Out[31]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [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, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

array2D==i give you the position where array2D == i, although I do not understand what you are trying to do, you can modify the code by array2D==i给您的位置是array2D == i,尽管我不明白您要做什么,但是您可以通过以下方式修改代码

import numpy as np
numOfLabels = 80
array2D = np.random.choice(255,(512,512))
mask = np.zeros((512,512,numOfLabels))
for i in range(numOfLabels):
    mask[array2D==i, i] = 1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM