Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Downsample array in Python

I have basic 2-D numpy arrays and I'd like to "downsample" them to a more coarse resolution. Is there a simple numpy or scipy module that can easily do this? I should also note that this array is being displayed geographically via Basemap modules.

SAMPLE: enter image description here

like image 863
wuffwuff Avatar asked Sep 06 '13 20:09

wuffwuff


People also ask

How do you downsample image data in Python?

Step 1: Fead the image. Step 2: Pass the image as a parameter to the pyrdown() function. Step 3: Display the output.


3 Answers

scikit-image has implemented a working version of downsampling here, although they shy away from calling it downsampling for it not being a downsampling in terms of DSP, if I understand correctly:

http://scikit-image.org/docs/dev/api/skimage.measure.html#skimage.measure.block_reduce

but it works very well, and it is the only downsampler that I found in Python that can deal with np.nan in the image. I have downsampled gigantic images with this very quickly.

like image 117
K.-Michael Aye Avatar answered Oct 20 '22 02:10

K.-Michael Aye


When downsampling, interpolation is the wrong thing to do. Always use an aggregated approach.

I use block means to do this, using a "factor" to reduce the resolution.

import numpy as np
from scipy import ndimage

def block_mean(ar, fact):
    assert isinstance(fact, int), type(fact)
    sx, sy = ar.shape
    X, Y = np.ogrid[0:sx, 0:sy]
    regions = sy//fact * (X//fact) + Y//fact
    res = ndimage.mean(ar, labels=regions, index=np.arange(regions.max() + 1))
    res.shape = (sx//fact, sy//fact)
    return res

E.g., a (100, 200) shape array using a factor of 5 (5x5 blocks) results in a (20, 40) array result:

ar = np.random.rand(20000).reshape((100, 200))
block_mean(ar, 5).shape  # (20, 40)
like image 31
Mike T Avatar answered Oct 20 '22 02:10

Mike T


imresize and ndimage.interpolation.zoom look like they do what you want

I haven't tried imresize before but here is how I have used ndimage.interpolation.zoom

a = np.array(64).reshape(8,8)
a = ndimage.interpolation.zoom(a,.5) #decimate resolution

a is then a 4x4 matrix with interpolated values in it

like image 6
Hammer Avatar answered Oct 20 '22 02:10

Hammer