problem with centroid of binary image

hi i use bwconncomp and regionprob with centroid feature to find centroid of binary image but i cant understand one thing? if i use centroid feature, it return one point or a structure of points? when i use this i have a structure of point that i think it is wrong do you have any idea?

2 Comments

nadia naji
nadia naji on 10 Feb 2013
Edited: nadia naji on 10 Feb 2013
i need to consider the behavior of centroid of binary image (with several object in that image ) in sequential frame of video and show them the number of object can be different in each frame. how can i do it? pls help me?

Sign in to comment.

 Accepted Answer

Note that if your "binary array" is a numeric datatype, with 0's and 1's, rather than a logical array (false and true's), then regionprops will treat the numeric array as if it is a labeled array that happens to contain only one label. To avoid that, call bwlabel() to separate out the blobls.
labelarray = bwlabel(not_really_binary_Image));
measurements = regionprops(labelarray, 'Centroid');
then measurements will be a struct array with the field 'Centroid' for each blob. Each of the 'Centroid' fields will be a vector whose length matches the dimension of the image (usually 2).

11 Comments

It was that way for older versions (prior to R2008a I think??). With more modern versions it considers them as separate blobs if the values are all 1, though it will merge blobs for disconnected blobs with number 2 or higher. See this demo where I skip labeling in R2012b and it finds 3 separate blobs:
grayImage = peaks(200);
subplot(1,2,1);
imshow(grayImage, []);
title('Original Gray Image', 'FontSize', 30);
axis on;
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Binarize the image to find 3 blobs.
binaryImage = grayImage > 3;
subplot(1,2,2);
imshow(binaryImage);
axis on;
title('Binary Image with Marked Centroids', 'FontSize', 30);
% Make the measurements, skipping the labeling.
measurements = regionprops(binaryImage, 'Area', 'Centroid')
[allAreas] = [measurements.Area]
allCentroids = [measurements.Centroid]
x_centroids = allCentroids(1:2:end)
y_centroids = allCentroids(2:2:end)
hold on;
plot(x_centroids, y_centroids, 'r+', 'MarkerSize', 30);
is not any way to find the centroid of whole image in r2012a? can you help me?
The documentation indicates http://www.mathworks.com/help/images/ref/regionprops.html that the automatic labelling happens for binary arrays, which the documentation defines in terms of logical datatype
if i mean on structure of centroid it can get me the centroid of objects in each frame?
no, you cannot apply mean() to a structure.
what does class() of your binary array show? Are you passing the binary array into regionprops or are you passing the result of bwconncomp ? bwconncomp already does the separation into blobs so if you want the overall centroid rather than the centroid of each blob, you should not pass in the result of bwconncomp
Image Analyst
Image Analyst on 10 Feb 2013
Edited: Image Analyst on 10 Feb 2013
Walter - you're right. I didn't read carefully enough.
nadia naji
nadia naji on 11 Feb 2013
Edited: nadia naji on 11 Feb 2013
i use bwconncomp and then pass the output of this function to regionprobs in fact i use this code con=bwconncomp(img); ctr=regionprobs(con,'Centroid');
is it wrong? i should pass the image to regionprobs?? i pass the binary image to regionprobs but i have a structure of centroids instead of only one centroid for overall image?
If you pass the con to regionprops you are going to get one centroid per blob.
If you pass an array of logical values (true & false) to modern regionprops() then you are going to get one centroid per blob.
If you do have an array of logical values as your variable img, then
ctr = regionprops(double(img), 'Centroid');
should return the centroid of the image.
Please post your image. I don't like working "blind."
thanks a lot it works by using double i really appreciate your help
How did you end up with a double? That's not normally the case. Usually you process the image to a point where you can threshold it and get a binary image. You said you had a binary image (logical) but now you say you have a double image. Something's weird.

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 10 Feb 2013
Edited: Image Analyst on 10 Feb 2013
regionprops returns a structure array. Each element in the array is a structure with all the measurements for that one blob. Centroid or WeightedCentroid might be one of those measurements, if you asked regionprops to calculate it. It will be a 2 element array. For example, for blob #k,
measurements = regionprops(binaryImage, 'Centriod');
theCentroid = measurements(k).Centroid; % for blob #k only
Perhaps this demo will help:
% Demo to have the user freehand draw an irregular shape over
% a gray scale image, have it extract only that part to a new image,
% and to calculate the mean intensity value of the image within that shape.
% Also calculates the perimeter, centroid, and center of mass (weighted centroid).
% Change the current folder to the folder of this m-file.
if(~isdeployed)
cd(fileparts(which(mfilename)));
end
clc; % Clear command window.
clear; % Delete all variables.
close all; % Close all figure windows except those created by imtool.
imtool close all; % Close all figure windows created by imtool.
workspace; % Make sure the workspace panel is showing.
fontSize = 16;
% Read in a standard MATLAB gray scale demo image.
folder = fullfile(matlabroot, '\toolbox\images\imdemos');
baseFileName = 'cameraman.tif';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% File doesn't exist -- 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 in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(fullFileName);
imshow(grayImage, []);
axis on;
title('Original Grayscale Image', 'FontSize', fontSize);
set(gcf, 'Position', get(0,'Screensize')); % Maximize figure.
message = sprintf('Left click and hold to begin drawing.\nSimply lift the mouse button to finish');
uiwait(msgbox(message));
hFH = imfreehand();
% Create a binary image ("mask") from the ROI object.
binaryImage = hFH.createMask();
xy = hFH.getPosition;
% Now make it smaller so we can show more images.
subplot(2, 3, 1);
imshow(grayImage, []);
axis on;
drawnow;
title('Original Grayscale Image', 'FontSize', fontSize);
% Display the freehand mask.
subplot(2, 3, 2);
imshow(binaryImage);
axis on;
title('Binary mask of the region', 'FontSize', fontSize);
% Label the binary image and computer the centroid and center of mass.
labeledImage = bwlabel(binaryImage);
measurements = regionprops(binaryImage, grayImage, ...
'area', 'Centroid', 'WeightedCentroid', 'Perimeter');
area = measurements.Area
centroid = measurements.Centroid
centerOfMass = measurements.WeightedCentroid
perimeter = measurements.Perimeter
% Calculate the area, in pixels, that they drew.
numberOfPixels1 = sum(binaryImage(:))
% Another way to calculate it that takes fractional pixels into account.
numberOfPixels2 = bwarea(binaryImage)
% Get coordinates of the boundary of the freehand drawn region.
structBoundaries = bwboundaries(binaryImage);
xy=structBoundaries{1}; % Get n by 2 array of x,y coordinates.
x = xy(:, 2); % Columns.
y = xy(:, 1); % Rows.
subplot(2, 3, 1); % Plot over original image.
hold on; % Don't blow away the image.
plot(x, y, 'LineWidth', 2);
drawnow; % Force it to draw immediately.
% Burn line into image by setting it to 255 wherever the mask is true.
burnedImage = grayImage;
burnedImage(binaryImage) = 255;
% Display the image with the mask "burned in."
subplot(2, 3, 3);
imshow(burnedImage);
axis on;
caption = sprintf('New image with\nmask burned into image');
title(caption, 'FontSize', fontSize);
% Mask the image and display it.
% Will keep only the part of the image that's inside the mask, zero outside mask.
blackMaskedImage = grayImage;
blackMaskedImage(~binaryImage) = 0;
subplot(2, 3, 4);
imshow(blackMaskedImage);
axis on;
title('Masked Outside Region', 'FontSize', fontSize);
% Calculate the mean
meanGL = mean(blackMaskedImage(binaryImage));
% Put up crosses at the centriod and center of mass
hold on;
plot(centroid(1), centroid(2), 'r+', 'MarkerSize', 30, 'LineWidth', 2);
plot(centerOfMass(1), centerOfMass(2), 'g+', 'MarkerSize', 20, 'LineWidth', 2);
% Now do the same but blacken inside the region.
insideMasked = grayImage;
insideMasked(binaryImage) = 0;
subplot(2, 3, 5);
imshow(insideMasked);
axis on;
title('Masked Inside Region', 'FontSize', fontSize);
% Now crop the image.
leftColumn = min(x);
rightColumn = max(x);
topLine = min(y);
bottomLine = max(y);
width = rightColumn - leftColumn + 1;
height = bottomLine - topLine + 1;
croppedImage = imcrop(blackMaskedImage, [leftColumn, topLine, width, height]);
% Display cropped image.
subplot(2, 3, 6);
imshow(croppedImage);
axis on;
title('Cropped Image', 'FontSize', fontSize);
% Put up crosses at the centriod and center of mass
hold on;
plot(centroid(1)-leftColumn, centroid(2)-topLine, 'r+', 'MarkerSize', 30, 'LineWidth', 2);
plot(centerOfMass(1)-leftColumn, centerOfMass(2)-topLine, 'g+', 'MarkerSize', 20, 'LineWidth', 2);
% Report results.
message = sprintf('Mean value within drawn area = %.3f\nNumber of pixels = %d\nArea in pixels = %.2f\nperimeter = %.2f\nCentroid at (x,y) = (%.1f, %.1f)\nCenter of Mass at (x,y) = (%.1f, %.1f)\nRed crosshairs at centroid.\nGreen crosshairs at center of mass.', ...
meanGL, numberOfPixels1, numberOfPixels2, perimeter, ...
centroid(1), centroid(2), centerOfMass(1), centerOfMass(2));
msgbox(message);

2 Comments

nadia naji
nadia naji on 10 Feb 2013
Edited: nadia naji on 10 Feb 2013
excuse me i cant understand some things i need to have one centroid for objects in image not structure of several centroid because i need to consider the movement of centroids in sequential frame? do you understand what i need? i need centroid of whole image please help me
Nadia, if this is in a loop over frames, just extract the centroids (x_centroids and y_centroids) from the structure. Make x_centroids and y_centroids arrays that depend on the frame. So if you have 300 frames, x_centroids is an array of 300 x centroids. Then you can do mean_x_centroid = mean(x_centroids). It becomes more complicated if there are different numbers of blobs in each frame - then it becomes essentially a tracking problem, which is more complicated because you have to account for blobs coming into the field of view and blobs leaving the field of view.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!