Skip to content

Instantly share code, notes, and snippets.

@dkirkby
Created August 1, 2019 15:27
Show Gist options
  • Save dkirkby/69ced37a86753dda60d3ebad56246a19 to your computer and use it in GitHub Desktop.
Save dkirkby/69ced37a86753dda60d3ebad56246a19 to your computer and use it in GitHub Desktop.
Downsample a 2D image array
def downsample(data, downsampling, summary=np.sum, allow_trim=False):
"""Downsample a 2D array.
Parameters
----------
data : array
Two dimensional array of values to downsample.
downsampling : int
Downsampling factor to use along both dimensions. Must evenly divide the
data dimensions when allow_trim is False.
summary : callable
The summary function to use that will be applied to each block of shape
(dowsampling, downsampling) to obtain the output downsampled values.
Must support broadcasting and an axis parameter. Useful choices are
np.sum, np.mean, np.min, np.max, np.median, np.var but any ufunc
should work.
allow_trim : bool
When False, the input dimensions (ny, nx) must both exactly divide
the downsampling value. Otherwise, any extra rows and columns are
silently trimmed before apply the summary function.
Returns
-------
array
A two dimensional array of shape (ny // downsampling, nx // downsampling)
where the input data shape is (ny, nx).
"""
data = np.asarray(data)
if data.ndim != 2:
raise ValueError('Data must be 2 dimensional.')
ny, nx = data.shape
if not allow_trim and ((nx % downsampling) or (ny % downsampling)):
raise ValueError('Data shape {0} does not evenly divide downsampling={1} and allow_trim is False.'
.format((ny, nx), downsampling))
ny //= downsampling
nx //= downsampling
shape = (ny, nx, downsampling, downsampling)
strides = (downsampling * data.strides[0], downsampling * data.strides[1]) + data.strides
blocks = np.lib.stride_tricks.as_strided(
data[:downsampling * ny, :downsampling * nx], shape=shape, strides=strides)
return summary(blocks, axis=(2, 3))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment