42

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 2x2 array:

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

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

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?

0

4 Answers 4

75

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]])
Sign up to request clarification or add additional context in comments.

1 Comment

Unfortunately np.kron() is rather slow on big arrays compared to the a.repeat(n, 1).repeat(n, 0) method here. Its ok for more complex sub-patterns.
18

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.

Comments

11

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)

4 Comments

scipy.misc.imresize has been removed from scipy.
There is scipy.ndimage.zoom instead.
One can also use 'resize' method of Pillow library’s Image object as numpy.array(Image.fromarray(arr).resize()) Details: pillow.readthedocs.io/en/stable/reference/Image.html
this solution still works only with data of type int or float but not complex
9

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.