Home > Back-end >  Is there a numpy function to compress a (k, m, n) matrix to a (k//2, m//2, n//2) matrix by summing n
Is there a numpy function to compress a (k, m, n) matrix to a (k//2, m//2, n//2) matrix by summing n

Time:10-20

This can be accomplished with

cube = (
    cube[::2, ::2, ::2]
      cube[1::2, ::2, ::2]
      cube[::2, 1::2, ::2]
      cube[1::2, 1::2, ::2]
      cube[::2, ::2, 1::2]
      cube[1::2, ::2, 1::2]
      cube[::2, 1::2, 1::2]
      cube[1::2, 1::2, 1::2]
)

But I'm wondering if there is a function to accomplish this quickly and cleanly. If not, is there a canonical name for this operation?

CodePudding user response:

This sounds like a classical strided-convolution pooling operation.
You can do this in many ways, but the most straightforward would probably be to use skimage's block_reduce functionality, as so -

from skimage.measure import block_reduce
a = np.arange(6*8*4).reshape(6, 8, 4)
reduced_a = block_reduce(a, block_size=(2, 2, 2), func=np.sum) 
# Make sure the dimensions are as expected:
print(reduced_a.shape)
# (3, 4, 2)

# Test specific value for correct reduction of matrix:
assert reduced_a[0, 0, 0] == np.sum(a[:2, :2, :2])
# And more generally, for any index:
i, j, k = 2, 0, 1
assert reduced_a[i, j, k] == np.sum(a[i*2:i*2 2, j*2:j*2 2, k*2:k*2 2])

Another way would be to directly convolve your "cube" with a "ones" kernel, and then subsample for the required 2-stride:

from scipy import ndimage
convolved_a = ndimage.convolve(a, np.ones((2, 2, 2)))[::2, ::2, ::2]
# Assert that this is indeed the same:
assert np.all(convolved_a == reduced_a)

CodePudding user response:

In purely numpy (say, if you're trapped in a non-extensible API, or are otherwise trying to limit dependencies), you can use my recipe here

cube = np.sum(window_nd(cube, 2, 2), (-3, -2, -1))
  • Related