【问题标题】:Sliding max window and its average for multi-dimensional arrays多维数组的滑动最大窗口及其平均值
【发布时间】:2015-05-06 19:22:45
【问题描述】:

我有一个60 x 21 x 700 矩阵,其中60 x 21 代表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 还很陌生,所以如果我遗漏了什么或者只是没有正确理解事情,我深表歉意。 任何帮助或指导将不胜感激。

【问题讨论】:

  • 矩阵的维度不能被2整除。你想为此做什么?
  • @SanthanSalai,我认为 OP 正在考虑“滑动”平均值,因此矩阵大小不必是窗口大小的精确倍数。 Gumajin,请您确认或确认这一点。
  • @Hoki 是的,我认为这将是最接近我想要实现的目标。对不起,如果我的问题不是很清楚。

标签: matlab matrix


【解决方案1】:

二维数组:对于给定的二维数组输入,可以使用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

【讨论】:

  • 我正要打字完全一样。我认为这是最有效的方式,因为 conv2 在过去非常快。
  • 该死的你总是在这些上打败我!干得好;-)
  • @Hoki 对不起! :) 事实证明,我们甚至不需要在每个窗口中找到平均值。
  • 非常感谢。因此,如果我想为所有 700 帧计算这个值,是否可以使用 for 循环?
  • 请注意,如果您使用 valid 而不是 same 作为卷积输出选项,则不必丢弃最后一行和最后一列(因为它们只是 2 个值而不是 4 个值的平均值)。
【解决方案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
    

    【讨论】:

      猜你喜欢
      • 2017-09-03
      • 1970-01-01
      • 1970-01-01
      • 2019-02-26
      • 1970-01-01
      • 1970-01-01
      • 2012-05-30
      • 2018-02-03
      • 1970-01-01
      相关资源
      最近更新 更多