Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sliding window summation of a matrix

I have a 50x50 matrix, and I'd like to sum up the values in every 10x10 (or another set size value - always square) overlapping grid i.e.:

enter image description here

Overlapping windows are shown only in the diagonal for the sake of clarity. The first task I've tried to do is define the coordinates of each window:

win=10;
start = [1,10,1,10];
for y=1:(50-win)
    for g=1:(50-win)
        tmp = [start(g,1)+1,start(g,2)+1,start(end,3),start(end,4)];
        start = [start;tmp];
    end
    start(end+1,1:4) = [1,10,1+y,10+y];
end

And then I'd loop over the list of coordinates, using sum and logical indexing for each window.

PROBLEM #1: The above code is not particularly eloquent. Can anybody show a more 'MATLABesque' way of doing it or a more concise way?

PROBLEM #2: I'd then like to define a particular coordinate (index) in the matrix e.g. m(26,26) and get a list of all windows this coordinate is contained within. But I have no idea how to do this. Can anybody show me how?

like image 449
user3012926 Avatar asked Jul 23 '20 13:07

user3012926


People also ask

What is the sliding window method?

In the sliding window method, a window of specified length, Len, moves over the data, sample by sample, and the statistic is computed over the data in the window. The output for each input sample is the statistic over the window of the current sample and the Len - 1 previous samples.

What is a sliding window in java?

The Sliding window is a problem-solving technique of data structure and algorithm for problems that apply arrays or lists. These problems are painless to solve using a brute force approach in O(n²) or O(n³). However, the Sliding window technique can reduce the time complexity to O(n).

What is the time complexity of sliding window?

The time complexity of this solution is O(n) because each element is visited at most twice. In the worst case scenario, all elements will be visited once by the start pointer and another time by the end pointer.


2 Answers

Problem #1

The most Matlab-like way for doing this I can think of is two-dimensional convolution (conv2) (as I now see was commented by @rahnema1):

M = randi(9, 5, 5); % input: square matrix, arbitrary size
N = 3; % block size, assumed square, not larger than M
result = conv2(M, ones(N), 'valid');

Equivalently, you can use the recently introduced movsum function, twice (once for each dimension):

result = movsum(movsum(M, N, 1, 'Endpoints', 'discard'), N, 2, 'Endpoints', 'discard');

Example:

M =
     4     4     3     1     2
     2     8     7     1     6
     3     6     7     5     5
     6     5     4     8     1
     5     9     6     9     4

result =
    44    42    37
    48    51    44
    51    59    49

Problem #2

The simplest way (not the most efficient one) is to use convolution again with a logical matrix containing true at the desired position and false otherwise, and checking where the convolution is not zero:

in_coords = [3 4]; % example input coordinates
T = false(size(M)); % initiallize matrix containing false, same size as M
T(in_coords(1), in_coords(2)) = true; % true at the desired coordinates
C = conv2(T, ones(N), 'valid'); % this gives 1 for blocks affected by in_coords
[ii, jj] = find(C); % row and column indices of nonzero values 
out_coords = [ii jj]; % build result

In this example,

out_coords =
     1     2
     2     2
     3     2
     1     3
     2     3
     3     3
like image 182
Luis Mendo Avatar answered Sep 30 '22 07:09

Luis Mendo


EDIT: you want the conv2 solution. I answered this when you only asked whats in in the body, and not comments, so I answered on how to get the diagonal sliding of the windows. If you want all, you want conv2 as Luis suggests.

Answer to #1

num_pixels_box=10;
offset=[1,1];
num_offsets=size(img,1)/num_pixels_box; % assumes square image and box

for ii=1:num_offsets
    index_start=[0,0]+ii*offset;
    index_end = index_start+[num_pixels_box-1,num_pixels_box-1];
    result(ii)=sum(sum(img(index_start(1):index_end(1),index_start(2):index_end(2))));
end

I havent tested it, but should be the general idea on how to crate it in a MATLABesque way. you can combine these things into other variables, or more compact forms, but I hope this way it makes sense.

Answer to #2

If you have upper and lower bounds of a square, knowing if a point is inside of it its just couple of if conditions. Make a function is_in_square() for clarity. Then just loop over existing windows.

like image 33
Ander Biguri Avatar answered Sep 30 '22 07:09

Ander Biguri