Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resampling a numpy array representing an image

I am looking for how to resample a numpy array representing image data at a new size, preferably having a choice of the interpolation method (nearest, bilinear, etc.). I know there is

scipy.misc.imresize 

which does exactly this by wrapping PIL's resize function. The only problem is that since it uses PIL, the numpy array has to conform to image formats, giving me a maximum of 4 "color" channels.

I want to be able to resize arbitrary images, with any number of "color" channels. I was wondering if there is a simple way to do this in scipy/numpy, or if I need to roll my own.

I have two ideas for how to concoct one myself:

  • a function that runs scipy.misc.imresize on every channel separately
  • create my own using scipy.ndimage.interpolation.affine_transform

The first one would probably be slow for large data, and the second one does not seem to offer any other interpolation method except splines.

like image 757
Gustav Larsson Avatar asked Nov 05 '12 23:11

Gustav Larsson


People also ask

Can an image could be converted into a NumPy array?

Using OpenCV Library imread() function is used to load the image and It also reads the given image (PIL image) in the NumPy array format. Then we need to convert the image color from BGR to RGB. imwrite() is used to save the image in the file.

Can NumPy array store images?

fromarray() Function to Save a NumPy Array as an Image. The fromarray() function is used to create an image memory from an object which exports the array. We can then save this image memory to our desired location by providing the required path and the file name.


1 Answers

Based on your description, you want scipy.ndimage.zoom.

Bilinear interpolation would be order=1, nearest is order=0, and cubic is the default (order=3).

zoom is specifically for regularly-gridded data that you want to resample to a new resolution.

As a quick example:

import numpy as np import scipy.ndimage  x = np.arange(9).reshape(3,3)  print 'Original array:' print x  print 'Resampled by a factor of 2 with nearest interpolation:' print scipy.ndimage.zoom(x, 2, order=0)   print 'Resampled by a factor of 2 with bilinear interpolation:' print scipy.ndimage.zoom(x, 2, order=1)   print 'Resampled by a factor of 2 with cubic interpolation:' print scipy.ndimage.zoom(x, 2, order=3) 

And the result:

Original array: [[0 1 2]  [3 4 5]  [6 7 8]] Resampled by a factor of 2 with nearest interpolation: [[0 0 1 1 2 2]  [0 0 1 1 2 2]  [3 3 4 4 5 5]  [3 3 4 4 5 5]  [6 6 7 7 8 8]  [6 6 7 7 8 8]] Resampled by a factor of 2 with bilinear interpolation: [[0 0 1 1 2 2]  [1 2 2 2 3 3]  [2 3 3 4 4 4]  [4 4 4 5 5 6]  [5 5 6 6 6 7]  [6 6 7 7 8 8]] Resampled by a factor of 2 with cubic interpolation: [[0 0 1 1 2 2]  [1 1 1 2 2 3]  [2 2 3 3 4 4]  [4 4 5 5 6 6]  [5 6 6 7 7 7]  [6 6 7 7 8 8]] 

Edit: As Matt S. pointed out, there are a couple of caveats for zooming multi-band images. I'm copying the portion below almost verbatim from one of my earlier answers:

Zooming also works for 3D (and nD) arrays. However, be aware that if you zoom by 2x, for example, you'll zoom along all axes.

data = np.arange(27).reshape(3,3,3) print 'Original:\n', data print 'Zoomed by 2x gives an array of shape:', ndimage.zoom(data, 2).shape 

This yields:

Original: [[[ 0  1  2]   [ 3  4  5]   [ 6  7  8]]   [[ 9 10 11]   [12 13 14]   [15 16 17]]   [[18 19 20]   [21 22 23]   [24 25 26]]] Zoomed by 2x gives an array of shape: (6, 6, 6) 

In the case of multi-band images, you usually don't want to interpolate along the "z" axis, creating new bands.

If you have something like a 3-band, RGB image that you'd like to zoom, you can do this by specifying a sequence of tuples as the zoom factor:

print 'Zoomed by 2x along the last two axes:' print ndimage.zoom(data, (1, 2, 2)) 

This yields:

Zoomed by 2x along the last two axes: [[[ 0  0  1  1  2  2]   [ 1  1  1  2  2  3]   [ 2  2  3  3  4  4]   [ 4  4  5  5  6  6]   [ 5  6  6  7  7  7]   [ 6  6  7  7  8  8]]   [[ 9  9 10 10 11 11]   [10 10 10 11 11 12]   [11 11 12 12 13 13]   [13 13 14 14 15 15]   [14 15 15 16 16 16]   [15 15 16 16 17 17]]   [[18 18 19 19 20 20]   [19 19 19 20 20 21]   [20 20 21 21 22 22]   [22 22 23 23 24 24]   [23 24 24 25 25 25]   [24 24 25 25 26 26]]] 
like image 162
Joe Kington Avatar answered Oct 01 '22 21:10

Joe Kington