在数组的最大值附近查找数组

时间:2019-03-06 11:13:11

标签: matlab image-processing matrix

我正在研究一个非常复杂的问题。用语言描述是非常困难的,因此我将尝试用一个例子来解释它。

假设我有一个值矩阵:

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最大值附近的矩阵。有人可以告诉我如何在不使用double for循环的情况下做到这一点吗?

谢谢!

5 个答案:

答案 0 :(得分:5)

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

Since we have max indices per column, but later want to access these elements in the original array A, we need proper linear indices for A. Here, the trick is to add the number of rows multiplied by the column index (starting by 0). The easiest way to understand might be to remove the semicolons, and inspect the intermediate values of ind.

答案 1 :(得分:4)

@HansHirse's answer is more efficient, as it does not create an intermediate matrix.


Try this:

[~, 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, []);

For Matlab R2016b or newer, you can simplify the third line:

[~, 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, []);

答案 2 :(得分: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));

答案 3 :(得分:0)

尽管效率不如其他解决方案,但您可以使用“图像处理工具箱”来生成结果。

[~,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, []);

答案 4 :(得分:0)

仅供参考,这是3D盒的一般形式:

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