【问题标题】:Select n elements in matrix left-wise based on certain value根据某个值向左选择矩阵中的 n 个元素
【发布时间】:2025-12-16 12:50:02
【问题描述】:

我有一个逻辑矩阵 A,我想选择给定距离的每个 1s 值左侧的所有元素。假设我的距离是 4,我想(例如)用一个固定值(比如 2)替换 A 中每个 1 左侧的所有 4 个单元格。

A= [0 0 0 0 0 1 0
   0 1 0 0 0 0 0
   0 0 0 0 0 0 0
   0 0 0 0 1 0 1]

B= [0 2 2 2 2 1 0
   2 1 0 0 0 0 0
   0 0 0 0 0 0 0
   2 2 2 2 2 2 1]

在 B 中是我想要的,同时考虑覆盖(B 中的最后一行),以及在我的 1 左侧只有 1 个值而不是 4 作为固定搜索距离(第二行)的情况。

【问题讨论】:

  • 你试过什么?您可以为单个向量执行此操作吗?您是否考虑过仅循环遍历行?
  • 是的,就像示例的最后一行一样。如果有时在此操作期间某些 1 被 2 覆盖,这不是问题(就像我的示例中矩阵的最后一行)
  • 它应该是0,因为我只改变左边的4个单元格,那个0是第五个。
  • 已经撤消了错误的编辑并调整了我的答案。

标签: arrays matlab matrix


【解决方案1】:

这个可爱的单线怎么样?

n = 3;
const = 5;
A = [0 0 0 0 0 1 0;
     0 1 0 0 0 0 0;
     0 0 0 0 0 0 0;
     0 0 0 0 1 0 1]

A(bsxfun(@ne,fliplr(filter(ones(1,1+n),1,fliplr(A),[],2)),A)) = const

结果:

A =

     0     0     5     5     5     1     0
     5     1     0     0     0     0     0
     0     0     0     0     0     0     0
     0     5     5     5     5     5     1

这里有一些解释:

Am = fliplr(A);                      %// mirrored input required
Bm = filter(ones(1,1+n),1,Am,[],2);  %// moving average filter for 2nd dimension
B = fliplr(Bm);                      %// back mirrored
mask = bsxfun(@ne,B,A)               %// mask for constants
A(mask) = const

【讨论】:

    【解决方案2】:

    这是一个您可以想出的简单解决方案:

    w=4;                            % Window size
    v=2;                            % Desired value
    
    B = A;
    for r=1:size(A,1)               % Go over all rows
      for c=2:size(A,2)             % Go over all columns
        if A(r,c)==1                % If we encounter a 1
           B(r,max(1,c-w):c-1)=v;   % Set the four spots before this point to your value (if possible)
        end
      end
    end
    

    【讨论】:

      【解决方案3】:
      d = 4; %// distance
      v = 2; %// value
      
      A = fliplr(A).'; %'// flip matrix, and transpose to work along rows.
      ind = logical( cumsum(A) ...
          - [ zeros(size(A,1)-d+2,size(A,2)); cumsum(A(1:end-d-1,:)) ] - A );
      A(ind) = v;
      A = fliplr(A.');
      

      结果:

      A =
           0     2     2     2     2     1     0
           2     1     0     0     0     0     0
           0     0     0     0     0     0     0
           2     2     2     2     2     2     1
      

      【讨论】:

        【解决方案4】:

        方法 #1 使用 imdilate 的单线,可用于 Image Processing Toolbox -

        A(imdilate(A,[ones(1,4) zeros(1,4+1)])==1)=2
        

        说明

        步骤#1:创建一个与imdilate一起使用的形态结构元素-

        morph_strel = [ones(1,4) zeros(1,4+1)]
        

        这基本上表示一个窗口,将n 向左扩展为 1,向右扩展 n 个位置,包括以 0 表示的原点。

        步骤 #2: 使用 imdilate 将修改 A,这样我们将在 A 中每个 1 左侧的所有四个位置都有 1 -

        imdilate_result = imdilate(A,morph_strel)
        

        步骤#3:A 中的每个1 选择所有四个索引并将它们设置为2 -

        A(imdilate_result==1)=2
        

        因此,可以将这种方法的一般形式写为 -

        A(imdilate(A,[ones(1,window_length) zeros(1,window_length+1)])==1)=new_value
        

        对于给定的数据,window_length 将是 4new_value 将是 2


        方法 #2 使用 bsxfun-

        %// Paramters
        window_length = 4;
        new_value = 2;
        
        B = A' %//'
        [r,c] = find(B)
        extents = bsxfun(@plus,r,-window_length:-1)
        valid_ind1 = extents>0
        jump_factor = (c-1)*size(B,1)
        extents_valid = extents.*valid_ind1
        B(nonzeros(bsxfun(@plus,extents_valid,jump_factor).*valid_ind1))=new_value
        B = B' %// B is the desired output
        

        【讨论】:

          最近更新 更多