How to "scale" a numpy array?

Question:

I would like to scale an array of shape (h, w) by a factor of n, resulting in an array of shape (h*n, w*n), with the.

Say that I have a 2×2 array:

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

I would like to scale the array to become 4×4:

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

That is, the value of each cell in the original array is copied into 4 corresponding cells in the resulting array. Assuming arbitrary array size and scaling factor, what’s the most efficient way to do this?

Asked By: David Eyk

||

Answers:

You could use 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]])

I am not sure if there’s a neat way to combine the two operations into one.

Answered By: NPE

You should use the Kronecker product, numpy.kron:

Computes the Kronecker product, a composite array made of blocks of the second array scaled by the first

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

which gives what you want:

array([[1, 1, 1, 1],
       [1, 1, 1, 1],
       [0, 0, 1, 1],
       [0, 0, 1, 1]])
Answered By: Andrew Jaffe

To scale effectively I use following approach. Works 5 times faster than repeat and 10 times faster that kron. First, initialise target array, to fill scaled array in-place. And predefine slices to win few cycles:

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)

Now this function will do the scale:

def scale(A, B, slices):        # fill A with B through slices
    for s in slices: A[s] = B

Or the same thing simply in one function:

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
Answered By: Mikhail V

scipy.misc.imresize can scale images. It can be used to scale numpy arrays, too:

#!/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)
Answered By: Martin Thoma
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.