【问题标题】:Check neighbor values in a matrix, Matlab检查矩阵中的邻居值,Matlab
【发布时间】:2018-02-17 23:11:39
【问题描述】:

我的问题是:我必须编写一个代码,该代码采用 0 和 1 的 6x6 矩阵,并检查矩阵每个位置的某些条件以迭代它,并根据条件创建一个具有新值的矩阵,基于中心值的相邻元素。条件如下:

如果中心值为 1,它有 3 个选项:

-如果在相邻单元格中只有一个单元格包含数字 1,或者 cero 单元格包含数字 1,则中心值从 1 转换为 0。

-如果中心值的相邻单元格总共包含4个或更多的1,则从1转换为0。

-如果相邻单元格总共包含 2 或 3 个数字 1,则保持为 1。

现在,如果中心值为 0,则它有 1 个选项:

-如果相邻单元格总共包含 3 个 1(顶部),它将从 0 转换为 1。

-否则一直为0

矩阵如下:

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

比如,A(5,2)位置的数字1应该变成0,因为它周围有4个1,再比如A(4,6)的0 ) 应该变成 1,因为它周围有 3 个 1。

我创建了 2 个循环,其中 1 个用于行,另一个用于列,以遍历矩阵的每个值,但在有条件的情况下,我不知道如何检查周围单元格或相邻单元格的值

我是 Matlab 新手,如果你能帮助我,那就太好了!谢谢。

编辑:添加了我到目前为止所做的代码。

[f,c]=size(A)
for i=1:f
       for j=1:c
            if A(i,:)==1

              if A(i+1,j+1)==1 && A(i+1,j-1)==1 && A(i-1,j-1)==1
                  A(i,:)=1;
              end 

          elseif A(i,:)==0

              if A(i+1,j+1)==1 && A(i+1,j-1)==1 && A(i-1,j-1)==1
                  A(i,:)=1;

              end
          end
     end
 end

我尝试将条件设置为 (i-1,j-1),(i+1,j+1),(i+1,j),(i,j+1),(i- 1,j),(i,j-1) 但我认为这行不通,因为我正在检查 coditions 作为一个组,而不是计算邻居中 1 的总数

编辑 2:一直在考虑如何解决它,我认为我可以创建一个变量来计算中心值周围 1 的数量,但它给了我一个错误,它超出了矩阵的维度第 50 行,即使在我考虑了第一列、行和最后一列、行之后。

这是完整的代码:

[f,c] = size(gen0);
nrogen = input('Introduzca el número de generaciones de bacterias que quiera crecer: ');

if isempty(nrogen) || ~isnumeric(nrogen) || ~isscalar(nrogen) || round(nrogen)~=nrogen || nrogen < 0
    disp('Número no pertinente, intente de nuevo');
    return
end

nac = 0;
mue = 0;
neigh = 0;

for k=1:nrogen
    for i=1:f
        for j=1:c
            if i>1 && i<6
                if gen0(i+1,j+1)==1
                    neigh=neigh+1;
                end

                if gen0(i,j+1)==1
                    neigh=neigh+1;
                end

                if gen0(i+1,j)==1
                    neigh=neigh+1;
                end

                if gen0(i-1,j-1)==1
                    neigh=neigh+1;
                end

                if gen0(i,j-1)==1
                    neigh=neigh+1;
                end

                if gen0(i-1,j)==1
                    neigh=neigh+1;
                end

            elseif i==1 

                if gen0(i+1,j+1)==1
                    neigh=neigh+1;
                end

                if gen0(i,j+1)==1
                    neigh=neigh+1;
                end

                if gen0(i+1,j)==1
                    neigh=neigh+1;
                end

            elseif i==6

                if gen0(i-1,j-1)==1
                    neigh=neigh+1;
                end

                if gen0(i,j-1)==1
                    neigh=neigh+1;
                end

                if gen0(i-1,j)==1
                    neigh=neigh+1;
                end


                if gen0(i,:)==1
                    if neigh==2 || neigh==3
                        gen0(i,:)=1;
                    elseif neigh==1 || neigh==0
                        gen0(i,:)=0;
                    end
                end
            end
        end
        disp(gen0);
    end

    if gen0(i,:)==1
        if neigh==2 || neigh==3
            gen0(i,:)=1;
        elseif neigh==1 || neigh==0 || neigh>3
            gen0(i,:)=0;
        end
    end
end

【问题讨论】:

  • 你能告诉我们循环(你拥有的所有代码)吗?最好从错误中吸取教训,而不是仅仅复制正确的答案。
  • @ViG 添加了代码。这就是我所拥有的,我是一般编程的新手,所以我对这个问题有点沮丧。感谢您的回答!
  • @ViG 一直在思考如何自己制作!查看帖子,谢谢

标签: matlab loops matrix


