user1234
user1234

Reputation: 437

how to find neighours of a pixel and its co-ordinate

i need to find all the black neighbors of a pixel; for that i tried the following ;but the output is not correct.Cropped input image is enter image description here labeled image(i put color to this label) enter image description here i want to add the black region of the input image (region around ellipse like structure) and change the white region around ellipse in the labeled image as blue(need to change the label of surrounding white region as 1)

  clc
    clear all;close all
    img=[0   255 0 0 0;
         0   1   1 255 0;
         255 0   0 255 0;];
    [m n]=size(img)
    img= padarray(img, [2 2], 0)
    fi_neighbors=zeros(1,8);
    for i=1:m
        for j=1:n
    for r=3:m
        for c=3:n

           neighbors(1) = img(r-1,c-1); % Upper left.  
    neighbors(2) = img(r-1,c); % Upper middle.  
    neighbors(3) = img(r-1,c+1); % Upper right.  
    neighbors(4) = img(r,c-1); % left.  
    neighbors(5) = img(r,c+1); % right. 
    neighbors(6) = img(r+1,c+1); % Lowerleft.  
    neighbors(7) = img(r+1,c); % lower middle.  
    neighbors(8) = img(r+1,c-1); % Lower left.  
        end

    end
    fi_neighbors=[neighbors;fi_neighbors]
        end
    end

Upvotes: 0

Views: 619

Answers (1)

beaker
beaker

Reputation: 16791

There are several errors in your code, so I'll try to take them one by one. Here is your original code, reformatted a bit:

img = [0 0 0 0 0;
       0 1 1 0 0;
       0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [2 2], 0)
fi_neighbors = zeros(1,8);

for i = 1:m
   for j = 1:n
      for r = 3:m
         for c = 3:n
            neighbors(1) = img(r-1,c-1); % Upper left.  
            neighbors(2) = img(r-1,c);   % Upper middle.  
            neighbors(3) = img(r-1,c+1); % Upper right.  
            neighbors(4) = img(r,c-1);   % left.  
            neighbors(5) = img(r,c+1);   % right. 
            neighbors(6) = img(r+1,c+1); % Lower right.  <-- corrected
            neighbors(7) = img(r+1,c);   % lower middle.  
            neighbors(8) = img(r+1,c-1); % Lower left.  
         end
      end
      fi_neighbors = [neighbors;fi_neighbors]
   end
end

The first error is that the loop variables i and j are never used. Therefore they are useless (except for making us perform the same calculations m x n times). Let's take those out.

img = [0 0 0 0 0;
       0 1 1 0 0;
       0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [2 2], 0)
fi_neighbors = zeros(1,8);

for r = 3:m
   for c = 3:n
      neighbors(1) = img(r-1,c-1); % Upper left.  
      neighbors(2) = img(r-1,c);   % Upper middle.  
      neighbors(3) = img(r-1,c+1); % Upper right.  
      neighbors(4) = img(r,c-1);   % left.  
      neighbors(5) = img(r,c+1);   % right. 
      neighbors(6) = img(r+1,c+1); % Lower right.  
      neighbors(7) = img(r+1,c);   % lower middle.  
      neighbors(8) = img(r+1,c-1); % Lower left.              
   end
end
fi_neighbors = [neighbors;fi_neighbors]

With those loops out of the way, we can see that you're only updating the fi_neighbors array once after you've done all of the calculations. That's why you got the same result m x n times before. We need to move that inside the loop where the result is updated after each set of calculations (I've left out the setup this time and only listed the loops):

for r = 3:m
   for c = 3:n
      neighbors(1) = img(r-1,c-1); % Upper left.  
      neighbors(2) = img(r-1,c);   % Upper middle.  
      neighbors(3) = img(r-1,c+1); % Upper right.  
      neighbors(4) = img(r,c-1);   % left.  
      neighbors(5) = img(r,c+1);   % right. 
      neighbors(6) = img(r+1,c+1); % Lower right.  
      neighbors(7) = img(r+1,c);   % lower middle.  
      neighbors(8) = img(r+1,c-1); % Lower left.              
      fi_neighbors = [neighbors;fi_neighbors]   %// moved inside loops
   end
end

Next up are the ranges for our loops. You padded the array with 2 zeros on each side, so you start with row/column 3. That's good, but you still end the loops at m and n. That means you process (m-2) x (n-2) pixels. You need to extend the range. But actually, you've padded more than you need. A padding of one pixel on each side would be sufficient, so let's do both at once, change the padding and correct the ranges:

img = [0 0 0 0 0;
       0 1 1 0 0;
       0 0 0 0 0;];
[m n] = size(img)
img = padarray(img, [1 1], 0)
fi_neighbors = zeros(1,8);

for r = 2:m+1
   for c = 2:n+1
      neighbors(1) = img(r-1,c-1); % Upper left.  
      neighbors(2) = img(r-1,c);   % Upper middle.  
      neighbors(3) = img(r-1,c+1); % Upper right.  
      neighbors(4) = img(r,c-1);   % left.  
      neighbors(5) = img(r,c+1);   % right. 
      neighbors(6) = img(r+1,c+1); % Lower right.  
      neighbors(7) = img(r+1,c);   % lower middle.  
      neighbors(8) = img(r+1,c-1); % Lower left.              
      fi_neighbors = [neighbors;fi_neighbors]
   end
end

Now you should have a working program that gives you the correct output:

