-5

Given a 2D array of any size (X+2*padding, Y+2*padding,) and a window size W, the resulting array should be of shape (X, Y, W*W), (X, Y, W, W), (X*Y, W*W), (X*Y, W, W). The 2D array already has a border padding with 0. Stride is always 1.

For example (with window size = 3):

a = [[0, 0, 0, 0, 0, 0, 0, 0],
     [0, 1, 2, 3, 4, 5, 6, 0],
     [0, 1, 2, 3, 4, 5, 6, 0],
     [0, 1, 2, 3, 4, 5, 6, 0],
     [0, 0, 0, 0, 0, 0, 0, 0]]

# Just some possible results as example (it can be in any form suggested above 2D/3D/4D):

# in case of result shape (X*Y, W, W):

result = [w1, w2, ... wn]

w1 = [[0, 0, 0],
      [0, 1, 2],
      [0, 1, 2]]

w2 = [[0, 0, 0],
      [1, 2, 3],
      [1, 2, 3]]

wn = [[5, 6, 0],
      [5, 6, 0],
      [0, 0, 0]]

# in case of result shape (X*Y, W*W):

result = [[0, 0, 0, 0, 1, 2, 0, 1, 2],
          [0, 0, 0, 1, 2, 3, 1, 2, 3],
          [0, 0, 0, 2, 3, 4, 2, 3, 4],
          ...
          [4, 5, 6, 4, 5, 6, 0, 0, 0],
          [5, 6, 0, 5, 6, 0, 0, 0, 0]]

I would be fine with any resulting shape described above as long as the resulting array consists out of all windows with a defined window size.

Is this possible by only using numpy functions/functionality (no for loops etc.)?

Note: X, Y and W should be flexible, the solution should not only work on my example

The question here: sliding window in numpy doesn't include a window size and the proposed solutions only work on the very specific array shape provided in the question or use other functionality than that provided by numpy.

Spenhouet
  • 6,556
  • 12
  • 51
  • 76
  • 4
    Possible duplicate of [sliding window in numpy](https://stackoverflow.com/questions/15722324/sliding-window-in-numpy) – koPytok Jun 22 '18 at 09:04
  • @koPytok It's not. The operations used in the answers to the linked question all only work on the specific example of only having 2 values per row and also it doesn't include a flexibel window size. It basically something different that I'm asking for. – Spenhouet Jun 22 '18 at 09:43
  • First, you should be able to use the referenced duplicate and generalize to your case easily. Second, you specify that the outputs should be 3D and yet none of your examples are. Please rewrite your question to be more clear. – David Jun 25 '18 at 00:07
  • @David The answers in the liked "duplicate" are not applicable for my question. They are not generalizable to fit to my case because they can't solve my case. All my examples in my question are 3D. I don't know why you are unable to see that. – Spenhouet Jun 25 '18 at 05:55
  • "... of shape (X, Y, W\*W), (X, Y, W, W), (X\*Y, W\*W), (X\*Y, W, W)." Some of these are 3D, one is even 4D. All of your outputs in your example are 2D. – David Jun 25 '18 at 23:08
  • Also, it's unclear the operation that you are applying to your windows to get the bottom result that you show. – David Jun 25 '18 at 23:18
  • You are right that the input is 2D (as mentioned in the title). The output can be 2D, 3D or 4D. That is up to the solution and not important to me (as mentioned in the question). The example is actually 3D. For w I wrote w1, w2, ..., wn to better visualize the windows. The solution I'm looking for should only be solved by using numpy (as clearly stated in my question). – Spenhouet Jun 26 '18 at 12:21
  • Again, I'm not what you are missing. Your variable 'result' is clearly 2D. – David Jun 26 '18 at 17:42

1 Answers1

0

Before getting to the answer, to be clear, this was a duplicate of the sliding window question that was referenced. You needed to simply add a dimension and account for padding. Given your ranking on this site, I would have assumed you would have read the question and skimmed the documentation. It is clear you did not do that. Please do so in the future.

Below is the code that solves your posted example. I'll leave it up to you to handle the cases where the final shape is different.

import numpy as np                                                                                   

a = np.array([[0, 0, 0, 0, 0, 0, 0, 0],                                                              
     [0, 1, 2, 3, 4, 5, 6, 0],                                                                       
     [0, 1, 2, 3, 4, 5, 6, 0],                                                                       
     [0, 1, 2, 3, 4, 5, 6, 0],                                                                       
     [0, 0, 0, 0, 0, 0, 0, 0]])                                                                      

def window_stack(x, stepsize=1, window=3, pad=1):                                                    
    m,n = x.shape                                                                                    
    res = np.array([[x[i:i+window:stepsize,j:j+window:stepsize] for j in range(n-window+1)] for i in\
 range(m-window+1)])                                                                                 
    m -= 2*pad                                                                                       
    n -= 2*pad                                                                                       
    return res.reshape(m*n,window*window)                                                            

res = window_stack(a)                                                                                

print "Original:"                                                                                    
print a                                                                                              
print                                                                                                
print "Result:"                                                                                      
print res
David
  • 696
  • 6
  • 19
  • Thanks for your answer. But it doesn't answer my question. I asked for a numpy solution (without any other methods like for loops, ...). That is why this type of solution from the linked question isn't applicable to my question. – Spenhouet Jun 26 '18 at 12:14
  • You said using numpy, not exclusively using numpy. If you are trying to get this type of performance then why don't you write some C, compile it, and then call that from Python. You'll avoid the python for loops and get what you need. – David Jun 26 '18 at 17:41
  • 1
    I believe it can be done how you've specified, but I'll have to work on it after work. – David Jun 26 '18 at 17:56
  • For production code you are absolutely right. I was just wondering if and how this could be done by only using numpy in python. I first tried the bit shifting and index tricks mentioned in the linked answer but this didn't get me far, therefore I thought I would ask the community if someone knows how to do this. It would be great if you find a solution and very interesting to see. – Spenhouet Jun 26 '18 at 18:36
  • It's going to take some kind of hacky-ish numpy reshaping, but yeah. – David Jun 26 '18 at 19:22
  • If the window is static then you should be able to do this, but you want a non-defined window size, so no, cant with pure numpy. You'll need loops. – David Jun 26 '18 at 20:51
  • The window size can be static for one run (it doesn't change dynamically) but it should be adjustable. – Spenhouet Jun 27 '18 at 06:38