Python Numpy数组索引和掩码

时间:2019-01-07 06:07:16

标签: python arrays numpy

我需要使用二维索引数组对三维数组(RGB / BGR图像)进行索引的帮助。对于不同的颜色通道,所有值均为0、1或2。结果应为2D颜色值数组。如果有人可以告诉我python中的语法,那就太好了!

关于我要执行的操作的上下文(另请阅读下面的TLDR):

我实质上是在尝试将以下代码从非常慢的普通for循环语法转换为更有效的python / numpy语法:

colorIndices = np.zeros((height,width));       # an array which has the index of the outstanding color
colorIndices -= 1;           # all -1's

for x in range(0,width):
    for y in range(0,height):

        pix = img[y,x];        # get the pixel, a 1D array of length 3
        colorID = np.argmax(pix);           #get which index has max value (candidate for outstanding color)

        if(pix[colorID]>np.average(pix)+np.std(pix)):      # if that value is more than one std dev away from the overall pixel's value, the pixel has an outstanding color
            colorIndices[y,x] = colorID;

然后,我想使用以下方法访问每个像素中的出色颜色通道:

img[:,:,:]=0;
img[colorIndices] = 255;

TLDR:如果像素是那种颜色的阴影,我想将其设置为纯蓝色,绿色或红色。我定义像素是否为红色阴影的方法是,像素的R值是否比{R,G,B}的总体分布平均值高出一个std。

到目前为止,我的破损代码是

  colorIDs = np.argmax(img, axis=2);

  averages = np.average(img, axis=2);
  stds = np.std(img, axis=2);
  cutoffs = averages + stds;

  print(img[colorIDs]);

Here is an example of the image I am using

2 个答案:

答案 0 :(得分:2)

我认为您想将noproxy的2d索引掩码应用于第二轴:

argmax

最近的numpy版本具有为我们执行此操作的功能

In [38]: img=np.random.randint(0,10,(16,16,3))
In [39]: ids = np.argmax(img, axis=2)
In [40]: ids
Out[40]: 
array([[0, 1, 2, 1, 2, 0, 0, 0, 2, 2, 1, 0, 1, 2, 1, 0],
       [0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1],
       [1, 1, 0, 0, 0, 0, 1, 2, 0, 2, 2, 1, 2, 1, 1, 0],
       [2, 0, 1, 2, 0, 0, 1, 1, 0, 2, 2, 1, 1, 1, 1, 2],
       [2, 2, 1, 1, 0, 1, 0, 2, 1, 0, 0, 2, 2, 0, 1, 2],
       [1, 0, 2, 1, 0, 2, 0, 1, 0, 1, 1, 2, 1, 1, 0, 2],
       [1, 0, 0, 0, 1, 2, 1, 0, 1, 2, 1, 1, 1, 2, 0, 0],
       [1, 2, 2, 2, 0, 0, 1, 1, 0, 1, 0, 2, 2, 1, 1, 0],
       [0, 2, 2, 1, 0, 0, 1, 0, 2, 1, 1, 0, 2, 1, 1, 0],
       [1, 0, 2, 1, 2, 0, 1, 1, 0, 2, 2, 2, 1, 1, 0, 1],
       [1, 1, 1, 1, 1, 2, 1, 1, 0, 2, 1, 0, 0, 1, 0, 0],
       [1, 2, 1, 0, 2, 2, 2, 1, 0, 1, 2, 1, 2, 0, 2, 1],
       [2, 0, 2, 1, 2, 0, 1, 1, 2, 2, 2, 2, 1, 0, 2, 1],
       [0, 1, 0, 0, 2, 0, 1, 0, 0, 0, 0, 2, 0, 2, 0, 1],
       [0, 1, 2, 1, 1, 0, 1, 2, 0, 1, 0, 0, 2, 1, 0, 2],
       [0, 0, 2, 2, 2, 2, 2, 1, 0, 0, 0, 2, 0, 0, 1, 1]])
