Centroid Contour for a Binary Image Containing Multiple Objects

9 views (last 30 days)
I have the following image:
which I convert into a binary image. The centroid and boundary of each object has been defined so now I would like to determine the centroid contour (as a function of angle) for each object. I have seen some tutorials for which this is done on a single blob, but I am not quite sure how I can apply this to multiple objects.
This is what I have so far:
% Read in demo image
originalImage = imread('…pseudocubic3x.jpg');
grayImage = rgb2gray(originalImage);
subplot(3, 3, 1); imshow(originalImage);
subplot(3, 3, 2); imshow(grayImage);
% Logical Operation Approach.
thresholdValue = 200;
% binaryImage = grayImage > thresholdValue; % Bright objects will be the chosen if you use >, SEM Images.
binaryImage = grayImage < thresholdValue; % Dark objects will be the chosen if you use <, TEM Images.
% Do a "hole fill" to get rid of any background pixels inside the blobs.
binaryImage = imfill(binaryImage, 'holes');
% Display the binary image.
subplot(3, 3, 3); imagesc(binaryImage); colormap(gray(256)); title('Binary Image, obtained by thresholding');
% Label each object so we can make measurements of it
labeledImage = bwlabeln(binaryImage, 8);
subplot(3, 3, 4); imshow(labeledImage); title('Labeled Binary Image');
% locate the centroid of the object
celldata = regionprops(binaryImage, 'Centroid');
% 'Centroid' – 1-by-Q vector that specifies the center of mass of the region.
celldata_centroid = [celldata.Centroid];
centroidx = celldata_centroid(:, 1);
centroidy = celldata_centroid(:, 2);
% plot the centroid of the object
subplot(3, 3, 5); imshow(binaryImage);
title('Centroid Locations');
hold on
numObj = numel(celldata);
for k = 1 : numObj
plot(celldata(k).Centroid(1), celldata(k).Centroid(2), 'bo');
end
hold off
% define object boundaries
boundaries = bwboundaries(binaryImage);
mat_boundaries = cell2mat(boundaries);
boundaryx = mat_boundaries(:, 1:2:5);
boundaryy = mat_boundaries(:, 2:2:6);
allDistances = sqrt((boundaryx - centroidx).^2 + (boundaryy - centroidy).^2); % The array dimensions don't match up here so it always returns an error. Not quite sure how to go about it from here.

Answers (1)

Image Analyst
Image Analyst on 3 Aug 2014
Please attach your image so we can run the code.
Not sure what you want to do but it sounds like it might be exactly what my Image Segmentation tutorial does: http://www.mathworks.com/matlabcentral/fileexchange/?term=authorid%3A31862
  3 Comments
Image Analyst
Image Analyst on 3 Aug 2014
Edited: Image Analyst on 3 Aug 2014
Just because the objects I use in the demo are circular does not mean that regionprops() can only give centroids for circular objects. I'll try your code.... centroids is not computed correctly....I've fixed it below:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
imtool close all; % Close all imtool figures if you have the Image Processing Toolbox.
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;
%===============================================================================
% Read in a standard MATLAB color demo image.
folder = 'C:\Users\Dennis\Documents';
baseFileName = 'pseudocubic3x.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);
grayImage = rgb2gray(rgbImage);
subplot(2, 2, 1);
imshow(grayImage);
title('Original Image', 'fontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Logical Operation Approach.
thresholdValue = 200;
binaryImage = grayImage < thresholdValue; % Dark objects will be the chosen if you use <
% Do a "hole fill" to get rid of any background pixels inside the blobs.
binaryImage = imfill(binaryImage, 'holes');
% Display the binary image.
subplot(2, 2, 2);
imagesc(binaryImage);
colormap(gray(256));
title('Binary Image, obtained by thresholding', 'fontSize', fontSize);
% Label each object so we can make measurements of it
[labeledImage, numberOfRegions] = bwlabeln(binaryImage, 8);
subplot(2, 2, 3);
coloredLabels = label2rgb(labeledImage, 'hsv', 'k', 'shuffle'); % pseudo random color labels
imshow(coloredLabels);
title('Labeled Binary Image', 'fontSize', fontSize);
% locate the centroid of the object
measurements = regionprops(binaryImage, 'Centroid');
% 'Centroid' – 1-by-Q vector that specifies the center of mass of the region.
centroids = [measurements.Centroid];
centroidx = centroids(1:2:end);
centroidy = centroids(2:2:end);
% Plot the centroids of each object
subplot(2, 2, 4);
imshow(binaryImage);
title('Centroid Locations', 'fontSize', fontSize);
hold on
for k = 1 : numberOfRegions
plot(centroidx(k), centroidy(k), 'b*');
end
% Define object boundaries
boundaries = bwboundaries(binaryImage);
numberOfBoundaries = size(boundaries, 1);
for k = 1 : numberOfBoundaries
thisBoundary = boundaries{k};
boundaryx = thisBoundary(:, 2);
boundaryy = thisBoundary(:, 1);
plot(boundaryx, boundaryy, 'r-', 'LineWidth', 2);
% For this blob, compute distances from boundaries to edge.
allDistances = sqrt((boundaryx - centroidx(k)).^2 + (boundaryy - centroidy(k)).^2);
% Find farthest point, max distance.
[maxDistance(k), indexOfMax] = max(allDistances);
% Drawline
x1 = centroidx(k);
y1 = centroidy(k);
x2 = boundaryx(indexOfMax);
y2 = boundaryy(indexOfMax);
line([x1, x2], [y1, y2], 'Color', [1 0 1], 'LineWidth', 2);
end
hold off;
% Report to command window.
maxDistance
Dennis Chen
Dennis Chen on 4 Aug 2014
Thank you. As a quick follow up, I wanted to find the distance from the centroid to the edge as a function of an angle. Therefore, I added the following:
% For this blob, compute angles
deltaY = boundaryy - centroidy(k);
deltaX = boundaryx - centroidx(k);
allAngles = atand(deltaY ./ deltaX);
I'm also a bit confused about the fact that the variables allDistances and allAngles have the values "418x1double", which corresponds to the array of one of the boundaries.
If I choose to plot(allAngles, allDistances), it would seem that I would only obtain contour information for one of the objects. Could you please confirm my statement?

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!