【问题标题】:Change values of four nearest neighbours of certain matrix cells更改某些矩阵单元的四个最近邻居的值
【发布时间】:2017-07-01 18:20:03
【问题描述】:

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

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

我尝试过使用两个嵌套的 for 循环,但使用索引会变得非常棘手。我将不胜感激。

【问题讨论】:

    标签: matlab matrix


    【解决方案1】:

    我从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 覆盖到原始单元格中。

    也就是说,

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

    【讨论】:

      【解决方案2】:

      您可以使用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; 等的原因。当然,除非你真的想要圆形边界条件。这就是我得到的


      还有这个,我认为这样做更有效。

      对于每个给定的像素,四个最近邻的线性索引由偏移量给出

      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
      

      【讨论】:

        【解决方案3】:

        @Vahe Tshitoyan 使用 circshift 的答案似乎不错,而我使用的是 for 循环:

        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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-06-20
          • 2019-05-26
          • 1970-01-01
          • 2011-06-22
          • 1970-01-01
          • 2016-04-06
          • 1970-01-01
          • 2019-04-09
          相关资源
          最近更新 更多