4

I've got a 900 x 650 2D numpy array which I'd like to split into 10 x 10 blocks, which will be checked for nonzero elements. Is there a Pythonic way that I can achieve this with numpy?

I'm looking for functionality similar to the following:

blocks_that_have_stuff = []
my_array = getArray()
my_array.cut_into_blocks((10, 10))
for block_no, block in enumerate(my_array):
    if numpy.count_nonzero(block) > 5:
        blocks_that_have_stuff.append(block_no)
5
  • you mean numpy.count_nonzero(block) > 5 ? Commented Jun 29, 2013 at 22:14
  • Oops, yup that is what I meant. Commented Jun 29, 2013 at 22:14
  • how are your blocks supposed to be set up? is it all possible 10x10 blocks? Just non-overlapping 10x10 blocks. Commented Jun 29, 2013 at 22:18
  • Non-overlapping 10x10 blocks. Commented Jun 29, 2013 at 22:19
  • 3
    This stackoverflow answer seems to contain a nice way of splitting a mtrix into blocks: stackoverflow.com/a/5078155/204218 Commented Jun 29, 2013 at 22:22

1 Answer 1

8

I wrote a routine that cut your matrix in blocks. The example is very easy to understand. I wrote it in an easy form to display the result (only for checking purpose). If you are interested in it, you could include in the output the number of blocks or anything.

import matplotlib.pyplot as plt
import numpy as np

def cut_array2d(array, shape):
    arr_shape = np.shape(array)
    xcut = np.linspace(0,arr_shape[0],shape[0]+1).astype(np.int)
    ycut = np.linspace(0,arr_shape[1],shape[1]+1).astype(np.int)
    blocks = [];    xextent = [];    yextent = []
    for i in range(shape[0]):
        for j in range(shape[1]):
            blocks.append(array[xcut[i]:xcut[i+1],ycut[j]:ycut[j+1]])
            xextent.append([xcut[i],xcut[i+1]])
            yextent.append([ycut[j],ycut[j+1]])
    return xextent,yextent,blocks

nx = 900; ny = 650
X, Y = np.meshgrid(np.linspace(-5,5,nx), np.linspace(-5,5,ny))
arr = X**2+Y**2

x,y,blocks = cut_array2d(arr,(10,10))

n = 0

for x,y,block in zip(x,y,blocks):
    n += 1
    plt.imshow(block,extent=[y[0],y[1],x[0],x[1]],
               interpolation='nearest',origin='lower',
               vmin = arr.min(), vmax=arr.max(),
               cmap=plt.cm.Blues_r)
    plt.text(0.5*(y[0]+y[1]),0.5*(x[0]+x[1]),str(n),
             horizontalalignment='center',
             verticalalignment='center')

plt.xlim([0,900])
plt.ylim([0,650])
plt.savefig("blocks.png",dpi=72)
plt.show()

The output is:

enter image description here

Regards

Note: I think you could optimize this routine using np.meshgrid instead a lot of appends with the xextent & yextent.

Sign up to request clarification or add additional context in comments.

2 Comments

Amazing, exactly what I was looking for. I wish I could rep you more for this incredible answer.
@DanDoe, I believe that you can start a bounty (2 days after you posted) on your question, and award it to the above answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.