How to find the positions of pixels with 4 neighborhood in a binary pixel grid

11 Ansichten (letzte 30 Tage)
Hi everybody, this is a homework problem I have for a computer science class, I think I'm on the right track with my code but I'm not sure if the syntax is entirely correct
I have:
for i=1:3
for j=1:3
i > 1
if image(i-1,j) > 0
if image(i,j)==1 && image(i-1,j)==1
image(i,j)=fourneighbors;
end
end
if image(i,j-1) > 0
if image(i,j)==1 && image(i,j-1)==1
image(i,j)=fourneighbors;
end
end
if image(i+1,j) > 0
if image(i,j)==1 && image(i+1,j)==1
image(i,j)=fourneighbors;
end
end
if image(i,j+1) > 0
if image(i,j)==1 && image(i,j+1)==1
image(i,j)=fourneighbors;
end
end
end
end
each if statement is supposed to check whether neighboring pixels share the same brightness value, and also whether the pixel exists since it is only a 3x3 grid.
  4 Kommentare
Umar
Umar am 19 Okt. 2024
Hi @DGM,
You brought up some good points such as to clarify whether @Harrison need to return true pixels based on patterns or counts of neighboring pixels. Depending on this requirement, @Harrison may need different approaches or data structures.
Harrison
Harrison am 19 Okt. 2024
Thank you so much for your response, I'll try to clarify a bit
It is a binary image
Handling edges is part of what I'm trying to figure out--basically I need the code to check if the pixel being observed actually exists first to avoid indexing errors.
The question is asking me to identify the locations of pixels that belong to a 4-neighborhood. it doesn't need to be a complete neighborhood--just as long as they share the same value. The exact wording of the question is "Identify the position of pixels with 4-neighborhood." I was a little confused by this myself.
I apologize for any lack of clarity, I am very new to all of this and my instructors don't give very clear instructions, let alone assitance if we ask them. Genuinely they ask us to do these tasks with no prior explanation of Matlab's syntax.

Melden Sie sich an, um zu kommentieren.

Antworten (2)

DGM
DGM am 19 Okt. 2024
Bearbeitet: DGM am 20 Okt. 2024
I wouldn't bother with conditionally checking for out-of-bounds indexes in the loop. Simply pad the array and process it. Letting your filter window "hang off the edge" of your array is simpler and faster for typical cases.
I'm assuming the text means "the position of true pixels with a full 4-neighborhood" -- i.e. the image locally looks like [x 1 x; 1 1 1; x 1 x], where we don't care about the values at x. This is basically morphological erosion.
Here are four ways to do that using the same simple filter. They're all equivalent, but they're the result of different ways of thinking about the task.
% test image
inpict = [0 0 1 0 0 0; ...
0 0 0 0 0 0; ...
0 0 1 1 0 0; ...
0 1 1 1 0 0; ...
0 0 1 0 1 1; ...
0 0 0 1 1 0];
% precalculate some things
% depending on what method we use, we might not need all these
% mask selecting 4-neighbors
se4 = [0 1 0; 1 0 1; 0 1 0]; % exclude self
se5 = [0 1 0; 1 1 1; 0 1 0]; % include self
seb = 2.^([1 4 7; 2 5 8; 3 6 9]-1); % weights
neighborhood = myfilter33(inpict,seb.*se5); % pattern identity
% return true for true pixels which have a full 4-nhood
% this does neighbor count matching as in the prior example
% using the image itself to select pixels we care about
A = myfilter33(inpict,se4).*inpict == 4
A = 6x6 logical array
0 0 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 0 0 0 0 0 0 0 0 0
% or you can combine both steps by using a different filter
B = myfilter33(inpict,se5) == 5
B = 6x6 logical array
0 0 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 0 0 0 0 0 0 0 0 0
% or you could do similar using the pattern matching concept
% if all we need is erosion, this is overcomplicated
C = neighborhood == sum(se5.*seb,1:2)
C = 6x6 logical array
0 0 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 0 0 0 0 0 0 0 0 0
% or you could think of this more like the morphological erosion that it is
D = ~myfilter33(~inpict,se5,1)
D = 6x6 logical array
0 0 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 0 0 0 0 0 0 0 0 0
% i made this take custom padding values just to point out that it matters
% note why it matters in the last example
function outpict = myfilter33(inpict,fk,padval)
% very simple filter function
%
% INPICT is a 2D array
% FK is a 3x3 filter kernel
% PADVAL (scalar) is used to pad the array (default 0)
%
% Output is class 'double'
% enforce default
if nargin<3
padval = 0;
end
sz = size(inpict,1:2);
% make sure we're in float class
inpict = im2double(inpict);
% pad the array with zeros so we don't have
% to check the edges conditionally every time
inpict = padarray(inpict,[1 1],padval,'both');
outpict = zeros(sz);
for row = 2:sz(1)+1
for col = 2:sz(2)+1
yy = row-1:row+1;
xx = col-1:col+1;
outpict(row-1,col-1) = sum(inpict(yy,xx).*fk,1:2);
end
end
end
Now this works for logical images, but if what we really want is to build a set of morphological filter tools (dilation, erosion, opening, closing, etc), then we should probably ask how far we want to go. While we can implement all of these by using convolution as above, the more general form (for both binary and grayscale) would be a nonlinear filter. We'd just have to change the core behavior of our filter to be a max() operation instead of a sum. That would implement a dilation filter, and all the others are derived from that.
Beware if you try to compare this to the behavior of imerode(), as the above example uses zero (false) padding, whereas imerode() does edge-replication. Why did I choose zero padding? Zero padding replicates what you were already trying to do with your conditional edge handling. It makes the behavior at the edges easier to understand.
Attached is an extra image. It's a tiling of all possible 3x3 neighborhood patterns. The tiling causes some pattern duplication, but the point is that all patterns are present. This makes it useful for comparing filter behavior.
"I apologize for any lack of clarity, I am very new to all of this and my instructors don't give very clear instructions, let alone assitance if we ask them. Genuinely they ask us to do these tasks with no prior explanation of Matlab's syntax."
Yeah. That seems to be a theme, especially for freshman and interdisciplinary sorts of courses. It's like everyone's just phoning it in.
  1 Kommentar
