Sliding max window and its average for multi-dimensional arrays

烈酒焚心 提交于 2020-01-01 02:45:09

问题


I have a 60 x 21 x 700 matrix, where the 60 x 21 represent a pressure output x number of frames. I want to find the 2 x 2 window that generates the maximum average pressure per frame and store it in a new variable so that it can be plotted. For example, if the matrix looked something like this:

01 02 02 01 01
02 01 01 02 02
02 03 04 04 03
01 02 06 10 05
02 02 08 09 05

The max window and its average for a 2 x 2 window would be -

06 10
08 09

= 8.25

So far in my search for a solution I've only been able to find a way to get the max value (eg. 10 from the matrix above), but really can't work out how to get the max average from a small area that doesn't have a fixed index to reference. I'm fairly new to MATLAB, so my apologies if I've missed something or am simply not understanding things correctly. Any help or guidance would be much appreciated.


回答1:


2D Arrays: For the given 2D array input, you can use 2D convolution -

%// Perform 2D convolution with a kernel of `2 x 2` size with all ones
conv2_out = conv2(A,ones(2,2),'same')

%// Find starting row-col indices of the window that has the maximum conv value
[~,idx] = max(conv2_out(:))
[R,C] = ind2sub(size(A),idx)

%// Get the window with max convolution value
max_window = A(R:R+1,C:C+1)

%// Get the average of the max window
out =  mean2(max_window)

Sample step-by-step run of the code -

A =
     1     2     2     1     1
     2     1     1     2     2
     2     3     4     4     3
     1     2     6    10     5
     2     2     8     9     5
conv2_out =
     6     6     6     6     3
     8     9    11    11     5
     8    15    24    22     8
     7    18    33    29    10
     4    10    17    14     5
idx =
    14
R =
     4
C =
     3
max_window =
     6    10
     8     9
out =
         8.25

Multi-dimensional Arrays: For multi-dimensional array case, you need to perform ND convolution -

%// Perform ND convolution with a kernel of 2 x 2 size with all ONES
conv_out = convn(A,ones(2,2),'same')

%// Get the average for all max windows in all frames/slices  
[~,idx] = max(reshape(conv_out,[],size(conv_out,3)),[],1)
max_avg_vals = conv_out([0:size(A,3)-1]*numel(A(:,:,1)) + idx)/4

%// If needed, get the max windows across all dim3 slices/frames
nrows = size(A,1)
start_idx = [0:size(A,3)-1]*numel(A(:,:,1)) + idx
all_idx = bsxfun(@plus,permute(start_idx(:),[3 2 1]),[0 nrows;1 nrows+1])
max_window = A(all_idx)

Sample input, output -

>> A
A(:,:,1) =
     4     1     9     9
     3     7     5     5
     9     6     1     6
     7     1     1     5
     4     2     2     1
A(:,:,2) =
     9     4     2     2
     3     6     4     5
     3     9     1     1
     6     6     8     8
     5     3     6     4
A(:,:,3) =
     5     5     7     7
     6     1     9     9
     7     7     5     4
     4     1     3     7
     1     9     3     1
>> max_window
max_window(:,:,1) =
     9     9
     5     5
max_window(:,:,2) =
     8     8
     6     4
max_window(:,:,3) =
     7     7
     9     9
>> max_avg_vals
max_avg_vals =
            7          6.5            8



回答2:


A moving average can be done with a simple convolution. It has to be 2D in your case, so:

A = [01 02 02 01 01
     02 01 01 02 02
     02 03 04 04 03
     01 02 06 10 05
     02 02 08 09 05];

B = [1 1;1 1] / 4 ; %// prepare moving average filter [2x2]

C = conv2(A,B,'valid') ; %// perform 2D moving average

Produces:

C =
    1.5     1.5     1.5     1.5
    2       2.25    2.75    2.75
    2       3.75    6       5.5
    1.75    4.5     8.25    7.25

Which is exactly the average of each of your [2x2] areas.




回答3:


One other approach using im2col

%// getting each 2x2 sliding submatrices as columns
cols = im2col(A,[2 2],'sliding'); 

%// getting the mean & reshaping it to 2D matrix
C = reshape(mean(cols),size(A,1)-1,[]); 

%// to find the maximum of the sub-matrix-means and its corresponding index.
[B,i] = max(mean(cols)); 

%// reshaping the corresponding sub-matrix to 2D matrix
mat = reshape(cols(:,i),2,2); 

Results:

>> mat

mat =

 6    10
 8     9

>> C

C =

1.5000    1.5000    1.5000    1.5000
2.0000    2.2500    2.7500    2.7500
2.0000    3.7500    6.0000    5.5000
1.7500    4.5000    8.2500    7.2500

>> B

B =

8.2500


来源:https://stackoverflow.com/questions/30072284/sliding-max-window-and-its-average-for-multi-dimensional-arrays

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