我需要使用二维索引数组对三维数组(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]);
答案 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_axis
或fancy 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
不能在此处直接使用。问题是用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