在Python中从较大的(n,n)复制较小的正方形数组(m,m)

时间:2018-09-17 14:11:53

标签: python arrays numpy slice

假设我有一个数组:

from numpy import *
x = range(16)
x = reshape(x,(4,4))

print x
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

我想通过定义矩阵的大小(而不是行/列索引)来获得始终位于x中间的较小数组的副本

例如如果我想要一个2x2数组,它将返回:

[[5  6]
 [9 10]]

出于我的目的,我的初始数组较大(4096x4096),我想复制中间正方形数组的副本,大小为(128x128),(256x256),(512x512),(1024x1024)和(2048x2048)。 / p>

我也想保留原始数组,所以我不必只从原始切片中切掉行/列,而是只希望修剪原始副本并保存到新变量中。

我正在考虑定义一些变量,例如(对于2x2情况):

rows_to_keep = [1,2]
cols_to_keep = [1,2]

然后使用

x[np.ix_(rows_to_keep, columns_to_keep)]

但是,当我的rows_to_keep是最多2048个数字(例如,从4096x4096原始图像中复制128x128正方形我可以创建一个索引列表,该索引从1984年的row / col转到2112:

size_to_keep = 128
indices = np.linspace(0, size_to_keep, size_to_keep, endpoint=False)

rows_to_keep = [(4096/2)-(size_to_keep/2) + i for i in indices]
cols_to_keep = [(4096/2)-(size_to_keep/2) + i for i in indices]

copy_array = x[np.ix_(rows_to_keep, columns_to_keep)]    

但是,这又变得混乱/不切实际。我希望有一种更Python化的方式来做到这一点?预先感谢

2 个答案:

答案 0 :(得分:3)

由于所有索引都是连续的,因此您只需使用适当的slice即可。显然,您无法避免计算极值,仅此而已。

这可以采取以下形式(包括一些代码以确保它适用于size的任何整数值):

def get_center(arr, size):
    mask = tuple(
        slice(int(dim / 2 - size / 2), int(dim / 2 + size / 2))
        if 0 < size < dim else slice(None)
        for dim in arr.shape)
    return arr[mask].copy()

可以简单地像这样使用:

import numpy as np
dim = 4
x = np.arange(dim * dim).reshape((dim, dim))
y = get_center(x, 2)
# [[ 5,  6],
#  [ 9, 10]]

并按预期工作,但不占用太多内存。

当然,您可能希望调整自己的极值,以按自己喜欢的方式处理奇怪的情况(问题中并未真正定义)。

答案 1 :(得分:2)

Numpy可用于视图,这意味着您进行操作

extracted_middle_square = x[1:2,1:2]

您将看到x的视图(不是副本,并且x未被修改)。如果您要创建一个新变量,请

extracted_middle_square = x[1:2,1:2].copy()

这应该可以解决您的问题。