How can I downscale the raster data of 4 X 6
size into 2 X 3
size enforcing \'1\' to be chosen if any element with in 2*2 pixels include 1, otherwise 0
You could use the patch extraction routine of scikit learn as follows (you should be able to copy and paste):
from sklearn.feature_extraction.image import extract_patches
data = np.array([[0, 0, 1, 1, 0, 0],
[1, 0, 0, 1, 0, 0],
[1, 0, 1, 0, 0, 0],
[1, 1, 0, 0, 0, 0]])
patches = extract_patches(data, patch_shape=(2, 2), extraction_step=(2, 2))
non_zero_count_patches = (patches > 0).any(axis=-1).any(axis=-1).astype(int)
print non_zero_count_patches
Explanation: the function extract_patches
generates a view on your array that represents sliding patches of size patch_shape
and of discretization step extraction_step
, which you can vary as you want. The following line checks which of the patches contains a non zero item. However, this can be replaced by anything else you may be interested in, such as the mean, sum, etc. An advantage is that you can choose patch size and extraction step freely (they do not need to correspond), without memory overhead until any
is invoked (it uses strides internally).
import numpy as np
def toblocks(arr, nrows, ncols):
h, w = arr.shape
blocks = (arr.reshape(h // nrows, nrows, -1, ncols)
.swapaxes(1, 2)
.reshape(h // nrows, w // ncols, ncols * nrows))
return blocks
data = np.array([[0, 0, 1, 1, 0, 0],
[1, 0, 0, 1, 0, 0],
[1, 0, 1, 0, 0, 0],
[1, 1, 0, 0, 0, 0]])
blocks = toblocks(data, 2, 2)
downscaled = blocks.any(axis=-1).astype(blocks.dtype)
print(downscaled)
# [[1 1 0]
# [1 1 0]]
Where the above solution comes from: A while ago, an SO question asked how to break an array into blocks. All I did was slightly modify that solution to apply any
to each of the blocks.