Expanding/Zooming in a numpy array
Question:
I have the following array:
import numpy as np
a = np.array([[2, 3, 5],
[4, 6, 7],
[1, 5, 7]])
I want to expand it to this array:
b = [[2 2 2 3 3 3 5 5 5]
[2 2 2 3 3 3 5 5 5]
[2 2 2 3 3 3 5 5 5]
[4 4 4 6 6 6 7 7 7]
[4 4 4 6 6 6 7 7 7]
[4 4 4 6 6 6 7 7 7]
[1 1 1 5 5 5 7 7 7]
[1 1 1 5 5 5 7 7 7]
[1 1 1 5 5 5 7 7 7]]
So I’m using the following command:
import scipy.ndimage
b = scipy.ndimage.interpolation.zoom(a, 3, order=0)
based on this question and answer here Resampling a numpy array representing an image.
However, what I’m getting is this:
b = [[2 2 3 3 3 3 5 5 5]
[2 2 3 3 3 3 5 5 5]
[4 4 6 6 6 6 7 7 7]
[4 4 6 6 6 6 7 7 7]
[4 4 6 6 6 6 7 7 7]
[4 4 6 6 6 6 7 7 7]
[1 1 5 5 5 5 7 7 7]
[1 1 5 5 5 5 7 7 7]
[1 1 5 5 5 5 7 7 7]]
I want the expansion to be exactly by 3, or whatever the zoom factor is, but currently it’s different for each element of the array.
Is there a direct way to do this? Or shall I do it manually with some coding?
Answers:
I don’t know if there’s a function that does exactly what you want in NumPy or SciPy but it’s easy to create one yourself:
from __future__ import division
import numpy as np
def zoom(a, factor):
a = np.asarray(a)
slices = [slice(0, old, 1/factor) for old in a.shape]
idxs = (np.mgrid[slices]).astype('i')
return a[tuple(idxs)]
It gives the expected result:
>>> a = [[2,3,5], [4,6,7], [1,5,7]]
>>> zoom(a,3)
array([[2, 2, 2, 3, 3, 3, 5, 5, 5],
[2, 2, 2, 3, 3, 3, 5, 5, 5],
[2, 2, 2, 3, 3, 3, 5, 5, 5],
[4, 4, 4, 6, 6, 6, 7, 7, 7],
[4, 4, 4, 6, 6, 6, 7, 7, 7],
[4, 4, 4, 6, 6, 6, 7, 7, 7],
[1, 1, 1, 5, 5, 5, 7, 7, 7],
[1, 1, 1, 5, 5, 5, 7, 7, 7],
[1, 1, 1, 5, 5, 5, 7, 7, 7]])
I haven’t tested it for all factors and shapes, maybe that approach could have trouble because of floating point accuracy (the step argument in the slices).
Maybe a little late, but for the sake of completness: Numpy Kron does the job perfectly
>>> import numpy as np
>>> a = np.array([[2,3,5], [4,6,7], [1,5,7]])
>>> np.kron(a, np.ones((3,3)))
array([[ 2., 2., 2., 3., 3., 3., 5., 5., 5.],
[ 2., 2., 2., 3., 3., 3., 5., 5., 5.],
[ 2., 2., 2., 3., 3., 3., 5., 5., 5.],
[ 4., 4., 4., 6., 6., 6., 7., 7., 7.],
[ 4., 4., 4., 6., 6., 6., 7., 7., 7.],
[ 4., 4., 4., 6., 6., 6., 7., 7., 7.],
[ 1., 1., 1., 5., 5., 5., 7., 7., 7.],
[ 1., 1., 1., 5., 5., 5., 7., 7., 7.],
[ 1., 1., 1., 5., 5., 5., 7., 7., 7.]])
Here is my approach, which uses simple numpy functions. It returns the same dtype as the input.
import numpy as np
def zoom(a, factor):
sx, sy = (factor * dim for dim in a.shape)
X, Y = np.ogrid[0:sx, 0:sy]
return a[X//factor, Y//factor]
I have the following array:
import numpy as np
a = np.array([[2, 3, 5],
[4, 6, 7],
[1, 5, 7]])
I want to expand it to this array:
b = [[2 2 2 3 3 3 5 5 5]
[2 2 2 3 3 3 5 5 5]
[2 2 2 3 3 3 5 5 5]
[4 4 4 6 6 6 7 7 7]
[4 4 4 6 6 6 7 7 7]
[4 4 4 6 6 6 7 7 7]
[1 1 1 5 5 5 7 7 7]
[1 1 1 5 5 5 7 7 7]
[1 1 1 5 5 5 7 7 7]]
So I’m using the following command:
import scipy.ndimage
b = scipy.ndimage.interpolation.zoom(a, 3, order=0)
based on this question and answer here Resampling a numpy array representing an image.
However, what I’m getting is this:
b = [[2 2 3 3 3 3 5 5 5]
[2 2 3 3 3 3 5 5 5]
[4 4 6 6 6 6 7 7 7]
[4 4 6 6 6 6 7 7 7]
[4 4 6 6 6 6 7 7 7]
[4 4 6 6 6 6 7 7 7]
[1 1 5 5 5 5 7 7 7]
[1 1 5 5 5 5 7 7 7]
[1 1 5 5 5 5 7 7 7]]
I want the expansion to be exactly by 3, or whatever the zoom factor is, but currently it’s different for each element of the array.
Is there a direct way to do this? Or shall I do it manually with some coding?
I don’t know if there’s a function that does exactly what you want in NumPy or SciPy but it’s easy to create one yourself:
from __future__ import division
import numpy as np
def zoom(a, factor):
a = np.asarray(a)
slices = [slice(0, old, 1/factor) for old in a.shape]
idxs = (np.mgrid[slices]).astype('i')
return a[tuple(idxs)]
It gives the expected result:
>>> a = [[2,3,5], [4,6,7], [1,5,7]]
>>> zoom(a,3)
array([[2, 2, 2, 3, 3, 3, 5, 5, 5],
[2, 2, 2, 3, 3, 3, 5, 5, 5],
[2, 2, 2, 3, 3, 3, 5, 5, 5],
[4, 4, 4, 6, 6, 6, 7, 7, 7],
[4, 4, 4, 6, 6, 6, 7, 7, 7],
[4, 4, 4, 6, 6, 6, 7, 7, 7],
[1, 1, 1, 5, 5, 5, 7, 7, 7],
[1, 1, 1, 5, 5, 5, 7, 7, 7],
[1, 1, 1, 5, 5, 5, 7, 7, 7]])
I haven’t tested it for all factors and shapes, maybe that approach could have trouble because of floating point accuracy (the step argument in the slices).
Maybe a little late, but for the sake of completness: Numpy Kron does the job perfectly
>>> import numpy as np
>>> a = np.array([[2,3,5], [4,6,7], [1,5,7]])
>>> np.kron(a, np.ones((3,3)))
array([[ 2., 2., 2., 3., 3., 3., 5., 5., 5.],
[ 2., 2., 2., 3., 3., 3., 5., 5., 5.],
[ 2., 2., 2., 3., 3., 3., 5., 5., 5.],
[ 4., 4., 4., 6., 6., 6., 7., 7., 7.],
[ 4., 4., 4., 6., 6., 6., 7., 7., 7.],
[ 4., 4., 4., 6., 6., 6., 7., 7., 7.],
[ 1., 1., 1., 5., 5., 5., 7., 7., 7.],
[ 1., 1., 1., 5., 5., 5., 7., 7., 7.],
[ 1., 1., 1., 5., 5., 5., 7., 7., 7.]])
Here is my approach, which uses simple numpy functions. It returns the same dtype as the input.
import numpy as np
def zoom(a, factor):
sx, sy = (factor * dim for dim in a.shape)
X, Y = np.ogrid[0:sx, 0:sy]
return a[X//factor, Y//factor]