DGM
DGM am 19 Okt. 2024
Bearbeitet: DGM am 19 Okt. 2024
A logical-only simplification of the filter routine:
% test image
inpict = [0 0 1 0 0 0; ...
0 0 0 0 0 0; ...
0 0 1 1 0 0; ...
0 1 1 1 0 0; ...
0 0 1 0 1 1; ...
0 0 0 1 1 0];
se5 = [0 1 0; 1 1 1; 0 1 0]; % include self
outpict = myerode33(inpict,se5)
outpict = 6x6 logical array
0 0 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 0 0 0 0 0 0 0 0 0
function outpict = myerode33(inpict,se)
% very simple morphological erosion function using zero padding
%
% INPICT is a 2D logical array
% FK is a 3x3 logical array
%
% Output is class 'logical'
sz = size(inpict,1:2);
% make sure we're in float class
inpict = logical(inpict);
se = logical(se);
% pad the array with zeros so we don't have
% to check the edges conditionally every time
inpict = padarray(inpict,[1 1],false,'both');
% erosion is the complement of the dilation of the complement
% so complement the input ...
inpict = ~inpict;
outpict = zeros(sz);
for row = 2:sz(1)+1
for col = 2:sz(2)+1
yy = row-1:row+1;
xx = col-1:col+1;
sample = inpict(yy,xx);
outpict(row-1,col-1) = any(sample(se)); % ... dilation ...
end
end
% ... and complement the output
outpict = ~outpict;
end

Melden Sie sich an, um zu kommentieren.


Umar
Umar am 19 Okt. 2024

Hi @Harrison,

There are several issues that need to be addressed to ensure the code functions correctly. Below, I will outline the necessary corrections and provide a complete, updated version of the code.

Boundary Conditions: The code does not adequately handle boundary conditions, which can lead to indexing errors when accessing pixels outside the 3x3 grid.

Variable Initialization: The variable fourneighbors is used but not defined in the provided code. We need to ensure it is initialized properly.

Logical Structure: The nested if statements can be simplified for better readability and efficiency.

Here is the revised version of your MATLAB code, which includes boundary checks and proper initialization of variables:

% Initialize a sample 3x3 image matrix
image = [1 0 1; 
       1 1 1; 
       0 1 0];
% Initialize the value to assign to neighboring pixels
fourneighbors = 2; % Example value to represent neighboring pixels
% Loop through the 3x3 grid
for i = 1:3
  for j = 1:3
      % Check the upper neighbor
      if i > 1 && image(i-1,j) == 1 && image(i,j) == 1
          image(i,j) = fourneighbors;    
      end
        % Check the left neighbor
        if j > 1 && image(i,j-1) == 1 && image(i,j) == 1
            image(i,j) = fourneighbors;
        end
        % Check the lower neighbor
        if i < 3 && image(i+1,j) == 1 && image(i,j) == 1 
            image(i,j) = fourneighbors;
        end
        % Check the right neighbor
        if j < 3 && image(i,j+1) == 1 && image(i,j) == 1
            image(i,j) = fourneighbors;
        end
    end
  end
% Display the final image matrix
disp('Updated Image Matrix:');
disp(image);

Please see attached.

So, in the above code snippet,image matrix is initialized with sample values. The variable fourneighbors is set to 2, which will be used to mark pixels that have neighboring pixels with the same brightness. The outer loop iterates over the rows, while the inner loop iterates over the columns of the 3x3 grid. Each if statement includes conditions to ensure that the code does not attempt to access indices outside the bounds of the matrix. For example, if i > 1 checks that the upper neighbor exists, and if j < 3 checks that the right neighbor exists. If the current pixel and its neighbor share the same brightness value (both equal to 1), the current pixel is updated to the value of fourneighbors. Finally, the updated image matrix is displayed using disp.

This updated code should now function correctly, checking neighboring pixels in the 3x3 grid while avoiding any indexing errors. You can modify the image matrix to test different scenarios.

Hope this helps.

If you have any further questions or need additional modifications, feel free to ask!

  4 Kommentare
Harrison
Harrison am 20 Okt. 2024
Thank you so much, I actually ended up doing it with fprintf before you responded but this is good information to know.
You and everyone else who responded have seriously been so helpful--I mentioned it in another comment but the instructors for this class have been absolutely no help. They literally showed us how to download the app, did a very rough overview of the basic procedure with pseudocode and expect us to know the exact syntax to implement it in matlab.
Gripes about my professors aside, again thank you so much for all of your help. <3
Umar
Umar am 20 Okt. 2024
Hi @ Harrison,
Glad to know your problem is resolved. Please don’t forget to click “Accept Answer” and vote for @DGM for his efforts. If you still have any further questions, please don’t hesitate to ask.

Melden Sie sich an, um zu kommentieren.

Produkte


Version

R2024b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by