【问题标题】:Python Numpy array indexing and maskingPython Numpy 数组索引和屏蔽
【发布时间】:2019-01-08 12:31:34
【问题描述】:

我需要帮助使用 2 维索引数组来索引 3 维数组(RGB/BGR 图像)。对于不同的颜色通道,所有值都是 0、1 或 2。结果应该是一个二维的颜色值数组。如果有人能告诉我在 python 中的语法,那就太好了!

关于我正在尝试做的事情的背景(另请阅读下面的 TLDR):

我实际上是在尝试将以下代码从非常慢的普通 for 循环语法转换为更高效的 p​​ython/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} 的整体分布的平均值高出一个标准值以上。

到目前为止我的损坏代码:

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

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

  print(img[colorIDs]);

【问题讨论】:

  • 你能粘贴img的样本
  • 你的代码为什么/如何被破坏以及img的形状是什么?
  • @MadPhysicist 我的代码不完整,我不知道如何完成它以满足我的目标。我应该说不完整。
  • @najeem 图片应该是任何尺寸的通用图片,但为了您的方便,我会上传我正在使用的图片。

标签: python arrays numpy


【解决方案1】:

我认为您想将argmax 的二维索引掩码应用于第二轴:

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]])

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

np.take_along_axis(img, ids[:,:,None], 2)[:,:,0]

并设置值np.put_along_axis

【讨论】:

  • 这会创建 0 和 255 的掩码吗?
  • @MadPhysicist 沿轴方法是我正在寻找的(使用 2D 数组索引),但我无法将它应用到我正在做的事后。你的帖子解决了这个问题。
  • @hpaulj 感谢您向我提供有关 take_along_axis 的信息。我完全没有意识到这个功能。不幸的是,我认为 put_along_axis 的效果不如 OP 的情况。
【解决方案2】:

您可以将沿给定轴的数字索引转换为值,您可以使用np.take_along_axisfancy indexing。当使用花哨的索引时,您需要沿所有轴索引,其形状广播到最终结果的大小。 np.ogrid 对此有所帮助。对于 MxNx3 数组 img (M, 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 不能在这里直接使用。问题是用significant 掩盖ix 会使其形状相似性失效。但是,您可以在significant 标记的位置创建一个包含 255 的中间二维数组,并将其与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

【讨论】:

  • 什么是 M 和 N 变量?
  • 而且,最后一段代码中的星号对我来说没有运行,它说语法错误。
  • M 和 N 是高度和宽度。你用的是什么版本的 Python?
  • 你是对的。我可能没有解决这两个问题,但由于我在移动平台上,因此无法真正测试。一旦我有机会在几个小时内在桌面上玩这个游戏,我会通知你。
  • @akarshkumar0101。我已经通过实际测试修复了所有的代码 sn-ps。
猜你喜欢
  • 1970-01-01
  • 2021-08-19
  • 1970-01-01
  • 2011-08-11
  • 2018-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多