0

How (in python3) can I extract several n-by-m block from a M-by-N array centering in each element?

for example, In a 9-by-9 matrix, and using a 3-by-3 block, I need to extract the block at each position of the matrix. The challenge here (for me) is because of the I,J element inside of his respective block change of position.

here an image where I show the 9 blocks (for 9 positions) of a 9-by-9 matrix (of course there are 81 blocks to extract)

Here an image

The code below works perfectly (ONLY) for the corners. Here the size of the block (Wsize-by-Wsize) is a odd number in order to locate the index (Eindex[0],Eindex1) in the middle.

def windowing(array,Wsize,Eindex):
    '''
    Extract an sub-array of array for the element located in the index 'Eindex'.
    Wsize-by-Wsize is the shape of the window 
    '''
    block=np.zeros(tuple(Wsize))
    k0 = int((Wsize[0]-1)/2)
    k1 = int((Wsize[1]-1)/2) 
    s0 =  Wsize[0]
    s1 =  Wsize[1]
    I =  array.shape[0]-1 # las index in i-direction
    J =  array.shape[1]-1 # las index in i-direction
    if (Eindex[0]==0) and (Eindex[1]==0):
        block=array[0:Eindex[0]+s0,0:Eindex[1]+s1]
        return block
    elif (Eindex[0]==I) and (Eindex[1]==0):
        block=array[-s0:,0:Eindex[1]+s1]
        return block
    elif (Eindex[0]==0) and (Eindex[1]==J):
        block=array[0:Eindex[0]+s0,-s1:]
        return block
    elif (Eindex[0]==I) and (Eindex[1]==J):
        block=array[-s0:,-s1:]
        return block

for example check:

x = np.arange(81).reshape(9,9)
print(windowing(x,[3,3],[0,0]))
print(windowing(x,[3,3],[8,8))
print(windowing(x,[3,3],[8,0]))
print(windowing(x,[3,3],[0,8]))
5
  • Do you have a Numpy array, a flat list of length 81, a list of lists, a dict, ..? Commented Feb 28, 2020 at 6:54
  • In the question is written: I have a 9-by-9 matrix. The shape of the block es 3-by-3. Commented Feb 28, 2020 at 18:58
  • Yes. There are several ways to notate a 9-by-9 matrix in Python, which is why I asked. Commented Feb 28, 2020 at 22:07
  • The question is not about how rotate a matrix, is: given a matrix A 9-by-9 (for example), extract a block 3-by-3 centering in the position i,j. If you have some strategy or idea, please write your answer, it will help me. Commented Feb 29, 2020 at 2:40
  • Notate, not rotate. Commented Feb 29, 2020 at 11:42

2 Answers 2

1

Here is an approach that takes arbitrary arrays, coordinates and window sizes.

def compute_indices(c, ws, length):

    # default setting: % operations to accommodate odd/even window sizes
    low, high = c - (ws//2), c + (ws//2) + ws%2 

    # correction for overlap with borders of array
    if low<0:
        low, high = 0, ws
    elif high>length:
        low, high = -ws, None

    return low, high


def extract_block(arr, coords, window_size=(3,3)):

    # extract array shapes and window sizes into single 
    # variables
    len_r, len_c = arr.shape
    wsr, wsc = window_size

    # extract coords and correct for 0-indexing
    r, c = coords
    r0, c0 = r-1, c-1

    row_low, row_high = compute_indices(r0, wsr, len_r)
    col_low, col_high = compute_indices(c0, wsc, len_c)

    return arr[row_low:row_high, col_low:col_high]

test cases:

a = np.arange(81).reshape(9,9)

extract_block(a, [1,1], (3,3))
array[[ 0  1  2]
     [ 9 10 11]
     [18 19 20]]

extract_block(a, [9,9], (3,3))
array([[60, 61, 62],
       [69, 70, 71],
       [78, 79, 80]])

extract_block(a, [5,2], (3,6))
array([[27, 28, 29, 30, 31, 32],
       [36, 37, 38, 39, 40, 41],
       [45, 46, 47, 48, 49, 50]])
Sign up to request clarification or add additional context in comments.

Comments

1

You can use numpy like this:

import numpy as np
# Array 9 by 9
x = np.arange(81).reshape((9, 9))
# -1 is important for the indexing
desired_position = np.array([[1,1], [1,5], [1,9], [5,1], [5,5], [5,9], [9,1], [9,5], [9,9]]) - 1
#print(desired_position)
for dp in desired_position:
    pos = []
    p1, p2 =dp[0] - 1, dp[0] + 2
    if p1 <= 0:
        p1, p2 = 0, 3
    elif p2 >= x.shape[0]:
        p2, p1 = x.shape[0], x.shape[0] - 3
    pos.append([p1, p2])

    p1, p2 = dp[1] - 1, dp[1] + 2
    if p1 <= 0:
        p1, p2 = 0, 3
    elif p2 >= x.shape[1]:
        p2, p1 = x.shape[1], x.shape[1] - 3
    pos.append([p1, p2])
    print(x[pos[0][0]:pos[0][1],pos[1][0]:pos[1][1]])

Please read the docs for numpy for futher information

I edited the code, so now it works.

3 Comments

but the 3rd array is 3-by-2, and must to be 3-by-3 because all block are the same size
the index [2,2] for instance gives as result a 4-by-4 matrix, but we know the block is a 3-by-3 shape. I am trying to fix it for all positions [i,j].
I edited the code one more time, now is working for each position. Please let me now, if somehoe it does not work on your machine.

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.