fi_neighbors =

   0   0   0   0   0   0   0   0   <-- img(m,n) neighbors
   1   0   0   0   0   0   0   0
   1   1   0   0   0   0   0   0
   0   1   1   0   0   0   0   0
   0   0   1   0   0   0   0   0
   0   0   0   0   0   0   0   0
   0   0   0   1   0   0   0   0
   0   0   0   1   0   0   0   0
   0   0   0   0   1   0   0   0
   0   0   0   0   1   0   0   0
   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   1
   0   0   0   0   0   0   1   1
   0   0   0   0   0   1   1   0
   0   0   0   0   0   1   0   0   <-- img(1,1) neighbors
   0   0   0   0   0   0   0   0

This works, but have a look at the notes that I added to the output. The first row of the result contains the neighbors for the pixel img(m,n): the last pixel in the image. The next-to-last row contains the neighbors for img(1,1), and the last row is just hanging there as a result of your initialization to zeros(1,8). All of that seems unnatural to me, so I'm going to flip the result array so that img(1,1) is the first row. Also, growing an array over each loop iteration is slow. We want to preallocate the array and then put the data in the proper place.

Since we're referencing pixels in the original image, but calculating on a padded image, it's much easier to add a counter variable than to do all of the row/column index calculations, so I've added pix as a counter:

img = [0 0 0 0 0;
       0 1 1 0 0;
       0 0 0 0 0;];
[m n] = size(img);
img = padarray(img, [1 1], 0)
fi_neighbors = zeros(m*n,8);   % preallocate result array

pix = 0;   % pixel counter
for r = 2:m+1
   for c = 2:n+1
      pix = pix + 1;   % find neighbors for next pixel
      neighbors(1) = img(r-1,c-1); % Upper left.  
      neighbors(2) = img(r-1,c);   % Upper middle.  
      neighbors(3) = img(r-1,c+1); % Upper right.  
      neighbors(4) = img(r,c-1);   % left.  
      neighbors(5) = img(r,c+1);   % right. 
      neighbors(6) = img(r+1,c+1); % Lower right.  
      neighbors(7) = img(r+1,c);   % lower middle.  
      neighbors(8) = img(r+1,c-1); % Lower left.
      fi_neighbors(pix,:) = neighbors;   % update the correct row
   end
end

Result:

fi_neighbors =

   0   0   0   0   0   1   0   0
   0   0   0   0   0   1   1   0
   0   0   0   0   0   0   1   1
   0   0   0   0   0   0   0   1
   0   0   0   0   0   0   0   0
   0   0   0   0   1   0   0   0
   0   0   0   0   1   0   0   0
   0   0   0   1   0   0   0   0
   0   0   0   1   0   0   0   0
   0   0   0   0   0   0   0   0
   0   0   1   0   0   0   0   0
   0   1   1   0   0   0   0   0
   1   1   0   0   0   0   0   0
   1   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0

Now, the neighbors of img(1,1) are in row 1 and the neighbors of img(m,n) are in row m*n.

Finally, there are a couple of quick optimizations you can make. Both of them require changes in the ordering of the result. If you're willing to have the pixels and neighbors presented in a different order, which I'll try to show clearly, then we can first change the ordering of the loops to take advantage of MATLAB's column-major ordering.

Instead of:

for r = 2:m+1
   for c = 2:n+1
      ...
   end
end

we'll use:

for c = 2:n+1    % be sure to swap m and n as well!
   for r = 2:m+1
      ...
   end
end

For large matrices, this should help with keeping the current columns we're working with in the cache. This will change the ordering of the pixels so that instead of the second pixel being img(1,2), it will now be img(2,1), then img(3,1), down to img(m,1), then img(1,2).

The second change condenses all of your neighbor calculations into 2 lines (maybe 3), but it changes the ordering as I'll show below:

pix = 0;   % pixel counter
for c = 2:n+1
   for r = 2:m+1
      pix = pix + 1;   % find neighbors for next pixel

      neighbors = img(r-1:r+1,c-1:c+1);
      neighbors = neighbors(:).';

      fi_neighbors(pix,:) = neighbors;   % update the correct row
   end
end

This takes the submatrix of img around the current pixel, then uses colon notation to turn it into a column vector and finally transposes it into a row vector. Here are the resulting neighbor locations within neighbors:

neighbors(1) % Upper left.
neighbors(2) % left.
neighbors(3) % Lower left.
neighbors(4) % Upper middle.
neighbors(5) % *** current pixel ***
neighbors(6) % Lower middle.
neighbors(7) % Upper right.
neighbors(8) % right.
neighbors(9) % Lower right.

But now we have 9 elements in neighbors including the current pixel! If you really don't want the current pixel listed, we can fix that, but either way we need to change the size of fi_neighbors to (m*n,9). We can then remove column 5 from the result at the end, if desired.

Here's the final code:

img = [0 0 0 0 0;
       0 1 1 0 0;
       0 0 0 0 0;];
[m n] = size(img);
img = padarray(img, [1 1], 0);
fi_neighbors = zeros(m*n,9);   % preallocate result array

pix = 0;   % pixel counter
for c = 2:n+1
   for r = 2:m+1
      pix = pix + 1;   % find neighbors for next pixel
      neighbors = img(r-1:r+1,c-1:c+1);
      neighbors = neighbors(:).';
      fi_neighbors(pix,:) = neighbors;   % update the correct row
   end
end

fi_neighbors(:,5) = []; % OPTIONAL - remove current pixel from each row

Obviously, there's more you could do, but this should be a very good start.

Upvotes: 2

Related Questions