In [41]: I,J = np.ix_(np.arange(16), np.arange(16))
In [42]: img[I,J,ids]
Out[42]: 
array([[5, 9, 9, 8, 8, 8, 5, 7, 1, 9, 9, 5, 5, 9, 6, 8],
       [6, 7, 5, 8, 5, 6, 9, 6, 7, 7, 7, 8, 3, 7, 9, 5],
       [7, 6, 8, 7, 6, 9, 6, 8, 9, 5, 8, 8, 9, 7, 9, 6],
       [8, 9, 3, 4, 7, 5, 8, 4, 4, 9, 1, 4, 9, 9, 9, 7],
       [9, 8, 9, 7, 9, 8, 7, 5, 8, 9, 9, 6, 9, 5, 8, 8],
       [7, 9, 8, 8, 9, 3, 6, 9, 8, 6, 8, 7, 7, 7, 7, 7],
       [8, 8, 5, 8, 9, 8, 8, 2, 8, 7, 8, 9, 5, 5, 6, 7],
       [9, 6, 6, 9, 5, 3, 6, 4, 7, 6, 8, 8, 6, 3, 9, 9],
       [7, 8, 9, 7, 5, 7, 5, 9, 6, 4, 7, 7, 8, 5, 7, 8],
       [9, 7, 6, 4, 8, 9, 3, 8, 9, 2, 6, 9, 6, 7, 9, 7],
       [9, 8, 6, 6, 5, 9, 3, 9, 2, 4, 9, 5, 9, 9, 6, 9],
       [8, 7, 8, 3, 8, 8, 9, 7, 9, 5, 9, 8, 6, 9, 7, 8],
       [8, 2, 7, 7, 4, 5, 9, 8, 8, 8, 6, 5, 3, 9, 9, 6],
       [6, 8, 8, 5, 8, 8, 8, 9, 3, 7, 7, 8, 5, 4, 2, 9],
       [3, 7, 9, 9, 8, 5, 9, 8, 9, 7, 3, 3, 9, 5, 5, 9],
       [8, 4, 3, 6, 4, 9, 9, 9, 9, 9, 9, 7, 9, 7, 5, 8]])

并设置值np.take_along_axis(img, ids[:,:,None], 2)[:,:,0]

答案 1 :(得分:1)

您可以沿给定轴将数字索引转换为值,可以使用np.take_along_axisfancy indexing。使用花式索引时,您需要沿所有轴索引其形状广播到最终结果大小的数组。 np.ogrid为此提供了帮助。对于MxNx3数组imgM, N, _ = img.shape),如果您有ix = np.argmax(img, axis=2),则索引应如下所示:

r, c = np.ogrid[:M, :N]
maxes = img[r, c, ix]

使用take_along_axis为您节省了一步和一些临时数组:

maxes = np.take_along_axis(img, ix, 2)

现在创建您的面具:

significant = np.abs(maxes - img.mean(axis=2) > img.std(axis=2))

这时,您有一个二维布尔蒙版和一个三维索引。最简单的事情可能是将所有内容转换为线性索引:

r, c = np.where(significant)

现在您可以构造输出了:

color_index = np.zeros_like(img)
color_index[r, c, ix[significant]] = 255

虽然诱人,np.put_along_axis不能在此处直接使用。问题是用ix遮盖significant会使形状相似性失效。但是,您可以在由significant标记的位置创建一个包含255的中间2D数组,并将其与put_along_axis一起使用:

values = np.zeros(significant.shape, dtype=img.dtype)
values[significant] = 255
color_index = np.zeros_like(img)
np.put_along_axis(color_index, ix, values, 2)

全部合并:

ix = np.argmax(img, axis=2)
significant = np.abs(np.take_along_axis(img, ix, 2) - img.mean(axis=2)) > img.std(axis=2)
color_index = np.zeros_like(img)
color_index[(*np.where(significant), ix[significant])] = 255