有没有比遍历2d数组的所有组件来获得特定范围内所有可能的蒙版更快的方法了,
import numpy as np
numOfLabels = 80
array2D = np.random.choice(255,(512,512))
for i in range(1,numOfLabels):
mask = array2D==i
也许可以广播并创建带有所有蒙版的3d阵列
编辑:
感谢您已经写好的答案。 为了更好的解释。我想做什么:
我有一个带有组件的二维标签矩阵。组件标有数字,例如1到80。我有两个图像。现在,我想为所有80个组件分别计算这两个图像的平均值,最大值,最小值。也许我有完全错误的想法去做。
EDIT2:
根据评论,我找到了一种使用以下代码的方法:
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
但是我想知道是否有一种更快的方法来获取写入字典的所有组件的所有统计信息,因为我不知道ndimage.measurements.labeled_comprehension是否很快,并且是否可以避免这种循环? / strong>
答案 0 :(得分:2)
您可以使用np.put_along_axis
一次创建所有遮罩。所有未标记的点都到达平面零:
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()
答案 1 :(得分:1)
这将使用广播创建3D蒙版阵列:
mask = array2D == np.arange(1, numOfLabels)[:, None, None]
例如
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]])
注意:我从您的代码中复制了标签范围,其中您以1
开始了范围。这意味着标签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]])
答案 2 :(得分:0)
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