更改某些矩阵单元的四个最近邻居的值

时间:2017-07-01 18:20:04

标签: matlab matrix

我有一个矩阵,其中值-1是随机分布的(参见图像中的黄色单元格)。矩阵的其余部分填充0(蓝色单元格)。

我现在需要从左侧,右侧,顶部或底部填充与-1相邻的单元格1.如果几个单元格的-1彼此相邻,则不应覆盖这些-1。

我尝试过两个嵌套的for循环,但它对索引非常棘手。我将不胜感激任何帮助。

see figure

3 个答案:

答案 0 :(得分:4)

我正在借用Vahe Tshitoyan's answer中的示例矩阵生成:

A = zeros(10,10);
A(randi(100,1,20))=-1;
colormap(parula(3));    % set colormap: blue, yellow, bluish green
image(-A*2+1);          % -A*2+1 is just a trick to get the desired colors
axis square

你可以

  1. 使用2D卷积(conv2)将1写入围绕等于-1的单元格的单元格中。
  2. -1覆盖到原始单元格中。
  3. 即,

    mask = [0 1 0; 1 0 1; 0 1 0];             % define neighbouthood mask
    B = double(conv2(-A, mask, 'same') > 0);  % step 1
    B(A==-1) = -1;                            % step 2
    figure
    colormap(parula(3));
    image(-B*2+1+3*(B==1));                   % similar trick to that used before
    axis square
    

    示例原始矩阵(A)和结果矩阵(B):

    enter image description here enter image description here

答案 1 :(得分:3)

您可以使用circshift功能。

% generating the matrix
A = zeros(10,10);
A(randi(100,1,20))=-1;
figure(1);imagesc(A, [-1 1]);

% neighbours + no circular boundary condition
downshifted = circshift(A, 1, 1);downshifted(1,:)=0;
upshifted = circshift(A, -1, 1);upshifted(end,:)=0;
leftshifted = circshift(A, -1, 2);leftshifted(:,end)=0;
rightshifted = circshift(A, 1, 2);rightshifted(:,1)=0;

% combining neighbours and removing where A~=0
neighbours = (downshifted|upshifted|leftshifted|rightshifted)&~A;

% final matrix
B = A+neighbours;
figure(2);imagesc(B, [-1 1]);

要注意的一点是circshift的圆形边界条件。这就是我手动设置downshifted(1,:)=0;等的原因。当然,除非你真的想要圆形边界条件。这就是我得到的

before and after

在我看来,还有更有效的方法。

对于每个给定像素,四个最近邻居的线性指数由

的偏移给出
offsets = [-n, -1, +1, +n];

其中n是行数。因此,您可以使用

之类的东西计算所有邻居的索引
minusOneInd = find(A==-1); % the linear indices of -1s
indices = unique(bsxfun(@plus, minusOneInd, offsets)); % all neighbours

然而,由于边缘和索引耗尽,这会导致一些麻烦。解决此问题的一种方法是用0填充初始矩阵,然后在操作完成后删除填充。如果A是您的初始矩阵,则可以按如下方式编写满足您所需要的完整代码。

Ap = padarray(A,[1 1]); % to get rid of the edge effects
n = size(Ap, 1);
offsets = [-n, +1, -1, +n]; % index offsets of four neighbours

minusOneInd = find(Ap==-1); % finding the indices of -1s
indices = unique(bsxfun(@plus, minusOneInd, offsets)); % neighbours
% now, remove out of range indices and indices where A is -1
indices(indices<1|indices>numel(Ap)|ismember(indices, minusOneInd))=[]; 

Ap(ind2sub(size(Ap),indices)) = 1; % assigning the ones
B = Ap(2:end-1,2:end-1); % this is what we want

答案 2 :(得分:0)

@Vahe Tshitoyan使用 circshift 的答案似乎很好,而我使用进行循环:

M = zeros(10);
M(randi(100, [1,20])) = -1;
siz = size(M);
[I, J] = ind2sub(siz, find(M == -1)); % row, column indice of those -1
for i = 1:numel(I)
    if I(i)>1 && M(I(i)-1, J(i))~=-1, M(I(i)-1, J(i)) = 1; end % above
    if I(i)<siz(1) && M(I(i)+1, J(i))~=-1, M(I(i)+1, J(i)) = 1; end % below
    if J(i)>1 && M(I(i), J(i)-1)~=-1, M(I(i), J(i)-1) = 1; end % left
    if J(i)<siz(2) && M(I(i), J(i)+1)~=-1, M(I(i), J(i)+1) = 1; end % right
end