从NumPy数组的中间切出一个子集

时间:2019-12-12 09:35:12

标签: python numpy

我使用栅格图像和模块rasterio将其实现为numpy阵列。我想从每个图像的中间切出(1000, 1000)大小的一部分(以避免图像的边界超出范围)。

image = np.random.random_sample((2000, 2000))

s = image.shape
mid = [round(x / 2) for x in s] # middle point of both axes
margins = [[y + x for y in [-500, 500]] for x in mid] # 1000 range around every middle point

结果是2个列表的清单,每个轴的切割范围。但这就是我的绊脚石:range()不接受列表,我正在尝试以下暴力破解方法:

cut_image = image[range(margins[0][0], margins[0][1]), range(margins[1][0], margins[1][1])]

但是:

cut_image.shape
## (1000,)

切片数组会丢失尺寸信息,而这正是我所不想要的。 考虑到我感到困惑。 寻找更具品味的解决方案。

2 个答案:

答案 0 :(得分:1)

这里的问题是您正在做的事情被称为整数索引,而不是切片索引。行为会发生变化,如果不熟悉,可能会违反直觉。您可以检查docs以获得更多详细信息。

以下是使用基本切片的方法:

# center coordinates of the image
x_0, y_0 = np.asarray(image.shape)//2
# slice taken from the center point
out = image[x_0-x_0//2:x_0+x_0//2, y_0-y_0//2:y_0+y_0//2]

print(out.shape)
# (1000, 1000)

答案 1 :(得分:1)

正如其他答案指出的那样,您不是真正对数组进行切片,而是对它进行索引。

如果您想对数组进行切片(对的话,这比使用索引列表更为优雅),您将对切片更加满意。这些对象代表start:end:step语法。

就您而言,

import numpy as np

WND = 50

image = np.random.random_sample((200, 300))

s = image.shape
mid = [round(x / 2) for x in s] # middle point of both axes
margins = [[y + x for y in [-WND, WND]] for x in mid] # 1000 range around every middle point

# array[slice(start, end)] -> array[start:end]
x_slice = slice(margins[0][0], margins[0][1])
y_slice = slice(margins[1][0], margins[1][1])

print(x_slice, y_slice)
# slice(50, 150, None) slice(100, 200, None)

cut_image = image[x_slice, y_slice]

print(cut_image.shape)
# (100,100)

编制索引?

您可能想知道问题中发生了什么,导致仅1000个元素,而不是预期的1000 * 1000。

这是使用不同维度的列表建立索引的简单示例

# n and n2 have identical values
n = a[[i0, i1, i2],[j0, j1, j2]]
n2 = np.array([a[i0, j0], a[i1, j1], a[i2, j2]]

需要澄清的是,您将了解,您的代码仅返回该块矩阵的对角系数,而不是使用块矩阵:)