From: Vivian Harvey on
ImageAnalyst <imageanalyst(a)mailinator.com> wrote in message <2f074096-4ec8-4b82-847a-d96c904dbdc7(a)b30g2000yqd.googlegroups.com>...
> Vivian Harvey:
> Where's your image? - you didn't post it, so about all I can offer is
> this demo which I use to find the area and centroid of round objects.
> http://www.mathworks.com/matlabcentral/fileexchange/25157
>
> Also, I'm not sure what this question or statement really means "If
> possible, not considering dimensions and there are no perfect shapes
> in the image. "
>
> And please define what you mean by "pinpoint." Do you mean the
> centroid (x,y) location? Or a list of all the pixels in the blob? Or
> something else?


Hi there,

http://i969.photobucket.com/albums/ae175/viviharve/untitled.png is sample..the thing is that I wanted to do is to detect that there are circular objects in the image as you can see on the sample, with dented and uneven edges..that isnt the real sample I am dealing with but it looks close..

...a centroid location would be good point to start if that is possible ...its just that the circular objects are filtered out irrespective of how big or small they are so that I dont have to use a loop of increasing radius of circles to scan the image for circular objects...
....as you can see there are two blobs here and a random shape..I just want to concentrate on the blobs and forget the random elongated shape even exists in the image...the data I need from this blobs can be obtained if I have the centroid or the coordinates of the pixels on teh circumference or both...
From: Vivian Harvey on
"David Young" <d.s.young.notthisbit(a)sussex.ac.uk> wrote in message <hnm54t$3iu$1(a)fred.mathworks.com>...
> Sorry - the link doesn't work because I put the full stop right after the URL. This link should be better: http://www.mathworks.com/matlabcentral/fileexchange/9833

Thanks for replying...
What I actually want to know is where the circular objects are first and then deal with the dimensions...I have thought about hough transforms before but most popular methods are by presuppositions what the radii could be..
From: David Young on
OK, now I've seen the image, maybe it's easier than I thought and doesn't need a Hough transform. If all the images have shapes that are nicely joined up like those in the test image, and they don't overlap, then you can just do a connected region analysis to separate them out and use simple properties of the regions to distinguish the more circular ones from the others.

Here's some example code that works on the image your link points to, assuming it's been saved in shapes.png:
-----
im = imread('../shapes.png');
im = rgb2gray(im);

% find the centroids of low-eccentricity blobs
graythresh = 128;
eccthresh = 0.6;
props = regionprops(im < graythresh, 'Centroid', 'Eccentricity');
roundones = props([props.Eccentricity] < eccthresh);
centroids = [roundones.Centroid];

% show them
imshow(im);
hold on;
plot(centroids(1:2:end), centroids(2:2:end), 'g+');
hold off;
-----
This just uses the eccentricity to pick out the rounder shapes. It's got a couple of parameters that are set at the start; these might need to be tweaked for this to work across a range of examples, and you might need a more sophisticated test in general. Look at regionprops for inspiration!
From: ImageAnalyst on
Vivian Harvey:
This is really easy. Just follow my demo
http://www.mathworks.com/matlabcentral/fileexchange/25157
You have to put in an imclearborder() to get rid of the bright
background after you threshold it, but other than that it will work
with very little modification. Here is the modified blobsdemo for
you:
By the way, your image has an extension of PNG but it is really a BMP
image.
Also, be sure to join any lines split apart by the newsreader.
It may look long but it's basically these parts
1. threshold.
2. imclearborder
3. label
4. regionprops
5. ismember() to retain only the round blobs and throw away the non-
round blobs.

