pceccon
pceccon

Reputation: 9844

Slicing array in regions - Python

I have to "divide" an n x m array in regions using a mask input.

For example, suppose I have a 20 x 20 array. My mask is the following (5 x 5) -- always:

enter image description here

where the numbers represent the regions in which the cells take part. This mask is not an input, that is just an ndarray. This mask just represent how I should slice my 20 x 20 at every 5 x 5 neighborhood.

For example, the first region comprehend the indices:

(0,0), (1,0), (1,1), (2,0), (2,1), (2,2)

For each 5 x 5neighborhood of my 20 x 20 array, I should return the values that are in each of the 8regions.

I know how to do that with a "standard code", but I wondering if there is a Pythonic way of do that, possible with a concise code.

As a code example, I could do something like:

def slice_in_regions(data, x_dim, y_dim):
    for x in xrange(0, x_dim, 5):
        for y in xrange(0, y_dim, 5):
            neighbors = data[x:x+4, y:y+4]
            region1 = [neighbors[0,0], neighbors[1,0], neighbors[1,1], neighbors[2,0], neighbors[2,1], neighbors[2,2]]
            # region2, region3...

However, that doesn't seem to be a good way to do that. Moreover, I'm counting on that my data will dimension be multiple of 5.

Thank you.

Upvotes: 0

Views: 660

Answers (1)

jmetz
jmetz

Reputation: 12773

It seems you could probably just resize your mask, e.g. if you're already using numpy,

mask = mask.repeat(4, axis=0).repeat(4, axis=1)
# Then you apply the mask using 
values = data[mask]

Otherwise,

import numpy as np
mask = np.repeat(mask, 4, axis=0).repeat(4, axis=1)
# Then you apply the mask using 
values = np.array(data)[mask]

Individual regions

If you need to access each region individually, you could precede the previous by using a labelled mask; as the labels will be grown into labelled regions you can then use, e.g.

values = [ data[mask==l] for l in range(1, mask.max()+1)]

Here values will be a list of arrays where each item corresponds to a labelled region in mask.

Generating the labelled mask

For completeness, to get from a binary mask to a labelled mask where every on pixel has it's own label you could use scipy.ndimage.label

mask = ndimage.label(mask, [[0,0,0],[0,1,0],[0,0,0]])

or if using a region labelling function is overkill, you can achieve a similar result using

mask[mask] = range(1,mask.sum()+1)

Upvotes: 1

Related Questions