numpy多维索引和函数"take" [英] numpy multidimensional indexing and the function 'take'

查看:91
本文介绍了numpy多维索引和函数"take"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一周的奇数天里,我几乎了解numpy中的多维索引. Numpy具有功能'take'似乎可以满足我的要求,但是还可以控制索引超出范围时发生的情况 具体来说,我有一个要查询的3维数组

On odd days of the week I almost understand multidimensional indexing in numpy. Numpy has a function 'take' which seems to do what I want but with the added bonus that I can control what happens if the indexing is out of rangect Specifically, I have a 3-dimensional array to ask as the lookup-table

lut = np.ones([13,13,13],np.bool)

和一个2x2的3个长向量数组,用作表的索引

and a 2x2 array of 3-long vectors to act as indexes into the table

arr = np.arange(12).reshape([2,2,3]) % 13 

IIUC,如果我要写lut[arr],则arr被视为2x2x3的数字数组,当将它们用作lut的索引时,它们各自返回13x13数组.这解释了为什么lut[arr].shape is (2, 2, 3, 13, 13).

IIUC, if I were to write lut[arr] then arr is treated as a 2x2x3 array of numbers and when these are used as indexes into lut they each return a 13x13 array. This explains why lut[arr].shape is (2, 2, 3, 13, 13).

我可以通过写作使它做我想做的事

I can make it do what I want by writing

lut[ arr[:,:,0],arr[:,:,1],arr[:,:,2] ] #(is there a better way to write this?)

,现在这三个术语的作用就好像它们已被压缩以生成2x2的元组数组,而lut[<tuple>]则根据lut生成单个元素一样.最终结果是来自lut的2x2条目数组,正是我想要的.

and now the three terms act as if they have been zipped to produce a 2x2 array of tuples and lut[<tuple>] produces a single element from lut. The final result is a 2x2 array of entries from lut, just what I want.

我已经阅读了获取"功能的文档...

I have read the documentation for the 'take' function ...

此功能与花式"索引功能相同 (使用数组索引数组);但是,它可以更容易 如果需要沿给定轴的元素,则可以使用.

This function does the same thing as "fancy" indexing (indexing arrays using arrays); however, it can be easier to use if you need elements along a given axis.

axis:int,可选
选择值的轴.

axis : int, optional
The axis over which to select values.

也许天真地,我以为设置axis=2我会得到三个值作为3元组来执行查找,但是实际上

Perhaps naively, I thought that setting axis=2 I would get three values to use as a 3-tuple to perform the lookup but actually

np.take(lut,arr).shape =  (2, 2, 3)
np.take(lut,arr,axis=0).shape =  (2, 2, 3, 13, 13)
np.take(lut,arr,axis=1).shape =  (13, 2, 2, 3, 13)
np.take(lut,arr,axis=2).shape =  (13, 13, 2, 2, 3)

所以很明显我不明白发生了什么.谁能告诉我如何实现我想要的?

so it's clear I don't understand what is going on. Can anyone show me how to achieve what I want?

推荐答案

最初的问题是试图在表中进行查找,但是 一些索引超出范围,我想控制 发生这种情况时的行为.

The original problem was trying to do a lookup in a table but some of the indexes were out of bounds and I wanted to control the behaviour when this happened.

import numpy as np
lut = np.ones((5,7,11),np.int) # a 3-dimensional lookup table
print("lut.shape = ",lut.shape ) # (5,7,11)

# valid points are in the interior with value 99,
# invalid points are on the faces with value 0
lut[:,:,:] = 0
lut[1:-1,1:-1,1:-1] = 99

# set up an array of indexes with many of them too large or too small
start = -35
arr = np.arange(start,2*11*3+start,1).reshape(2,11,3)

# This solution has the advantage that I can understand what is going on
# and so I can amend it if I need to

# split arr into tuples along axis=2
arrchannels = arr[:,:,0],arr[:,:,1],arr[:,:,2]

# convert into a flat array but clip the values
ravelledarr = np.ravel_multi_index(arrchannels, lut.shape, mode='clip')

# and now turn back into a list of numpy arrays
# (not an array of the original shape )
clippedarr = np.unravel_index( ravelledarr, lut.shape)
print(clippedarr[0].shape,"*",len(clippedarr)) # produces (2, 11) * 3

# and now I can do the lookup with the indexes clipped to fit
print(lut[clippedarr])

# these are more succinct but opaque ways of doing the same
# due to @Divakar and @hjpauli respectively
print( np.take(lut, np.ravel_multi_index(arr.T, lut.shape, mode='clip')).T )
print( lut.flat[np.ravel_multi_index(arr.T, lut.shape, mode='clip')].T )

实际应用是我有一个rgb图像,其中包含一些带有纹理的木纹木纹,并且我已经识别出了它的一个补丁.我想在此补丁中获取一组像素,并标记整个图像中与其中一个像素匹配的所有点. 256x256x256的存在表太大,因此我对补丁中的像素运行了聚类算法,并为每个群集设置了存在表(补丁中的颜色通过rgb-或hsv-space形成了细长的线程,因此簇周围的框很小).

The actual application was that I had an rgb image containing some grained wood with some markings on it and I had identified a patch of it. I wanted to take the set of pixels within this patch and mark all points in the whole image that matched one of them. A 256x256x256 existence table is too large so I ran a clustering algorithm on the pixels from the patch and set up existence tables for each cluster (the colours from the patch formed a slender thread through rgb- or hsv-space so the boxes around the clusters were small).

我使存在表略大于所需的大小,并用False填充每个面孔.

I make the existence tables slightly larger than needed and fill each face with False.

一旦我设置了这些小的存在表,我现在可以通过查找表中的每个像素并使用裁剪来制作通常不会映射到表中的像素,从而测试图像的其余部分是否与补丁匹配实际上映射到表的表面(并获得值"False")

Once I've set up these small existence tables I can now test the rest of the image for matching the patch by looking up each pixel in the tables and use the clipping to make pixels which wouldn't normally map into the tables actually map into a face of the table (and get the value 'False')

这篇关于numpy多维索引和函数"take"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