%------------------------------------------------------------------------------------------------
% Demo to illustrate simple blob detection, measurement, and
filtering.
% Requires the Image Processing Toolbox (IPT) because it demonstates
some functions
% supplied by that toolbox, plus it uses the "coins" demo image
supplied with that toolbox.
% If you have the IPT (you can check by typing ver on the command
line), you should be able to
% run this demo code simply by copying and pasting this code into a
new editor window,
% and then clicking the green "run" triangle on the toolbar.
% Running time = 7.5 seconds the first run and 2.5 seconds on
subsequent runs.
% A similar Mathworks demo:
% http://www.mathworks.com/products/image/demos.html?file=/products/demos/shipping/images/ipexprops.html
% Code written and posted by ImageAnalyst, July 2009.
%------------------------------------------------------------------------------------------------
% function BlobsDemo()
% echo on;
% Startup code.
tic; % Start timer.
clc; % Clear command window.
clear all; % Get rid of variables from prior run of this m-file.
disp('Running BlobsDemo.m...'); % Message sent to command window.
workspace; % Show panel with all the variables.

% Change the current folder to the folder of this m-file.
% (The line of code below is from Brett Shoelson of The Mathworks.)
if(~isdeployed)
cd(fileparts(which(mfilename)));
end

% Read in standard MATLAB demo image
fullFilename = 'C:\Documents and Settings\userName\My Documents
\Temporary stuff\Line Drawings.bmp';
rgbOriginalImage = imread(fullFilename);
% It's color, so take just the red channel:
originalImage = rgbOriginalImage(:,:,1);
subplot(3, 3, 1);
imshow(originalImage);
% Maximize the figure window.
set(gcf, 'Position', get(0, 'ScreenSize'));
% Force it to display RIGHT NOW (otherwise it might not display until
it's all done, unless you've stopped at a breakpoint.)
drawnow;
caption = sprintf('Original "coins" image showing\n6 nickels (the
larger coins) and 4 dimes (the smaller coins).');
title(caption);
axis square; % Make sure image is not artificially stretched because
of screen's aspect ratio.

% Just for fun, let's get its histogram.
[pixelCount grayLevels] = imhist(originalImage);
subplot(3, 3, 2);
bar(pixelCount); title('Histogram of original image');
xlim([0 grayLevels(end)]); % Scale x axis manually.

% Threshold the image to get a binary image (only 0's and 1's) of
class "logical."
% Method #1: using im2bw()
% normalizedThresholdValue = 0.4; % In range 0 to 1.
% thresholdValue = normalizedThresholdValue *
max(max(originalImage)); % Gray Levels.
% binaryImage = im2bw(originalImage,
normalizedThresholdValue); % One way to threshold to binary
% Method #2: using a logical operation.
thresholdValue = 100;
binaryImage = originalImage > thresholdValue; % Bright objects will
be the chosen if you use >.
% binaryImage = originalImage < thresholdValue; % Dark objects will
be the chosen if you use <.
binaryImage = imclearborder(binaryImage, 4);

% Do a "hole fill" to get rid of any background pixels inside the
blobs.
binaryImage = imfill(binaryImage, 'holes');

% Show the threshold as a vertical red bar on the histogram.
hold on;
maxYValue = ylim;
hStemLines = stem(thresholdValue, maxYValue(2), 'r');
children = get(hStemLines, 'children');
set(children(2),'visible', 'off');
% Place a text label on the bar chart showing the threshold.
annotationText = sprintf('Thresholded at %d gray levels',
thresholdValue);
% For text(), the x and y need to be of the data class "double" so
let's cast both to double.
text(double(thresholdValue + 5), double(0.5 * maxYValue(2)),
annotationText, 'FontSize', 10, 'Color', [0 .5 0]);
text(double(thresholdValue - 70), double(0.94 * maxYValue(2)),
'Background', 'FontSize', 10, 'Color', [0 0 .5]);
text(double(thresholdValue + 50), double(0.94 * maxYValue(2)),
'Foreground', 'FontSize', 10, 'Color', [0 0 .5]);


% Display the binary image.
subplot(3, 3, 3); imagesc(binaryImage); colormap(gray(256));
title('Binary Image, obtained by thresholding'); axis square;

labeledImage = bwlabel(binaryImage, 8); % Label each blob so we
can make measurements of it
coloredLabels = label2rgb (labeledImage, 'hsv', 'k', 'shuffle'); %
pseudo random color labels

