索引和切片#

DALI 数据节点可以使用熟悉的 Python 语法进行索引和切片,用于数组索引 x[sel],其中 x 是 DALI 数据节点,sel选择。 选择可以是索引切片

索引#

最简单的情况是使用常数索引进行标量索引

images = fn.decoders.image(...)
sizes = fn.sizes(images)  # height, width, channels

height = sizes[0]
width  = sizes[1]

上面的代码片段从表示图像大小的 3 元素张量中提取宽度和高度。

注意

批次维度是隐式的,不能被索引。 在此示例中,索引广播到整个批次。 有关每个样本的索引,请参阅使用运行时值进行索引

有关可以访问批次中不同样本数据的运算符,请参阅 fn.permute_batch()

从末尾索引#

可以使用负索引从张量的末尾开始索引。 -1 的索引表示最后一个元素

channels = sizes[-1]   # channels go last
widths = sizes[-2]     # widths are the innermost dimension after channels

使用运行时值进行索引#

使用常数进行索引通常是不够的。 使用 DALI,您可以使用其他计算的结果来访问张量元素。 在下面的示例中,我们使用运行时定义的索引来访问张量中随机位置的元素

raw_files = fn.readers.file(...)
length = raw_files.shape()[0]

# calculate a random index from 0 to file_length-1
random_01 = fn.random.uniform(range=(0, 1))  # random numbers in range [0..1)
index = fn.floor(random_01 * length)  # calculate indices from [0..length)
# cast the index to integer - required for indexing
index = fn.cast(index, dtype=dali.types.INT64)

# extract a random byte
random_byte = raw_files[index]

在这里,将从每个样本中提取随机索引处的字节。 index 是一个数据节点,表示一批标量值,每个样本一个。 这些值中的每一个都用作 raw_files 中相应样本的索引。

注意

索引必须是 CPU 运算符的结果。

切片#

要提取多个值(或切片),可以使用 Python 列表切片语法

header = raw_files[:16]  # extract 16-byte headers from files in the batch

如果省略切片的开头,则切片从 0 开始。 如果省略结尾,则切片在给定轴的末尾结束。 负索引可用于切片的开始和结束。 任何一端都可以是常数、运行时值(DataNode)或可以跳过。

多维选择#

对于多维数据,您可以指定多个以逗号分隔的选择。 如果选择是索引,则从输出中删除相应的维度

images = fn.decoders.image(jpegs, device="mixed")  # RGB images in HWC layout
red =   images[:,:,0]
green = images[:,:,1]
blue =  images[:,:,2]

redgreenblue 是 2D 张量。

即使切片的长度为 1,切片也会保留切片的维度

green_with_channel = images[:,:,1:2]  # the last dimension is kept

当索引和切片多维数据时,可以省略尾部维度。 这相当于将全范围切片传递给所有尾部维度

wide = letterboxed[20:-20,:,:]   # slice height, keep width and channels
wide = letterboxed[20:-20,:]     # this line is equivalent to the previous one
wide = letterboxed[20:-20]       # ...and so is this one

注意

另请参阅 fn.crop()fn.slice(),了解为图像处理量身定制的操作。

步长切片#

正向和负向步进也可以使用与 numpy 数组相同的语义来实现。 这可以在多个维度上完成。

reversed = array[::-1] every_second = array[::2] every_second_reversed = array[::-2] quarter_resolution = image[::2, ::2]

添加维度#

特殊值 dali.newaxis 可以用作索引。 此值在输出中创建一个大小为 1 的新维度

trailing_channel = grayscale[:,:,dali.newaxis]
leading_channel = grayscale[dali.newaxis]

布局指定符#

DALI 张量可以具有布局指定符,它会影响某些运算符如何解释数据 - 通常,图像将具有 "HWC" 布局。

当将标量索引应用于轴时,该轴将从输出中删除,同时删除该轴的布局名称

image = ...             # layout HWC
first_row = image[0]    # layout WC
last_col = image[:,-1]  # layout HC
red = image[:,:,0]      # layout HW

可以通过将其传递给 dali.newaxis 来为新创建的维度添加名称

image = ... # layout is HWC
single_frame_video = image[dali.newaxis("F")]  # layout is FHWC