Ayesha Khan
Ayesha Khan

Reputation: 155

Matrix in matlab?

I am working on Connected Components labeling, and my matrix is:

 1     1     0     2     2     2     0     3
 1     1     0     2     0     2     0     3
 1     1     1     1     0     0     0     3
 0     0     0     0     0     0     0     3
 4     4     4     4     0     5     0     3
 0     0     0     4     0     5     0     3
 6     6     0     4     0     0     0     3
 6     6     0     4     0     7     7     7

and now, i want to do the second scan over it, for this i have made following code:

for i=1:1:r
    for j=1:1:c
        if (bw(i,j)>=1) 

            if (i-1>0 & i+1<=r) 
                % if ( bw(i,j)~= bw(i-1,j) | bw(i,j)~= bw(i+1,j))
                if ( (bw(i,j)~= bw(i-1,j) & bw(i-1,j)>0))
                    bw(i,j)= min (bw(i-1,j),bw(i,j))
                elseif ((bw(i,j)~= bw(i+1,j) & bw(i+1,j)>0))
                    bw(i,j) = min(bw(i+1,j),bw(i,j));
                end
            end

            if (j-1>0 & j+1<=c) 
                if ( (bw(i,j)~= bw(i,j-1) & bw(i,j-1)>0))
                    bw(i,j) = min (bw(i,j-1),bw(i,j));
                elseif((bw(i,j)~= bw(i,j+1) & bw(i,j+1)>0))
                    bw(i,j) = min (bw(i,j+1),bw(i,j))  ; 
                end
            end

        end
    end
end
disp(bw);

but the problem is, when i run this code, i get the following output

 1     1     0     2     2     2     0     3
 1     1     0     1     0     2     0     3
 1     1     1     1     0     0     0     3
 0     0     0     0     0     0     0     3
 4     4     4     4     0     5     0     3
 0     0     0     4     0     5     0     3
 6     6     0     4     0     0     0     3
 6     6     0     4     0     7     7     7

only one value changes (2nd row, 4 col) in my result, whereas, I want:

     1     1     0     1     1     1     0     3
     1     1     0     1     0     1     0     3
     1     1     1     1     0     0     0     3
     0     0     0     0     0     0     0     3
     4     4     4     4     0     5     0     3
     0     0     0     4     0     5     0     3
     6     6     0     4     0     0     0     3
     6     6     0     4     0     3     3     3

could somebody please help? where am i making a mistake?

Upvotes: 1

Views: 343

Answers (2)

Vidar
Vidar

Reputation: 4221

Nice solution by Jonas. As I was a bit into coding when I saw it added, I thought I'd show you my solution as well. Hopefully it is a bit more similar to your original code.

One of the mistakes you made was assuming this connection could be done in just one pass. Generaly it can not, as detections of some of the "snake elements" are dependent on the way you iterate throught the matrix. Becuase of this, I added an outer while loop.

 bw =[  1     1     0     2     2     2     0     3;
        1     1     0     2     0     2     0     3;
        1     1     1     1     0     0     0     3;
        0     0     0     0     0     0     0     3;
        4     4     4     4     0     5     0     3;
        0     0     0     4     0     5     0     3;
        6     6     0     4     0     0     0     3;
        6     6     0     4     0     7     7     7 ];


 %Set up matrix   
 [r,c] = size(bw);   

 %Zero pad border
 bwZ = [zeros(1,c+2);[zeros(r,1) bw zeros(r,1)];zeros(1,c+2)];

 %Iterate over all elements within zero padded border
 done=0;%Done flag 
 cc=1;  %Infinite loop protection
 while not(done) && cc<r*c
     done=1;cc=cc+1;
     for i=2:r+1
         for j=2:c+1
            %Point should be evaluated
            p = bwZ(i,j);
            if p >= 1
                %Pick out elements around active elements
                if bwZ(i-1,j)==0;ue=inf;else ue = bwZ(i-1,j); end;%Up element
                if bwZ(i+1,j)==0;de=inf;else de = bwZ(i+1,j); end;%Down element
                if bwZ(i,j-1)==0;le=inf;else le = bwZ(i,j-1); end;%Left element
                if bwZ(i,j+1)==0;re=inf;else re = bwZ(i,j+1); end;%Right element

                bwZ(i,j) = min([ue de le re]);
                %Set flag, if something has changed 
               if bwZ(i,j) ~= p
                    done = 0;
               end
            end
         end
     end
 end

 %Remove zero padding
 bw = bwZ(2:end-1,2:end-1)

Output:

bw =

 1     1     0     1     1     1     0     3
 1     1     0     1     0     1     0     3
 1     1     1     1     0     0     0     3
 0     0     0     0     0     0     0     3
 4     4     4     4     0     5     0     3
 0     0     0     4     0     5     0     3
 6     6     0     4     0     0     0     3
 6     6     0     4     0     3     3     3

Upvotes: 2

Jonas
Jonas

Reputation: 74940

If the numbers don't need to be preserved, you can simply call bwlabel on your original image:

newImage = bwlabel(originalImage>0);

EDIT

Here's another version. It checks each connected component to see whether there's another connected component touching it. If yes, that connected component is relabelled.

%# nCC: number of connected components
nCC = max(originalImage(:));

for cc = 1:nCC
%# check whether the component exists
myCC = originalImage==cc;
if any(any(myCC))

   %# create a mask to check for neighbors
   %# by creating a border of 1 pixel
   %# around the original label
   msk = imdilate(myCC,true(3)) & ~myCC;

   %# read all the pixel values under the mask
   neighbours = originalImage(msk);

   %# we're not interested in zeros, remove them
   neighbours = neighbours(neighbours > 0);

   if ~isempty(neighbours)
   %# set the label of all neighbours to cc
   originalImage( ismember(originalImage,neighbours) ) = cc;
   end
end
end

Upvotes: 2

Related Questions