How to write a function that finds the connected neighbors of a pixel

8 views (last 30 days)
How do I do this in addition to having a threshold applied to the image as well.
  2 Comments
Lucas Hernandez
Lucas Hernandez on 31 Mar 2021
Thanks. I think I phrased my question wrongly because I know this function. Is there a way to write a matlab code with it’s inputs, the coordinates of a pixel (x0 and y0), a grayscale image, img, and a gray level threshold, T, and returns two outputs, x and y, the coordinates of that pixel’s connected neighbours?

Sign in to comment.

Answers (1)

DGM
DGM on 31 Mar 2021
I'm not sure I understand the question correctly, but I'm going to assume that you don't want the whole connected group and that you just want the locations of a pixel's neighbors (if any). Assuming you do the thresholding part beforehand, this is one way:
poi=[10 10]; % this is the pixel of interest
connspec=4; % specify 4 or 8
% this all assumes that the image has already been thresholded
% or otherwise converted to a binary image.
if inpict(poi(1),poi(2))
% doing things this way keeps us from also returning the POI
if connspec==4
neighbors=logical([0 1 0; 1 0 1; 0 1 0]);
elseif connspec==8
neighbors=logical([1 1 1; 1 0 1; 1 1 1]);
end
neighbors=neighbors & logical(inpict(poi(1)+(-1:1),poi(2)+(-1:1)));
osx=[-1 0 1; -1 0 1; -1 0 1]; % index offsets
osy=osx';
x=poi(2)+osx(neighbors)
y=poi(1)+osy(neighbors)
else
% do whatever you want to do if the pixel is false
disp('this pixel isn''t part of a connected foreground group')
end
There are probably more concise ways, but this is what I threw together. Length of vectors x,y will be at most either 4 or 8, depending on connspec. Take it as a demonstration rather than anything finished for your purpose. You'd have to incorporate this into your other required tasks in a function.
  3 Comments
DGM
DGM on 2 Apr 2021
Edited: DGM on 2 Apr 2021
What you're describing sounds more like a 'magic wand' selection, though i don't really know how the example output image could have been obtained with such a simple thresholding operation with the given value. Extracting the local connected group can be demonstrated:
% i'm going to assume that this is uint8, 0-255
inpict=rgb2gray(imread('birds1.png'));
% the example is T=2, but i have no idea what that means
% i'm going to assume that means to select value at poi +-2%
tol=5;
% if it's supposed to be +-2/255, comment this line
tol=tol*2.55;
% i'm assuming this is [row col]
poi=[67 45];
% specify connectivity
connspec=8;
% get value of selected pixel
ipoi=inpict(poi(1),poi(2));
% do a basic box masking
tpict=(inpict>=(ipoi-tol)) & (inpict<=(ipoi+tol));
% get object list
[objects count]=bwlabel(tpict,connspec);
% find which object poi belongs in
selectedobj=objects(poi(1),poi(2));
% select that object only
outmask=(objects==selectedobj);
% view the result
imshow(cat(2,im2double(inpict),outmask))
Like I said, I don't know how they got that output with that threshold value. I'm assuming they're doing something different for the masking part. Maybe the example was done on a color image? Otherwise, the selected area isn't going to look the same.
You said that the output image is supposed to be grayscale, but the example isn't. I still don't really know if this is what you're asking for. Do you simply intend to apply the generated mask to the source image?
% did you want to apply the mask?
maskedpict=im2double(inpict).*outmask;
Of course, you said you wanted x and y coordinates. How do those relate to this output? If you need a coordinate list for the selected object for some other purpose, you can use find() on outmask. If you need to find its centroid or something, you can use regionprops.
DGM
DGM on 2 Apr 2021
Edited: DGM on 2 Apr 2021
For what it's worth, let's say you had wanted to do this in color:
You have a bit more options for generating the initial mask, and you can potentially be more selective.
inpict=im2double(imread('birdscolor.jpg'));
% let's assume that since we're doing this in color
% our tolerance can be a vector
% this isn't as useful in RGB, but could be extended to e.g. LCH
tol=[22 22 22]/100;
% i'm assuming this is [row col]
poi=[67 45];
% specify connectivity
connspec=8;
% what type of selection calculation do we want? (box/ellipsoid)
method='ellipsoid';
% get tuple of selected pixel
cpoi=inpict(poi(1),poi(2),:);
% generate mask
switch method
case 'box'
tpict=ones([size(inpict,1) size(inpict,2)]);
for c=1:size(inpict,3)
% do a basic range (box) masking
tpict=tpict & (abs(inpict(:,:,c)-cpoi(c))<=tol(c));
end
case 'ellipsoid'
tpict=zeros([size(inpict,1) size(inpict,2)]);
for c=1:size(inpict,3)
% do euclidean distance (ellipsoid) masking
tpict=tpict + ((inpict(:,:,c)-cpoi(c))/tol(c)).^2;
end
tpict=tpict<=1;
end
tpict=logical(tpict);
% this is all still the same
[objects count]=bwlabel(tpict,connspec);
selectedobj=objects(poi(1),poi(2));
outmask=(objects==selectedobj);

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!