【问题标题】:Find Array around Maximum Values of an Array查找数组最大值附近的数组
【发布时间】:2019-07-28 00:53:56
【问题描述】:

我正在处理一个非常复杂的问题。这很难用语言来描述,所以我将尝试用一个例子来解释它。

假设我有一个值矩阵:

A = 

[31 85 36 71 51] 
[12 33 74 39 12]
[67 11 13 14 18]
[35 36 84 33 57]

现在,我想先在第一维中找到一个最大向量,这很容易:

[max_vector,~] = max(A,[],1);


max_vector=[67,85, 84, 71,57]

现在我想得到一个“瘦身”矩阵,其值在最大值(周期性索引)附近:

Desired_Matrix =

 [12 36 36 33 18]
 [67 85 84 71 57]
 [35 33 13 39 51]

这是一个矩阵,其向量围绕矩阵 A 的最大值。有人可以告诉我如何在不使用双 for 循环的情况下做到这一点吗?

谢谢!

【问题讨论】:

  • 您对这个问题有一些非常好的答案,consider accepting one of them。我建议这样做是因为您有几个问题的答案,但从未接受过答案,也许您没有意识到这种可能性。您不需要接受,但这被认为是一种好的做法。

标签: matlab image-processing matrix


【解决方案1】:
% Input.
A = [31 85 36 71 51; 12 33 74 39 12; 67 11 13 14 18; 35 36 84 33 57]

% Dimensions needed.
nRows = size(A, 1);
nCols = size(A, 2);

% Get maxima and corresponding indices in input.
[max_vector, ind] = max(A);

% Get neighbouring indices.
ind = [ind - 1; ind; ind + 1];

% Modulo indices to prevent dimension overflow.
ind = mod(ind, nRows);

% Correct zero indices.
ind(ind == 0) = nRows;

% Calculate correct indices in A.
temp = repmat(0:nRows:nRows*(nCols-1), 3, 1);
ind = ind + temp;

% Output.
B = A(ind)

由于我们每列有最大索引,但稍后想要访问原始数组A 中的这些元素,我们需要正确的linear indices 来获取A。在这里,诀窍是添加行数乘以列索引(从 0 开始)。最容易理解的方法可能是删除分号,并检查 ind 的中间值。

【讨论】:

  • 我喜欢你的模块化索引想法
  • 我不明白这一行: temp = repmat(0:nRows:nRows^2, 3, 1);你能告诉我这是做什么的吗?
  • 你有一个小的数学错误 - 0:nRows:nRows^2 恰好是正确的大小,因为在这个例子中 size(A,2) - 1 == size(A,1)。应该是0:nRows:nRows*nCols-1
  • @Wolfie 感谢您的更正,我相应地编辑了我的答案。多么愚蠢,因为在我的文字解释中,我就是这样描述的。对您的更正的小修正:0:nRows:nRows*(nCols-1) 而不是0:nRows:nRows*nCols-1。两者都有效,但“绝对正确”应该是带括号的版本。
  • 两者的工作方式完全相同。使用0:x:y 表示法创建一个数组,每个元素nix*i,这样ni < y。无论有无括号,我认为x*i 的上限值相同。在您的情况下,可能的上限值和y 相等,在我的情况下,我依赖于MATLAB 对严格< 的评估。我认为个人偏好更有意义 - 我只知道没有 -1 我会包含太多值,你知道你的目标是什么。
【解决方案2】:

@HansHirse's answer 更高效,因为它不会创建中间矩阵。


试试这个:

[~, ind_max] = max(A,[],1);
A_ext = A([end 1:end 1],:);
ind_lin = bsxfun(@plus, bsxfun(@plus, ind_max, (0:2).'), (0:size(A_ext,2)-1)*size(A_ext,1));
result = reshape(A_ext(ind_lin), 3, []);

对于 Matlab R2016b 或更高版本,可以简化第三行:

[~, ind_max] = max(A,[],1);
A_ext = A([end 1:end 1],:);
ind_lin = ind_max + (0:2).' + (0:size(A_ext,2)-1)*size(A_ext,1);
result = reshape(A_ext(ind_lin), 3, []);

【讨论】:

    【解决方案3】:

    这是另一种解决方案。这类似于HansHirse's answer,但有两个改进:

    • 更优雅地处理模块化索引
    • 更灵活地指定您想要的邻居

    代码:

    % Input
    A = [31 85 36 71 51; 
        12 33 74 39 12; 
        67 11 13 14 18; 
        35 36 84 33 57];
    
    % Relative rows of neighbours, i.e. this is [-1, 0, 1] for +/- one row
    p = -1:1;
    % Get A row and column counts for ease
    [nr, nc] = size(A);
    % Get max indices
    [~,idx] = max( A, [], 1 );
    % Handle overflowing indices to wrap around rows
    % You don't have to redefine "idx", could use this directly in the indexing line
    idx = mod( idx + p.' - 1, nr ) + 1;
    % Output B. The "+ ... " is to convert to linear indices, as "idx"
    % currently just refers to the row number.
    B = A(idx + (0:nr:nr*nc-1));
    

    【讨论】:

      【解决方案4】:

      您可以使用图像处理工具箱生成结果,但效率低于其他解决方案。

      [~,idx] = max(A, [], 1);
      d = imdilate( idx == (1:size(A,1) ).', [1;1;1], 'full');
      p = padarray(A, 1, 'circular');
      Desired_Matrix = reshape(p(d), 3, []);
      

      【讨论】:

        【解决方案5】:

        仅供参考,以下是 3D-Case 的通用形式:

        A = zeros(3,5,5);
        
        for id = 1: 20
            A(:,:,id) = id;
        
        
            if id == 10
                A(:,:,id) = 100;
            end
        
        end
        
        
        % Relative rows of neighbours, i.e. this is [-1, 0, 1] for +/- one row
        p = -1:1;
        % Get A row and column counts for ease
        [nr, nc, nz] = size(A);
        % Get max indices
        [~,idx] = max( A, [], 3 );
        % Handle overflowing indices to wrap around rows
        % You don't have to redefine "idx", could use this directly in the indexing line
        idx = mod( idx + reshape(p,1,1,3) - 1, nz ) + 1;
        % Output B. The "+ ... " is to convert to linear indices, as "idx"
        % currently just refers to the row number.
        
        INDICES = ((idx-1) * (nr*nc)+1 )+ reshape(0:1:nc*nr-1,nr,nc);
        
        B = A(INDICES);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-14
          • 2018-11-20
          • 2021-09-15
          • 2018-06-05
          • 2018-11-25
          • 1970-01-01
          相关资源
          最近更新 更多