基于相等比较条件将数组值分配给多维numpy数组吗?

问题描述 投票:0回答:1

我对numpy多维数组是陌生的,并且陷入似乎应该是一个“简单”的概念。

在下面的代码中,fakepng代表numpy数组内部的RGBA图像。我想将图像的每个纯黑色像素0的alpha通道设置为[0,0,0],以使其透明。我可以使用嵌套的for循环来做到这一点:

fakepng = np.array([[[0,0,0,255],[0,255,255,255]],[[255,255,0,255],[255,255,255,255]]])
rows, cols, channels = fakepng.shape
for x in range(0, rows):
    for y in range(0, cols):
        if (fakepng[x, y, 0] == 0 and fakepng[x, y, 1] == 0 and fakepng[x, y, 2] == 0):
            fakepng[x, y] = [0, 0, 0, 0]

但是,我迷失了寻找“正确的” numpy函数和/或语法以使其成为1行高效操作的迷路。我不确定这是索引还是掩码问题,是否需要向量化函数,或者最好的概念是什么。

python numpy numpy-ndarray array-broadcasting numpy-ufunc
1个回答
1
投票

为了避免烦人的for循环,您可以执行以下操作:

# 1. Create an auxiliary 2D array
aux_fakepng = fakepng.reshape(-1, 4)

# 2. Find all the rows in which all the elements but the last are 0
idx_rows = np.all(aux_fakepng[:, :-1] == 0, axis=1)

# 3. Set the alpha channel of those rows to 0
aux_fakepng[idx_rows, -1] = 0

注意,您正在修改aux_fakepng。由于您有两个引用指向同一数组,因此您对aux_fakepng所做的每次修改也会影响fakepng

编辑

由于某些人可能并不熟悉numpy和多维数组,因此我将尽我所能尽力解释这里发生的事情。

首先,我们首先创建一个指向fakepng的新引用。在此过程中,我们还将重塑数组,因此使用它更容易:

aux_fakepng = fakepng.reshape(-1, 4)

重塑数组时,我们指定新形状将为(-1, 4)。这意味着我们的新引用将具有4列,并且它将尝试考虑原始数组的其他维数以使其尽可能适合行数。请注意,如果该操作无法适合完美的数组(该数组中的所有行都有4列),则该操作可能会失败。

如果通道的值或多或少而不是4,我们可以执行以下操作:

aux_fakepng = fakepng.reshape(-1, fakepng.shape[-1])

通过这样做,我们使用的是fakepng值的最后一个值(指通道数)。

如前所述,此分配创建对原始数组的新引用。这意味着对aux_fakepng所做的每个修改也将影响fakepng,因为它们是同一对象。此分配不是深层副本(np.copy()之类的函数可以创建数组的深层副本。

一旦有了二维数组,我们需要找到所有RGB值都等于0的行。要找到这些行,我们可以执行以下操作:

idx_rows = np.all(aux_fakepng[:, :-1] == 0, axis=1)

但是,这是怎么回事? aux_fakepng[:, :-1]应该做什么?让我们先退后一步。

当前,这是aux_fakepng

array([[  0,   0,   0, 255],
       [  0, 255, 255, 255],
       [255, 255,   0, 255],
       [255, 255, 255, 255]])

在这里,我们选择ALL ROWS(:part),在每一行中,我们选择除最后一个之外的所有列(:-1部分)。因此,我们正在访问的是以下数组:

array([[  0,   0,   0],
       [  0, 255, 255],
       [255, 255,   0],
       [255, 255, 255]])

现在,我们通过执行aux_fakepng[:, :-1] == 0比较每个元素是否等于0。这将返回以下数组:

array([[ True,  True,  True],
       [ True, False, False],
       [False, False,  True],
       [False, False, False]])

但是,我们要查找所有元素均为0的行,而不是数组等于0的行。为此,我们使用np.all()函数,并将其沿axis=1应用。这意味着该函数将检查行中的所有元素是否均为0。如果要更好地理解this page轴,请参考numpy。该函数产生以下输出并将其分配给idx_rows

array([ True, False, False, False])

最后,我们将在([0, 0, 0]值)中发现黑色像素的那些行的alpha通道值更改为0:

aux_fakepng[idx_rows, -1] = 0

通过这样做,我们正在访问其索引对应于找到idx_rows值的True位置的行。在这些行内,我们访问与alpha通道相对应的最后一个元素(-1索引),并将其值设置为0。

© www.soinside.com 2019 - 2024. All rights reserved.