Скользящее максимальное окно и его среднее значение для многомерных массивов

У меня есть матрица 60 x 21 x 700, где 60 x 21 представляют a pressure output x number of frames. Я хочу найти окно 2 x 2, которое генерирует максимальное среднее давление на кадр и сохраняет его в новой переменной, чтобы можно было построить график. Например, если матрица выглядела примерно так:

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

Максимальное окно и его среднее значение для окна 2 x 2 будет -

06 10
08 09

= 8.25

До сих пор в моем поиске решения я только смог найти способ получить максимальное значение (например, 10 из приведенной выше матрицы), но на самом деле не получается выяснить, как получить максимальную среднее значение от небольшой области, которая не имеет фиксированного индекса для ссылки. Я новичок в MATLAB, поэтому извиняюсь, если я что-то пропустил или просто не понимаю вещи правильно. Любая помощь или руководство будут высоко оценены.

Ответ 1

2D-массивы:. Для данного ввода 2D-массива вы можете использовать 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)

Пример пошагового запуска кода -

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

Многомерные массивы: Для многомерного массива вам необходимо выполнить 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)

Пример ввода, вывод -

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

Скользящее среднее можно сделать с помощью простой свертки. Он должен быть 2D в вашем случае, поэтому:

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

Выдает:

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

Это точно среднее значение для каждой из ваших областей [2x2].

Ответ 3

Один другой подход с использованием 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); 

Результаты:

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