# How to trace the boundray of object in an image using MATLAB?

17 views (last 30 days)
Tayyaba Bano on 26 Nov 2020
Commented: Image Analyst on 18 Dec 2020
Hi,
I want to trace the boundary of an object in an image.(the bended black part)
I am attaching the binarised image herewith.
My questions are:
when I use dim= size(I) inin the following code, it gives different size and when I type in dim = size(BW), it gives different pixel size, so which should I follow?
imshow(I);
dim = size(I)
secondly how can I define the row and coloumn using this size information in order to continue with bwtraceboundary , because when i use this command it gives me a following error:
Error using bwtraceboundary
Expected input number 1, BW, to be two-dimensional.
waiting for a kind response.
Regards
Tayyaba

KALYAN ACHARJYA on 26 Nov 2020
"I want to trace the boundary of an object in an image.(the bended black part)"
Which image? Can you attach it (Please use clip button)
Tayyaba Bano on 26 Nov 2020
Thanks.
I hope its attached now.

KALYAN ACHARJYA on 26 Nov 2020
se=strel('disk',2);
im=imerode(~binary_image,se);
result=bwareafilt(im,1);
result=imdilate(result,se);
imshow(result);

Tayyaba Bano on 27 Nov 2020
Thanks :)
KALYAN ACHARJYA on 27 Nov 2020
To get the indices of boundary, apply hit and miss transformation, the
[r,c]=find(resultant_image==1)

Image Analyst on 26 Nov 2020
If you want to manually trace some boundary. Use drawfreehand().
If you have a binary image and you want an image of the perimeter only, then use bwperim().
perimImage = bwperim(binaryImage);
imshow(perimImage);
If you have a binary image and you want a list of the (x,y) coordinates, use bwboundaries().
boundaries = bwboundaries(binaryImage);
hold on; % Don't let boundaries blow away the image.
for k = 1 : length(boundaries)
thisBoundary = boundaries{k};
x = thisBoundary(:, 2);
y = thisBoundary(:, 1);
plot(x, y, 'LineWidth', 2);
end
hold off;

Tayyaba Bano on 27 Nov 2020
Yes I actually need the (x,y) coordinates of the boundary in the binary image.
I tried this command already but it states the following error:
Error using bwboundaries
Expected input number 1, BW, to be two-dimensional.
Error in bwboundaries>parseInputs (line 187)
validateattributes(BW_in, {'numeric','logical'}, {'real','2d','nonsparse'}, ...
Error in bwboundaries (line 140)
[BW, conn, findHoles] = parseInputs(args{:});
Error in Untitled3 (line 4)
boundaries = bwboundaries(BW);
Alltough the image is two-dimensional, still it displays this error.
Thanks much.
Tayyaba
Image Analyst on 27 Nov 2020
You passed in your color image. You need to use the binary image, after it's been converted to gray scale and segmented.

Image Analyst on 27 Nov 2020
Try this:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 22;
%--------------------------------------------------------------------------------------------------------
folder = pwd;
baseFileName = 'image.jpeg';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
% Get the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(grayImage);
if numberOfColorChannels > 1
% It's not really gray scale like we expected - it's color.
% Use weighted sum of ALL channels to create a gray scale image.
grayImage = rgb2gray(grayImage);
% ALTERNATE METHOD: Convert it to gray scale by taking only the green channel,
% which in a typical snapshot will be the least noisy channel.
% grayImage = grayImage(:, :, 2); % Take green channel.
end
% Display the image.
subplot(2, 3, 1);
imshow(grayImage, []);
title('Original Grayscale Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
hFig = gcf;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
% The image has a huge white frame around it. Let's crop that away.
verticalProfile = all(grayImage == 255, 2);
row1 = find(~verticalProfile, 1, 'first');
row2 = find(~verticalProfile, 1, 'last');
horizontalProfile = all(grayImage == 255, 1);
col1 = find(~horizontalProfile, 1, 'first');
col2 = find(~horizontalProfile, 1, 'last');
% Do the crop
grayImage = grayImage(row1:row2, col1:col2);
% Display the image.
subplot(2, 3, 2);
imshow(grayImage, []);
axis('on', 'image');
title('Cropped Grayscale Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
% Update size.
[rows, columns, numberOfColorChannels] = size(grayImage);
% Display histogram
subplot(2, 3, 3);
imhist(grayImage);
grid on;
title('Histogram of gray image', 'FontSize', fontSize);
%--------------------------------------------------------------------------------------------------------
% SEGMENTATION OF IMAGE
% Get a binary image
mask = grayImage < 25; %imbinarize(grayImage);
subplot(2, 3, 4);
impixelinfo;
title('Initial Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
% Make a circle mask to get rid of corners
% Create a logical image of a circle with specified
% diameter, center, and image size.
% First create the image.
imageSizeX = columns;
imageSizeY = rows;
[columnsInImage, rowsInImage] = meshgrid(1:imageSizeX, 1:imageSizeY);
% Next create the circle in the image.
centerX = columns/2;
centerY = rows/2;
circlePixels = (rowsInImage - centerY).^2 ...
+ (columnsInImage - centerX).^2 <= radius.^2;
% circlePixels is a 2D "logical" array.
% Now, display it.
% imshow(circlePixels) ;
% title('Binary image of a circle');
% Erase the corners
% Do an opening to break the stick away from the background things.
se = strel('disk', 2, 0);
% Take the biggest blob.
% Fill holes
% Blur it a bit to smooth it out.
windowSize = 17;
kernel = ones(windowSize, windowSize) / windowSize ^ 2;
subplot(2, 3, 5);
impixelinfo;
title('Final Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
% Get boundaries and plot them, just for fun.
subplot(2, 3, 6);
imshow(grayImage); % Show cropped image again.
hold on;
for k = 1 : length(boundaries)
thisBoundary = boundaries{k};
x = thisBoundary(:, 2);
y = thisBoundary(:, 1);
plot(x, y, 'r-', 'LineWidth', 2);
end
title('Image With Boundaries', 'FontSize', fontSize, 'Interpreter', 'None');

Image Analyst on 15 Dec 2020
401 is not the original image - it has a huge white frame around it. I'd try adjusting the threshold. You could also try morphological operations like imopen() to see if you can cut off some of the bright background that intrudes into the shape and gives it a ragged boundary. Perhaps the image capture conditions could also be improved, like change the exposure, lighting geometry, use polarizers, optical filters, or other such "tricks".
A bit more complicated, you could try deep learning with SegNet:
Tayyaba Bano on 18 Dec 2020
Actually I have to apply the code for number of images. Initially it worked well but for 401 and some others it doesnot show the compelete boundary.
Any how I am trying further to improve it.
Regards
Tayyaba
Image Analyst on 18 Dec 2020
Can you increase your exposure time to get a less noisy photo?
Maybe try some denoising routines, of which there are many. Maybe imnlmfit().