Sliding window summation of a matrix

时光怂恿深爱的人放手 提交于 2020-08-06 21:38:47

问题


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.:

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?


回答1:


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



回答2:


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.



来源:https://stackoverflow.com/questions/63055349/sliding-window-summation-of-a-matrix

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!