subplot(3, 3, 4);
imshow(labeledImage, []);
title('Labeled Image, from bwlabel()');
axis square;
subplot(3, 3, 5);
imagesc(coloredLabels);
axis square;
caption = sprintf('Pseudo colored labels, from label2rgb().\nBlobs are
numbered from top to bottom, then from left to right.');
title(caption);

% Get all the blob properties. Can only pass in originalImage in
version R2008a and later.
blobMeasurements = regionprops(labeledImage, originalImage, 'all');
numberOfBlobs = size(blobMeasurements, 1);

% bwboundaries() returns a cell array, where each cell contains the
row/column coordinates for an object in the image.
% Plot the borders of all the coins on the original grayscale image
using the coordinates returned by bwboundaries.
subplot(3, 3, 6); imagesc(originalImage);
title('Outlines, from bwboundaries()'); axis square;
hold on;
boundaries = bwboundaries(binaryImage);
numberOfBoundaries = size(boundaries);
for k = 1 : numberOfBoundaries
thisBoundary = boundaries{k};
plot(thisBoundary(:,2), thisBoundary(:,1), 'g', 'LineWidth', 2);
end
hold off;

fontSize = 14; % Used to control size of "blob number" labels put atop
the image.
labelShiftX = -7; % Used to align the labels in the centers of the
coins.
% Print header line in the command window.
fprintf(1,'Blob # Mean Intensity Area Perimeter
Centroid Diameter (ECD) Solidity\n');
% Loop over all blobs printing their measurements to the command
window.
for k = 1 : numberOfBlobs % Loop through all blobs.
% Find the mean of each blob. (R2008a has a better way where you can
pass the original image
% directly into regionprops. The way below works for all versions
including earlier versions.)
thisBlobsPixels = blobMeasurements(k).PixelIdxList; % Get list of
pixels in current blob.
meanGL = mean(originalImage(thisBlobsPixels)); % Find mean
intensity (in original image!)
meanGL2008a = blobMeasurements(k).MeanIntensity; % Mean again, but
only for version >= R2008a

blobArea = blobMeasurements(k).Area; % Get area.
blobPerimeter = blobMeasurements(k).Perimeter; % Get perimeter.
blobCentroid = blobMeasurements(k).Centroid; % Get centroid.
blobSolidity = blobMeasurements(k).Solidity; % Get solidity.
blobECD = sqrt(4 * blobArea / pi); % Compute ECD - Equivalent
Circular Diameter.
fprintf(1,'#%2d %17.1f %11.1f %8.1f %8.1f %8.1f % 8.1f %8.1f\n',
k, meanGL, blobArea, blobPerimeter, blobCentroid, blobECD,
blobSolidity);
% Put the "blob number" labels on the "boundaries" grayscale image.
text(blobCentroid(1) + labelShiftX, blobCentroid(2), num2str(k),
'FontSize', fontSize, 'FontWeight', 'Bold');
end

% Put the labels on the rgb labeled image also.
subplot(3, 3, 5);
for k = 1 : numberOfBlobs % Loop through all blobs.
blobCentroid = blobMeasurements(k).Centroid; % Get centroid.
text(blobCentroid(1) + labelShiftX, blobCentroid(2), num2str(k),
'FontSize', fontSize, 'FontWeight', 'Bold');
end

% Now I'll demonstrate how to select certain blobs based using the
ismember function.
% Let's say that we wanted to find only those blobs
% with an intensity between 150 and 220 and an area less than 2000
pixels.
% This would give us the three brightest dimes (the smaller coin
type).
allBlobSolidities = [blobMeasurements.Solidity];
% Get a list of the blobs that meet our criteria and we need to keep.
allowableIndexes = allBlobSolidities > 0.8; % Take the round objects.
keeperIndexes = find(allowableIndexes);
% Extract only those blobs that meet our criteria, and
% eliminate those blobs that don't meet our criteria.
% Note how we use ismember() to do this.
keeperBlobsImage = ismember(labeledImage, keeperIndexes);
subplot(3, 3, 7);
imshow(keeperBlobsImage, []);
axis square;
title('"Keeper" blobs (round blobs)');
% Re-label with only the keeper blobs kept.
labeledRoundBlobImage = bwlabel(keeperBlobsImage, 4); % Label each
blob so we can make measurements of it
% Now we're done. We have a labeled image of blobs that meet our
specified criteria.
subplot(3, 3, 8);
imshow(labeledRoundBlobImage, []);
axis square;
title('Re-labeled blobs (round blobs)');

elapsedTime = toc;
% Alert user that the demo is done and give them the option to save an
image.
message = sprintf('Finished running BlobsDemo.m.\n\nElapsed time = %.
2f seconds.', elapsedTime);
message = sprintf('%s\n\nCheck out the figure window for the images.
\nCheck out the command window for the numerical results.', message);
From: Vivian Harvey on
ImageAnalyst <imageanalyst(a)mailinator.com> wrote in message <390d8c4a-973f-4454-b20f-ff98b30f1c1c(a)e7g2000yqf.googlegroups.com>...
> Vivian Harvey:
> This is really easy. Just follow my demo
> http://www.mathworks.com/matlabcentral/fileexchange/25157
> You have to put in an imclearborder() to get rid of the bright
> background after you threshold it, but other than that it will work
> with very little modification. Here is the modified blobsdemo for
> you:
> By the way, your image has an extension of PNG but it is really a BMP
> image.
> Also, be sure to join any lines split apart by the newsreader.
> It may look long but it's basically these parts
> 1. threshold.
> 2. imclearborder
> 3. label
> 4. regionprops
> 5. ismember() to retain only the round blobs and throw away the non-
> round blobs.
>
> %------------------------------------------------------------------------------------------------
> % Demo to illustrate simple blob detection, measurement, and
> filtering.
> % Requires the Image Processing Toolbox (IPT) because it demonstates
> some functions
> % supplied by that toolbox, plus it uses the "coins" demo image
> supplied with that toolbox.
> % If you have the IPT (you can check by typing ver on the command
> line), you should be able to
> % run this demo code simply by copying and pasting this code into a
> new editor window,
> % and then clicking the green "run" triangle on the toolbar.
> % Running time = 7.5 seconds the first run and 2.5 seconds on
> subsequent runs.
> % A similar Mathworks demo:
> % http://www.mathworks.com/products/image/demos.html?file=/products/demos/shipping/images/ipexprops.html
> % Code written and posted by ImageAnalyst, July 2009.
> %------------------------------------------------------------------------------------------------
> % function BlobsDemo()
> % echo on;
> % Startup code.
> tic; % Start timer.
> clc; % Clear command window.
> clear all; % Get rid of variables from prior run of this m-file.
> disp('Running BlobsDemo.m...'); % Message sent to command window.
> workspace; % Show panel with all the variables.
>
> % Change the current folder to the folder of this m-file.
> % (The line of code below is from Brett Shoelson of The Mathworks.)
> if(~isdeployed)
> cd(fileparts(which(mfilename)));
> end
>
> % Read in standard MATLAB demo image
> fullFilename = 'C:\Documents and Settings\userName\My Documents
> \Temporary stuff\Line Drawings.bmp';
> rgbOriginalImage = imread(fullFilename);
> % It's color, so take just the red channel:
> originalImage = rgbOriginalImage(:,:,1);
> subplot(3, 3, 1);
> imshow(originalImage);
> % Maximize the figure window.
> set(gcf, 'Position', get(0, 'ScreenSize'));
> % Force it to display RIGHT NOW (otherwise it might not display until
> it's all done, unless you've stopped at a breakpoint.)
> drawnow;
> caption = sprintf('Original "coins" image showing\n6 nickels (the
> larger coins) and 4 dimes (the smaller coins).');
> title(caption);
> axis square; % Make sure image is not artificially stretched because
> of screen's aspect ratio.
>
> % Just for fun, let's get its histogram.
> [pixelCount grayLevels] = imhist(originalImage);
> subplot(3, 3, 2);
> bar(pixelCount); title('Histogram of original image');
> xlim([0 grayLevels(end)]); % Scale x axis manually.
>
> % Threshold the image to get a binary image (only 0's and 1's) of
> class "logical."
> % Method #1: using im2bw()
> % normalizedThresholdValue = 0.4; % In range 0 to 1.
> % thresholdValue = normalizedThresholdValue *
> max(max(originalImage)); % Gray Levels.
> % binaryImage = im2bw(originalImage,
> normalizedThresholdValue); % One way to threshold to binary
> % Method #2: using a logical operation.
> thresholdValue = 100;
> binaryImage = originalImage > thresholdValue; % Bright objects will
> be the chosen if you use >.
> % binaryImage = originalImage < thresholdValue; % Dark objects will
> be the chosen if you use <.
> binaryImage = imclearborder(binaryImage, 4);
>
> % Do a "hole fill" to get rid of any background pixels inside the
> blobs.
> binaryImage = imfill(binaryImage, 'holes');
>
> % Show the threshold as a vertical red bar on the histogram.
> hold on;
> maxYValue = ylim;
> hStemLines = stem(thresholdValue, maxYValue(2), 'r');
> children = get(hStemLines, 'children');
> set(children(2),'visible', 'off');
> % Place a text label on the bar chart showing the threshold.
> annotationText = sprintf('Thresholded at %d gray levels',
> thresholdValue);
> % For text(), the x and y need to be of the data class "double" so
> let's cast both to double.
> text(double(thresholdValue + 5), double(0.5 * maxYValue(2)),
> annotationText, 'FontSize', 10, 'Color', [0 .5 0]);
> text(double(thresholdValue - 70), double(0.94 * maxYValue(2)),
> 'Background', 'FontSize', 10, 'Color', [0 0 .5]);
> text(double(thresholdValue + 50), double(0.94 * maxYValue(2)),
> 'Foreground', 'FontSize', 10, 'Color', [0 0 .5]);
>
>
> % Display the binary image.
> subplot(3, 3, 3); imagesc(binaryImage); colormap(gray(256));
> title('Binary Image, obtained by thresholding'); axis square;
>
> labeledImage = bwlabel(binaryImage, 8); % Label each blob so we
> can make measurements of it
> coloredLabels = label2rgb (labeledImage, 'hsv', 'k', 'shuffle'); %
> pseudo random color labels
>
> subplot(3, 3, 4);
> imshow(labeledImage, []);
> title('Labeled Image, from bwlabel()');
> axis square;
> subplot(3, 3, 5);
> imagesc(coloredLabels);
> axis square;
> caption = sprintf('Pseudo colored labels, from label2rgb().\nBlobs are
> numbered from top to bottom, then from left to right.');
> title(caption);
>
> % Get all the blob properties. Can only pass in originalImage in
> version R2008a and later.
> blobMeasurements = regionprops(labeledImage, originalImage, 'all');
> numberOfBlobs = size(blobMeasurements, 1);
>
> % bwboundaries() returns a cell array, where each cell contains the
> row/column coordinates for an object in the image.
> % Plot the borders of all the coins on the original grayscale image
> using the coordinates returned by bwboundaries.
> subplot(3, 3, 6); imagesc(originalImage);
> title('Outlines, from bwboundaries()'); axis square;
> hold on;
> boundaries = bwboundaries(binaryImage);
> numberOfBoundaries = size(boundaries);
> for k = 1 : numberOfBoundaries
> thisBoundary = boundaries{k};
> plot(thisBoundary(:,2), thisBoundary(:,1), 'g', 'LineWidth', 2);
> end
> hold off;
>
> fontSize = 14; % Used to control size of "blob number" labels put atop
> the image.
> labelShiftX = -7; % Used to align the labels in the centers of the
> coins.
> % Print header line in the command window.
> fprintf(1,'Blob # Mean Intensity Area Perimeter
> Centroid Diameter (ECD) Solidity\n');
> % Loop over all blobs printing their measurements to the command
> window.
> for k = 1 : numberOfBlobs % Loop through all blobs.
> % Find the mean of each blob. (R2008a has a better way where you can
> pass the original image
> % directly into regionprops. The way below works for all versions
> including earlier versions.)
> thisBlobsPixels = blobMeasurements(k).PixelIdxList; % Get list of
> pixels in current blob.
> meanGL = mean(originalImage(thisBlobsPixels)); % Find mean
> intensity (in original image!)
> meanGL2008a = blobMeasurements(k).MeanIntensity; % Mean again, but
> only for version >= R2008a
>
> blobArea = blobMeasurements(k).Area; % Get area.
> blobPerimeter = blobMeasurements(k).Perimeter; % Get perimeter.
> blobCentroid = blobMeasurements(k).Centroid; % Get centroid.
> blobSolidity = blobMeasurements(k).Solidity; % Get solidity.
> blobECD = sqrt(4 * blobArea / pi); % Compute ECD - Equivalent
> Circular Diameter.
> fprintf(1,'#%2d %17.1f %11.1f %8.1f %8.1f %8.1f % 8.1f %8.1f\n',
> k, meanGL, blobArea, blobPerimeter, blobCentroid, blobECD,
> blobSolidity);
> % Put the "blob number" labels on the "boundaries" grayscale image.
> text(blobCentroid(1) + labelShiftX, blobCentroid(2), num2str(k),
> 'FontSize', fontSize, 'FontWeight', 'Bold');
> end
>
> % Put the labels on the rgb labeled image also.
> subplot(3, 3, 5);
> for k = 1 : numberOfBlobs % Loop through all blobs.
> blobCentroid = blobMeasurements(k).Centroid; % Get centroid.
> text(blobCentroid(1) + labelShiftX, blobCentroid(2), num2str(k),
> 'FontSize', fontSize, 'FontWeight', 'Bold');
> end
>
> % Now I'll demonstrate how to select certain blobs based using the
> ismember function.
> % Let's say that we wanted to find only those blobs
> % with an intensity between 150 and 220 and an area less than 2000
> pixels.
> % This would give us the three brightest dimes (the smaller coin
> type).
> allBlobSolidities = [blobMeasurements.Solidity];
> % Get a list of the blobs that meet our criteria and we need to keep.
> allowableIndexes = allBlobSolidities > 0.8; % Take the round objects.
> keeperIndexes = find(allowableIndexes);
> % Extract only those blobs that meet our criteria, and
> % eliminate those blobs that don't meet our criteria.
> % Note how we use ismember() to do this.
> keeperBlobsImage = ismember(labeledImage, keeperIndexes);
> subplot(3, 3, 7);
> imshow(keeperBlobsImage, []);
> axis square;
> title('"Keeper" blobs (round blobs)');
> % Re-label with only the keeper blobs kept.
> labeledRoundBlobImage = bwlabel(keeperBlobsImage, 4); % Label each
> blob so we can make measurements of it
> % Now we're done. We have a labeled image of blobs that meet our
> specified criteria.
> subplot(3, 3, 8);
> imshow(labeledRoundBlobImage, []);
> axis square;
> title('Re-labeled blobs (round blobs)');
>
> elapsedTime = toc;
> % Alert user that the demo is done and give them the option to save an
> image.
> message = sprintf('Finished running BlobsDemo.m.\n\nElapsed time = %.
> 2f seconds.', elapsedTime);
> message = sprintf('%s\n\nCheck out the figure window for the images.
> \nCheck out the command window for the numerical results.', message);


Thank you for the above. I will try to see whether this works and I hope I will be smart enough to incorporate the methodology :) ..Regards
First  |  Prev  |  Next  |  Last
Pages: 1 2 3
Prev: create a vector of months
Next: fmincon minimisation