how to get part of the object contour ?

I'm working to classify objects as human or non-human. My research focuses on the shape detection. I tried to use the function edge in MATLAB but I do not know how to find the boundary edge for the head, neck and shoulders only for a human object from an image. In another words I want to ignore the internal edges; I just want the boundary edge. Can anyone help me in this? i want to get this part of the object and it is coordinates ?

 Accepted Answer

Will this work for you?
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
%===============================================================================
% Read in demo image.
folder = pwd;
baseFileName = 'Being-Human.jpg';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
% Didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
rgbImage = imread(fullFileName);
% 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(rgbImage);
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(rgbImage);
% 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.
else
grayImage = rgbImage; % It's already gray.
end
% Display the original color image.
subplot(2, 2, 1);
imshow(grayImage);
axis on;
title('Original Color Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'Outerposition', [0, 0, 1, 1]);
% Let's compute and display the histogram.
[pixelCount, grayLevels] = imhist(grayImage);
subplot(2, 2, 2);
% The white bin is so huge that it suppresses the other bins, so set it to the nex highest
pixelCount(end) = pixelCount(end-1);
bar(grayLevels, pixelCount, 'BarWidth', 1); % Plot it as a bar chart.
grid on;
title('Histogram of gray scale image', 'FontSize', fontSize, 'Interpreter', 'None');
xlabel('Gray Level', 'FontSize', fontSize);
ylabel('Pixel Count', 'FontSize', fontSize);
xlim([0 grayLevels(end)]); % Scale x axis manually.
% Threshold the image.
thresholdValue = 230;
binaryImage = grayImage < thresholdValue;
% Draw line on histogram at the threshold value.
line([thresholdValue, thresholdValue], ylim, 'Color', 'r', 'LineWidth', 2);
% Fill holes
binaryImage = imfill(binaryImage, 'holes');
% Display the mask image.
subplot(2, 2, 3);
imshow(binaryImage);
axis on;
title('Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Find the topmost pixel in the mask
topRows = rows * ones(1, columns);
for col = 1 : columns
thisTopRow = find(binaryImage(:, col), 1, 'first');
if ~isempty(thisTopRow)
topRows(col) = thisTopRow;
end
end
% Display the top rows.
subplot(2, 2, 4);
imshow(rgbImage);
hold on;
plot(1:columns, topRows, 'b-', 'LineWidth', 2);
axis on;
title('Color Image with Top Rows', 'FontSize', fontSize, 'Interpreter', 'None');

6 Comments

thank you , i will try it, hope it is helpful
hi , thank you very much ,it is ok , but i want to ask you 1- how i can get the coordinates of the blue line in the fourth image? 2- is there any way to make the blue line just for the upper part not for all body? thank you for help
also why it not work on all type of images?
If you want to not include the columns where the top row is the last row of the image, just extract out elements where top row is not equal to the total number of rows:
colsToExtract = topRows ~= rows;
topRows = topRows(colsToExtract);
The code depends on there being a white background behind a human. Of course if you have a ninja on a black background, it's not designed to work with an image like that. If your images are so variable that there would have to be hundreds of special purpose algorithms for all kinds of weird cases, then you should just use imfreehand() to have the user hand tract the curve. I attach a demo for that.
Please I have a figure, I want to display all parts of the contour. What can I do?
@Shreen El-Sapa, your question does not seem to be related to @malek al-nawashi's post. Please start your own question.

Sign in to comment.

More Answers (2)

Hard to tell without the original image with tons of edges in it. It looks like you just uploaded the final image with one or two edges. What if there were other edges in there but below that curve, but were still accessible coming from underneath? What defines "outer" to you? Anyway, you might use the new boundary() function. Please upgrade your old version of MATLAB, unless you want to write that functionality in all by yourself.

2 Comments

hi, thank you for help
i want to read any image from dataset ,suppose the image is as this image
i want to write a MATLAB Function to give me the srounded edge of the head ,nick,and shoulders such as
and then the X coordinates of this edge
thank you for help
This will do it:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clearvars;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
fprintf('Beginning to run %s.m ...\n', mfilename);
%-----------------------------------------------------------------------------------------------------------------------------------
% Read in image.
folder = pwd;
baseFileName = 'image.jpeg';
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
rgbImage = imread(fullFileName);
[rows, columns, numberOfColorChannels] = size(rgbImage);
% Display the RGB image full size.
subplot(2, 2, 1);
imshow(rgbImage, []);
axis('on', 'image');
caption = sprintf('Original Image : "%s"', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Set up figure properties:
% Enlarge figure to full screen.
hFig1 = gcf;
hFig1.Units = 'Normalized';
hFig1.WindowState = 'maximized';
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
hFig1.Name = 'Demo by Image Analyst';
% Do color segmentation to get the mask.
hsvImage = rgb2hsv(rgbImage);
% Threshold the saturation image at 0.2
mask = hsvImage(:, :, 2) > 0.2;
% Fill holes
mask = imfill(mask, 'holes');
% Take the largest blob only.
mask = bwareafilt(mask, 1);
% Display the binary image.
subplot(2, 2, 2);
imshow(mask, []);
axis('on', 'image');
caption = sprintf('Mask Image');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Get the boundaries of the mask
maskBoundary = bwboundaries(mask);
maskBoundary = maskBoundary{1}; % Extract from cell. Is in (row, column) format, not (x, y).
% Get x and y for the boundary
x = maskBoundary(:, 2);
y = maskBoundary(:, 1);
% Make an all white image
whiteImage = 255 * ones(rows, columns, 3, 'uint8');
% Display the RGB image full size.
subplot(2, 2, 3);
imshow(whiteImage, []);
hold on;
plot(x, y, 'b-', 'LineWidth', 3);
axis('on', 'image');
caption = sprintf('Initial Boundary');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% It's hard to see single pixels because they get subsampled away during display,
% so let's use plot to plot a really thick line over it.
% Display the RGB image full size.
subplot(2, 2, 4);
imshow(whiteImage, []);
hold on;
caption = sprintf('Head and Shoulders');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% We only want the head and shoulders, so let's assume that the shoulders are 170 pixels below the top of the head.
shoulderLine = min(y) + 170;
yline(shoulderLine, 'Color', 'r', 'LineWidth', 2);
% Extract only the coordinates with y less than shoulderLine
indexes = y < shoulderLine;
xhs = x(indexes);
yhs = y(indexes);
plot(xhs, yhs, 'b-', 'LineWidth', 3);

Sign in to comment.

5 Comments

@malek al-nawashi Did you find the ans of your Question?
I posted an answer here: In a comment above.
Obviously it works only for the particular super-simple image he posted.
Hello guys, is there any way to take full human body (should be obese) from a very noise back ground to take the body joint contour and calculate the body width? Where should i start? Thank youu.
i would like to say thank you a lot xD

Sign in to comment.

Categories

Find more on Convert Image Type in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!