根据相等比较条件将数组值分配给多维 numpy 数组?
Assigning an array value into a multidimensional numpy array based on an equality comparison condition?
我是 numpy 多维数组的新手,并且陷入了似乎应该是一个 "easy" 概念的问题。
在下面的代码中,fakepng
表示 numpy 数组中的 RGBA 图像。我想将该图像的每个纯黑色像素 [0,0,0]
的 Alpha 通道设置为 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]
但是,我在尝试找到 "right" numpy 函数 and/or 语法以使其成为 1 行和高效操作时迷路了。我不确定这是索引问题还是屏蔽问题,我是否需要矢量化函数,或者最好的概念是什么。
为了避免烦人的循环缓慢,您可以执行以下操作:
# 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]])
在这里,我们选择 所有行(:部分)并且在每一行中我们选择 除最后一列之外的所有列 (:-1 部分)。所以,我们正在访问的是以下数组:
array([[ 0, 0, 0],
[ 0, 255, 255],
[255, 255, 0],
[255, 255, 255]])
现在,我们通过aux_fakepng[:, :-1] == 0
比较每个元素是否等于0。此 returns 以下数组:
array([[ True, True, True],
[ True, False, False],
[False, False, True],
[False, False, False]])
但是,我们想要找到所有元素都为 0 的行,而不是数组等于 0 的行。为此,我们使用 np.all()
函数并将其应用于 axis=1
.这意味着该函数将检查行中的所有元素是否为 0。如果您想更好地理解 numpy
轴,请参阅 this page。该函数产生以下输出并将其分配给 idx_rows
:
array([ True, False, False, False])
最后,我们将在([0, 0, 0]
值)中发现黑色像素的那些行的 alpha 通道值更改为 0:
aux_fakepng[idx_rows, -1] = 0
通过这样做,我们正在访问其索引对应于 idx_rows
位置的行,其中找到了 True
值。在这些行中,我们正在访问最后一个元素(-1 索引),它对应于 alpha 通道,我们将其值设置为 0。
我是 numpy 多维数组的新手,并且陷入了似乎应该是一个 "easy" 概念的问题。
在下面的代码中,fakepng
表示 numpy 数组中的 RGBA 图像。我想将该图像的每个纯黑色像素 [0,0,0]
的 Alpha 通道设置为 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]
但是,我在尝试找到 "right" numpy 函数 and/or 语法以使其成为 1 行和高效操作时迷路了。我不确定这是索引问题还是屏蔽问题,我是否需要矢量化函数,或者最好的概念是什么。
为了避免烦人的循环缓慢,您可以执行以下操作:
# 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]])
在这里,我们选择 所有行(:部分)并且在每一行中我们选择 除最后一列之外的所有列 (:-1 部分)。所以,我们正在访问的是以下数组:
array([[ 0, 0, 0],
[ 0, 255, 255],
[255, 255, 0],
[255, 255, 255]])
现在,我们通过aux_fakepng[:, :-1] == 0
比较每个元素是否等于0。此 returns 以下数组:
array([[ True, True, True],
[ True, False, False],
[False, False, True],
[False, False, False]])
但是,我们想要找到所有元素都为 0 的行,而不是数组等于 0 的行。为此,我们使用 np.all()
函数并将其应用于 axis=1
.这意味着该函数将检查行中的所有元素是否为 0。如果您想更好地理解 numpy
轴,请参阅 this page。该函数产生以下输出并将其分配给 idx_rows
:
array([ True, False, False, False])
最后,我们将在([0, 0, 0]
值)中发现黑色像素的那些行的 alpha 通道值更改为 0:
aux_fakepng[idx_rows, -1] = 0
通过这样做,我们正在访问其索引对应于 idx_rows
位置的行,其中找到了 True
值。在这些行中,我们正在访问最后一个元素(-1 索引),它对应于 alpha 通道,我们将其值设置为 0。