How to compare a matrix element with its neighbours without using a loop in MATLAB?

前端 未结 3 1686
天涯浪人
天涯浪人 2021-02-20 09:06

I have a matrix in MATLAB. I want to check the 4-connected neighbours (left, right, top, bottom) for every element. If the current element is less than any of the neighbours the

相关标签:
3条回答
  • 2021-02-20 09:21

    If you have the image processing toolbox, you can do this with a morpological dilation to find local maxima and suppress all other elements.

    array = magic(6); %# make some data
    
    msk = [0 1 0;1 0 1;0 1 0]; %# make a 4-neighbour mask
    
    %# dilation will replace the center pixel with the 
    %# maximum of its neighbors
    maxNeighbour = imdilate(array,msk);
    
    %# set pix to zero if less than neighbors
    array(array<maxNeighbour) = 0;
    
    array =
        35     0     0    26     0     0
         0    32     0     0     0    25
        31     0     0     0    27     0
         0     0     0     0     0     0
        30     0    34     0     0    16
         0    36     0     0    18     0
    

    edited to use the same data as @gnovice, and to fix the code

    0 讨论(0)
  • 2021-02-20 09:27

    If you don't have access to the Image Processing Toolbox, another way to accomplish this is by constructing four matrices representing the top, right, bottom and left first differences for each point and then searching for corresponding elements in all four matrices that are non-negative (i.e. the element exceeds all of its neighbours).

    Here's the idea broken down...

    Generate some test data:

    >> sizeA = 3;
    A = randi(255, sizeA)
    
    A =
    
       254   131    94
       135    10   124
       105   191    84
    

    Pad the borders with zero-elements:

    >> A2 = zeros(sizeA+2) * -Inf;
    A2(2:end-1,2:end-1) = A
    
    A2 =
    
         0     0     0     0     0
         0   254   131    94     0
         0   135    10   124     0
         0   105   191    84     0
         0     0     0     0     0
    

    Construct the four first-difference matrices:

    >> leftDiff = A2(2:end-1,2:end-1) - A2(2:end-1,1:end-2)
    
    leftDiff =
    
       254  -123   -37
       135  -125   114
       105    86  -107
    
    >> topDiff = A2(2:end-1,2:end-1) - A2(1:end-2,2:end-1)
    
    topDiff =
    
       254   131    94
      -119  -121    30
       -30   181   -40
    
    >> rightDiff = A2(2:end-1,2:end-1) - A2(2:end-1,3:end)
    
    rightDiff =
    
       123    37    94
       125  -114   124
       -86   107    84
    
    >> bottomDiff = A2(2:end-1,2:end-1) - A2(3:end,2:end-1)
    
    bottomDiff =
    
       119   121   -30
        30  -181    40
       105   191    84
    

    Find the elements that exceed all of the neighbours:

    indexKeep = find(leftDiff >= 0 & topDiff >= 0 & rightDiff >= 0 & bottomDiff >= 0)
    

    Create the resulting matrix:

    >> B = zeros(sizeA);
    B(indexKeep) = A(indexKeep)
    
    B =
    
       254     0     0
         0     0   124
         0   191     0
    

    After wrapping this all into a function and testing it on 1000 random 100x100 matrices, the algorithm appears to be quite fast:

    >> tic;
    for ii = 1:1000
    A = randi(255, 100);
    B = test(A);
    end; toc
    Elapsed time is 0.861121 seconds.
    
    0 讨论(0)
  • 2021-02-20 09:37

    One way to do this is with the function NLFILTER from the Image Processing Toolbox, which applies a given function to each M-by-N block of a matrix:

    >> A = magic(6)  %# A sample matrix
    
    A =
    
        35     1     6    26    19    24
         3    32     7    21    23    25
        31     9     2    22    27    20
         8    28    33    17    10    15
        30     5    34    12    14    16
         4    36    29    13    18    11
    
    >> B = nlfilter(A,[3 3],@(b) b(5)*all(b(5) >= b([2 4 6 8])))
    
    B =
    
        35     0     0    26     0     0
         0    32     0     0     0    25
        31     0     0     0    27     0
         0     0     0     0     0     0
        30     0    34     0     0    16
         0    36     0     0    18     0
    

    The above code defines an anonymous function which uses linear indexing to get the center element of a 3-by-3 submatrix b(5) and compare it to its 4-connected neighbors b([2 4 6 8]). The value in the center element is multiplied by the logical result returned by the function ALL, which is 1 when the center element is larger than all of its nearest neighbors and 0 otherwise.

    0 讨论(0)
提交回复
热议问题