简体   繁体   English

在矩阵Matlab中检查邻居值

[英]Check neighbor values in a matrix, Matlab

my problem is: I have to make a code that takes a matrix 6x6 of 0's and 1's and check certain conditions in each position of the matrix to iterate through it, and create a matrix with the new values based on the conditions, that are based in the neighbor elements of the center value. 我的问题是:我必须编写一个代码,该代码采用0和1的矩阵6x6,并检查矩阵的每个位置中的某些条件以对其进行迭代,然后根据条件创建具有新值的矩阵,该新值基于在中心值的相邻元素中。 The conditions are the following: 条件如下:

if the center value is 1 it has 3 options: 如果中心值为1,则有3个选项:

-If in the neighbor cells there is only one cell containing a number 1, or cero cells containing a number 1 the center value converts from 1 to 0. -如果在相邻的单元格中只有一个包含数字1的单元格,或者包含数字1的Cero单元格,则中心值将从1转换为0。

-If the neighbor cells of the center value contains in total 4 or more 1's, it converts from 1 to 0. -如果中心值的相邻单元格总共包含4个或更多1,则它将从1转换为0。

-And if the neighbor cells contain in total 2 or 3 number 1's, it keeps being 1. -并且,如果相邻单元格总共包含2个或3个1,则保持为1。

Now, if the center value is 0, it has 1 option: 现在,如果中心值为0,则有1个选项:

-If the neighbor cells contain 3 1's in total (tops), it converts from 0 to 1. -如果相邻单元格总共包含3个1(顶部),则它将从0转换为1。

-Else, it keeps being 0 -否则,它一直为0

The matrix is the following: 矩阵如下:

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]

So for example , the number 1 in the position A(5,2) should become 0, because it has 4 1's surrounding it, and another example, the zero in A(4,6) should become 1, because it has 3 1's surrounding it. 因此,例如 ,位置A(5,2)上的数字1应该变成0,因为它周围有4 1,而另一个示例,位置A(4,6)上的零应该变成1,因为它有3 1围绕它。

I made 2 loops using 1 for the rows and another for the columns to iterate through each value of the matrix, but in the conditional I don't know how to check the values of the surrounding cells or neighbor cells 我做了2个循环,其中1个用于行,另一个用于列,以遍历矩阵的每个值,但是在条件下,我不知道如何检查周围单元格或相邻单元格的值

I'm new to Matlab, if you can help me it would be great! 我是Matlab的新手,如果您能帮助我,那就太好了! Thanks. 谢谢。

Edit: added code the code I've made until now. 编辑:添加了代码,直到现在为止我所做的代码。

[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 tried to set the conditions to the (i-1,j-1),(i+1,j+1),(i+1,j),(i,j+1),(i-1,j),(i,j-1) but I think that will not work because I'm checking coditions as a group not counting the total numbers of 1 in the neighbors 我试图将条件设置为(i-1,j-1),(i + 1,j + 1),(i + 1,j),(i,j + 1),(i-1,j ),(i,j-1),但我认为这将不起作用,因为我将分类作为一个组进行检查而不计算邻居中1的总数

Edit 2: been thinking how to solve it and I thought that I could make a variable that counts the quantity of 1's in the surroundings of the center value, but it gives me an error that it exceeds the dimensions of the matrix in line 50, even after I made considerations for the first column, row and last column, row. 编辑2:一直在思考如何解决这个问题,我认为我可以做一个变量来计算中心值周围1的数量,但是它给我一个错误,它超出了第50行中矩阵的尺寸,即使我考虑了第一列,行和最后一列,行。

This is the complete code: 这是完整的代码:

[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

Nested loops is a sensible option. 嵌套循环是一个明智的选择。 However, what you are doing is basically an image filter, something that is already implemented by the function imfilter, so Why not to take advantage of that and simplify your life? 但是,您所做的基本上是一个图像过滤器,它已经由功能过滤器实现,所以为什么不利用它来简化您的生活呢? What you want to do can be accomplished with: 您可以通过以下方法完成您想做的事情:

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

Otherwise, if you want to keep the nested loops, instead of dealing with the exceptions of index out of bounds, I would suggest to pad A with zeros all around. 否则,如果您想保留嵌套循环,而不是超出范围之外处理索引异常,则建议在A周围使用零填充。 So if A size is n by m (6 by 6 in this case) you do: 因此,如果A大小为n×m(在这种情况下为6×6),则可以执行以下操作:

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

And then you loop i and j between 2:n+1 and 2:m+1 然后将i和j循环在2:n + 1和2:m + 1之间

In my opinion, using two nested loops in this case is a good approach. 我认为在这种情况下使用两个嵌套循环是一个好方法。 Retrieving the surrounding values of a matrix element is always tricky, but it can be accomplished with some efforts. 检索矩阵元素的周围值总是很棘手,但是可以通过一些努力来实现。 Here is the solution I propose you: 这是我为您建议的解决方案:

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

The final output for the given example is: 给定示例的最终输出是:

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

I just have a few doubts about the whole process you described. 我对您描述的整个过程只有几个疑问。

The first one concerns the criterions to apply when the center value is equal to 1 . 第一个涉及中心值等于1时要应用的标准。 Two of them seem to be contradictory: 其中两个似乎是矛盾的:

-If the neighbor cells of the center value contains in total 3 or more 1's, it converts from 1 to 0. -如果中心值的相邻单元格总共包含3个或更多1,则它将从1转换为0。

-And if the neighbor cells contain in total 2 or 3 number 1's, it keeps being 1. -并且,如果相邻单元格总共包含2个或3个1,则保持为1。

When the neighbors sum is equal to 3 ... which condition should be applied? 当邻居的和等于3 ...应采用哪种条件? The first one or the second one? 第一个还是第二个?

The second one concerns the original matrix A . 第二个问题涉及原始矩阵A Should it be updated inside the loop? 是否应该在循环内更新? I mean, in the current code, the values of A change when certain conditions are met... but this also means that the conditions are influenced by the outcome of the previous iterations. 我的意思是,在当前代码中,当满足某些条件时, A的值会发生变化……但这也意味着条件受先前迭代结果的影响。 Maybe your goal is to keep A static while updating a clone of it instead? 也许您的目标是在更新其副本的同时保持A静态?

Anyway, both issues are easy to deal with and you should be able to adapt my code to your needs without any problem. 无论如何,这两个问题都很容易处理,您应该能够毫无问题地适应我的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM