如何“缩放”一个numpy数组?

40
我希望按比例n缩放一个形状为(h,w)的数组,得到一个形状为(h*n,w*n)的数组。假设我有一个2x2的数组:
array([[1, 1],
       [0, 1]])

我想将这个数组缩放为4x4:

array([[1, 1, 1, 1],
       [1, 1, 1, 1],
       [0, 0, 1, 1],
       [0, 0, 1, 1]])

也就是说,原始数组中每个单元格的值都会被复制到结果数组中的4个相应单元格中。假设数组大小和缩放因子任意,最有效的方法是什么?

4个回答

73
你应该使用Kronecker乘积numpy.kron

计算Kronecker乘积,由第二个数组块缩放的复合数组

import numpy as np
a = np.array([[1, 1],
              [0, 1]])
n = 2
np.kron(a, np.ones((n,n)))

这将给出您想要的结果:

array([[1, 1, 1, 1],
       [1, 1, 1, 1],
       [0, 0, 1, 1],
       [0, 0, 1, 1]])

不错,我不知道那个。 - NPE
1
numpy.kron是专为问题中的情况而构建的。我更喜欢使用这种方法以获得更好的可读性,并且如果您的规格在以后发生变化,它也更加健壮。 - brc
3
数学家们迄今为止还没有让我失望。但你知道的,我应该怎么找到那个东西呢?:) numpy.kron - David Eyk
1
说实话,这对我帮助很大。我刚写了一个可怕的类方法,用四行代码实现了这个只需要一行就能完成的功能,而且这个方法的作用是_完全_可以被识别出来的(与我的可怕的函数式代码相比 :P)。说实话,这是我最近看到的最好的“hack”(为什么我没想到呢!!)。 - bjd2385
2
不幸的是,与此处的 a.repeat(n, 1).repeat(n, 0) 方法相比,np.kron() 在大数组上的速度较慢。对于更复杂的子模式来说还可以接受。 - kxr

18
你可以使用 repeat
In [6]: a.repeat(2,axis=0).repeat(2,axis=1)
Out[6]: 
array([[1, 1, 1, 1],
       [1, 1, 1, 1],
       [0, 0, 1, 1],
       [0, 0, 1, 1]])

我不确定是否有一种简洁的方法将这两个操作合并成一个。


11

scipy.misc.imresize可以缩放图像。 它也可以用于缩放numpy数组:

#!/usr/bin/env python

import numpy as np
import scipy.misc

def scale_array(x, new_size):
    min_el = np.min(x)
    max_el = np.max(x)
    y = scipy.misc.imresize(x, new_size, mode='L', interp='nearest')
    y = y / 255 * (max_el - min_el) + min_el
    return y

x = np.array([[1, 1],
              [0, 1]])
n = 2
new_size = n * np.array(x.shape)
y = scale_array(x, new_size)
print(y)

这就是我需要的。其他答案只能按整数倍调整大小,但这个答案可以调整到任意尺寸。 - Josh Davis
1
scipy.misc.imresize已从scipy中删除。 - Nick
scipy.ndimage.zoom代替。 - Albert
1
一个人也可以使用Pillow库的Image对象的'resize'方法,如numpy.array(Image.fromarray(arr).resize())详情请见:https://pillow.readthedocs.io/en/stable/reference/Image.html - Awais Mirza
这个解决方案仍然只适用于 int 或 float 类型的数据,而不适用于 complex 类型。 - freshNfunky

9
为了有效地进行缩放,我使用以下方法。它的速度比repeat快5倍,比kron快10倍。首先,初始化目标数组,以便在原地填充缩放后的数组。预定义切片以节省几个周期:
K = 2   # scale factor
a_x = numpy.zeros((h * K, w *K), dtype = a.dtype)   # upscaled array
Y = a_x.shape[0]
X = a_x.shape[1]
myslices = []
for y in range(0, K) :
    for x in range(0, K) :
        s = slice(y,Y,K), slice(x,X,K)
        myslices.append(s)

现在这个函数将会执行缩放操作:
def scale(A, B, slices):        # fill A with B through slices
    for s in slices: A[s] = B

或者只需在一个函数中完成相同的操作:

def scale(A, B, k):     # fill A with B scaled by k
    Y = A.shape[0]
    X = A.shape[1]
    for y in range(0, k):
        for x in range(0, k):
            A[y:Y:k, x:X:k] = B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接