如何以矢量化的方式在3D NumPy矩阵中高效地进行像素投票以创建新的2D矩阵?

2024-06-08 15:47:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个(n, height, width)形状的NumPy矩阵,包含uint8范围内的灰度图像。每层(总共n层)包含一个神经网络预测。我想比较所有的n layers,并为每个像素获得第二个最常见的值,并用这个新值创建一个新的(height, width)形状矩阵。换句话说,我使用每像素投票从分层矩阵中的所有矩阵创建一个新的2D矩阵。我更喜欢第二个最常见的值,因为最常见的值是3,出于不同的原因,我想忽略这一点;这就是为什么我用mode(vote[vote != 3], axis=None)[0][0]搜索第二个最常见的值。以下是一个可行的解决方案。但是,它不是很快,因为我必须缓慢地迭代。我想使用矢量化解决方案来节省时间

import numpy
from scipy.stats import mode

n = 84
height = 1872
width = 3128

layered_image = numpy.ndarray(shape=(n, height , width), dtype=numpy.uint8)
image = numpy.ndarray(shape=(height , width), dtype=numpy.uint8)

for i in range(0, height):
    for j in range(0, width):
        vote = []
        for k in range(len(layered_image)):
            vote.append(layered_image[k][i][j])
        vote = numpy.asarray(vote, dtype=numpy.uint8)
        image[i][j] = mode(vote[vote != 3], axis=None)[0][0]

谢谢你的建议


Tags: inimagenumpyformoderange矩阵像素
2条回答

多亏了Divakarbincounting方法对我来说非常有效。为了防止在处理大量层时过度使用RAM,我在这个方法中添加了切片。这有点慢,但它允许在内存较少的机器上进行处理;假设slice_coordinates是一个列表,包含所有图像块的左上角坐标,这些图像块位于(y, x)prediction_overlay三维分层图像和prediction_mask新二维图像的元组中,切片工作如下:

for i in range(len(slice_coordinates)):
    to_process = prediction_overlay [:, slice_coordinates[i][0] : slice_coordinates[i][0] + tile_height, slice_coordinates[i][1] : slice_coordinates[i][1] + tile_width]

    b = bincount2D_vectorized(to_process.reshape(to_process.shape[0],-1).T)
    processed = b[:,:-1].argmax(1).reshape(to_process.shape[1:])

    prediction_mask [slice_coordinates[i][0] : slice_coordinates[i][0] + tile_height, slice_coordinates[i][1] : slice_coordinates[i][1] + tile_width] = processed

一种方法是外部广播平等-

np.equal.outer(layered_image,np.arange(3)).sum(0).argmax(-1)

另一种是掩模处理-

# a is the input layered_image
c0,c1,c2 = (a==0).sum(0), (a==1).sum(0), (a==2).sum(0)
out = np.where(np.maximum(c0,c1)>c2, np.where(c0>c1,0,1), 2)

另一个带有2D bincount-

# https://stackoverflow.com/a/46256361/ @Divakar
def bincount2D_vectorized(a):    
    N = a.max()+1
    a_offs = a + np.arange(a.shape[0])[:,None]*N
    return np.bincount(a_offs.ravel(), minlength=a.shape[0]*N).reshape(-1,N)

# a is the input layered_image
b = bincount2D_vectorized(a.reshape(a.shape[0],-1).T)
out = b[:,:-1].argmax(1).reshape(a.shape[1:])

相关问题 更多 >