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