【解决方案1】:

嵌套循环是一个明智的选择。但是,您所做的基本上是一个图像过滤器,它已经由函数 imfilter 实现,所以为什么不利用它来简化您的生活呢?你想做的事情可以通过以下方式完成:

%Creating the filter that adds up all neighbors
filter=ones(3,3);
filter(2,2)=0;
%Apply the filter to compute the sum of all neighboring elements
onesCount=imfilter(A,filter);
%Creating the rules in arrays that contains result for a given count of ones (+1)
%ones count 0 1 2 3 4 5 6 7 8 9
onesRule = [0 0 1 1 0 0 0 0 0 0];
zeroRule = [0 0 0 1 0 0 0 0 0 0];
%Initializing output matrix
out=zeros(size(A));
%Assigning values to the cells with ones
outForOnes=onesRule(onesCount+1);
out(A==1)=outForOnes(A==1);
%Assigning values to the cells with zeros 
%(if you want you can skip this step initializing out=outForZeros)
outForZeros=zeroRule(onesCount+1);
out(A==0)=outForZeros(A==0);

否则,如果您想保留嵌套循环,而不是处理索引超出范围的异常,我建议在 A 周围用零填充。因此,如果 A 大小为 n x m(在本例中为 6 x 6),您可以这样做:

B=zeros(n+2,m+2);
B(2:end-1,2:end-1)=A;
A=B;

然后你在 2:n+1 和 2:m+1 之间循环 i 和 j

【讨论】:

  • 好像更简单哈哈。但是我不能使用除了循环和条件之外的任何东西,但还是谢谢你!哇,异常的解决方案很好!谢谢!我会用那个
  • @DanielArocha 您应该在问题中说明这一点。如果您对目前给出的解决方案不满意,我可以建议使用循环的替代方案。
  • 你是对的,我很抱歉。不用担心,问题解决了!感谢您和 Belluzzo,我设法解决了这个问题。
【解决方案2】:

在我看来,在这种情况下使用两个嵌套循环是一个好方法。检索矩阵元素的周围值总是很棘手,但可以通过一些努力来完成。这是我建议您的解决方案:

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

A_rows = size(A,1);
A_cols = size(A,2);

for i = 1:A_rows
    for j = 1:A_cols
        % Retrieve the current center...
        value = A(i,j);

        % Retrieve the neighboring column and row offsets...
        c = bsxfun(@plus,j,[-1  0  1 -1  1 -1  0  1]);
        r = bsxfun(@plus,i,[-1 -1 -1  0  0  1  1  1]);

        % Filter the invalid positions...
        idx = (c > 0) & (c <= A_cols) & (r > 0) & (r <= A_rows);

        % Transform the valid positions into linear indices...
        idx = (((idx .* c) - 1) .* A_rows) + (idx .* r);
        idx = reshape(idx.',1,numel(idx));

        % Filter the invalid linear indices...
        idx = idx(idx > 0);

        % Find the center neighbors and their sum...
        neighbors = A(idx);
        neighbors_sum = sum(neighbors);

        % Apply the transformation criterions to A...
        if (value == 0)
            if (neighbors_sum == 3)
                A(i,j) = 1;
            end
        else
            if (neighbors_sum <= 1) || (neighbors_sum >= 3)
                A(i,j) = 0;
            end
        end
    end
end

给定示例的最终输出是:

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

我只是对你描述的整个过程有一些疑问。

第一个涉及当中心值等于1 时应用的标准。其中两个似乎是矛盾的:

-如果中心值的相邻单元格总共包含3个或更多1,则从1转换为0。

-如果相邻单元格总共包含 2 或 3 个数字 1,则保持为 1。

当邻居总和等于3... 应该应用哪个条件?第一个还是第二个?

第二个涉及原始矩阵A。它应该在循环内更新吗?我的意思是,在当前代码中,A 的值在满足某些条件时会发生变化……但这也意味着条件会受到先前迭代结果的影响。也许您的目标是保持 A 静态,同时更新它的克隆?

无论如何,这两个问题都很容易处理,您应该能够毫无问题地根据您的需要调整我的代码。

【讨论】:

  • 感谢您抽出宝贵时间来做这件事,这真的很有帮助。对不起,这是一个错字,第一个条件应该是 4 个或更多 1,而不是 3 个或更多,这就是为什么它看起来很矛盾。对于您的第二个问题,没有必要保持第一个静态,所以没问题:) 谢谢!!
  • 然后将第二个条件改为if (neighbors_sum &lt;= 1) || (neighbors_sum &gt;= 4)。不客气。
  • 很高兴它有帮助。如果您对我的解决方案感到满意,请将我的回答标记为已接受。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-06
  • 1970-01-01
  • 2022-11-16
  • 2019-04-09
  • 1970-01-01
相关资源
最近更新 更多