detect certain shapes in binary

Asked by Tulips on 3 Jul 2012
Latest activity Commented on by Image Analyst on 31 Jul 2012

hi,in my image has 2 shapes ;triangular and circular(in binary). how can I eliminate the circular shape so that it just detect triangular shape.many thanks!

0 Comments

Tulips

Products

No products are associated with this question.

2 Answers

Answer by Walter Roberson on 3 Jul 2012
Accepted answer

Use regionprops() to calculate the Eccentricity. Eccentricity should be nearly 0 for a circle.

16 Comments

Image Analyst on 6 Jul 2012

See my image segmentation tutorial. http://www.mathworks.com/matlabcentral/fileexchange/?term=authorid%3A31862 It's done in there, and very well documented about how you use ismember() to filter out objects based on certain criteria.

Tulips on 6 Jul 2012

sir,which file should I refer to?there are a lot..

Walter Roberson on 6 Jul 2012

http://www.mathworks.com/matlabcentral/fileexchange/25157-image-segmentation-tutorial-blobsdemo/content/BlobsDemo.m

Look for the line that says

% Now I'll demonstrate how to select certain blobs based using the ismember function.
Walter Roberson
Answer by Image Analyst on 3 Jul 2012
Edited by Image Analyst on 9 Jul 2012

I prefer the perimeter squared to area ratio - the "circularity". For things like an asterisk shape, the eccentricity would be similar to similar to a circle bit the "circularity" of an asterisk would be much higher than that of a circle.

circularity = perimeter^2 / (4 * pi * area);

This is a very commonly used metric in shape analysis. So common that I don't know why it's not built into regionprops(). See my shape recognition demo:

% Demo to find certain shapes in an image based on their shape.
clc;    % Clear the command window.
close all;  % Close all figures (except those of imtool.)
imtool close all;  % Close all imtool figures.
clear;  % Erase all existing variables.
workspace;  % Make sure the workspace panel is showing.
fontSize = 20;
% Read in a standard MATLAB gray scale demo image.
folder = fullfile(matlabroot, '\toolbox\images\imdemos');
baseFileName = 'pillsetc.png';
% 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
% Read in image into an array.
rgbImage = imread(fullFileName); 
[rows, columns, numberOfColorBands] = size(rgbImage); 
% Display it.
subplot(2, 2, 1);
imshow(rgbImage, []);
title('Input Image', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Give a name to the title bar.
set(gcf,'name','Shape Recognition Demo','numbertitle','off') 
% If it's monochrome (indexed), convert it to color. 
if numberOfColorBands > 1
	grayImage = rgbImage(:,:,2);
else
	% It's already a gray scale image.
	grayImage = rgbImage;
end
% Make a triangle on it.
triangleXCoordinates = [360 420 480];
triangleYCoordinates = [350 252 350];
traiangleBinaryImage = poly2mask(triangleXCoordinates, triangleYCoordinates, rows, columns);
% Burn it into the gray scale image.
grayImage(traiangleBinaryImage) = 255;
% Display it.
subplot(2, 2, 2);
imshow(grayImage, []);
title('Grayscale Image', 'FontSize', fontSize);
% Binarize the image.
binaryImage = grayImage > 120;
% Display it.
subplot(2, 2, 3);
imshow(binaryImage, []);
title('Initial (Noisy) Binary Image', 'FontSize', fontSize);
% Remove small objects.
binaryImage = bwareaopen(binaryImage, 300);
% Display it.
subplot(2, 2, 4);
imshow(binaryImage, []);
title('Cleaned Binary Image', 'FontSize', fontSize);
[labeledImage numberOfObjects] = bwlabel(binaryImage);
blobMeasurements = regionprops(labeledImage,...
	'Perimeter', 'Area', 'FilledArea', 'Solidity', 'Centroid'); 
% Get the outermost boundaries of the objects, just for fun.
filledImage = imfill(binaryImage, 'holes');
boundaries = bwboundaries(filledImage);
% Collect some of the measurements into individual arrays.
perimeters = [blobMeasurements.Perimeter];
areas = [blobMeasurements.Area];
filledAreas = [blobMeasurements.FilledArea];
solidities = [blobMeasurements.Solidity];
% Calculate circularities:
circularities = perimeters .^2 ./ (4 * pi * filledAreas);
% Print to command window.
fprintf('#, Perimeter,        Area, Filled Area, Solidity, Circularity\n');
for blobNumber = 1 : numberOfObjects
	fprintf('%d, %9.3f, %11.3f, %11.3f, %8.3f, %11.3f\n', ...
		blobNumber, perimeters(blobNumber), areas(blobNumber), ...
		filledAreas(blobNumber), solidities(blobNumber), circularities(blobNumber));
end
% Say what shape they are.
% IMPORTANT NOTE: depending on the aspect ratio of the rectangle or triangle
% their circularity can go from some minimum number up to a huge number.
for blobNumber = 1 : numberOfObjects
	% Outline the object so the user can see it.
	thisBoundary = boundaries{blobNumber};
	subplot(2, 2, 2); % Switch to upper right image.
	hold on;
	% Display prior boundaries in blue
	for k = 1 : blobNumber-1
		thisBoundary = boundaries{k};
		plot(thisBoundary(:,2), thisBoundary(:,1), 'b', 'LineWidth', 3);
	end
	% Display this bounary in red.
	thisBoundary = boundaries{blobNumber};
	plot(thisBoundary(:,2), thisBoundary(:,1), 'r', 'LineWidth', 3);
	subplot(2, 2, 4); % Switch to lower right image.
	
	% Determine the shape.
	if circularities(blobNumber) < 1.2
		message = sprintf('The circularity of object #%d is %.3f,\nso the object is a circle',...
			blobNumber, circularities(blobNumber));
		shape = 'circle';
	elseif circularities(blobNumber) < 1.6
		message = sprintf('The circularity of object #%d is %.3f,\nso the object is a square',...
			blobNumber, circularities(blobNumber));
		shape = 'square';
	elseif circularities(blobNumber) > 1.6 && circularities(blobNumber) < 1.8
		message = sprintf('The circularity of object #%d is %.3f,\nso the object is an isocoles triangle',...
			blobNumber, circularities(blobNumber));
		shape = 'triangle';
	else
		message = sprintf('The circularity of object #%d is %.3f,\nso the object is something else.',...
			blobNumber, circularities(blobNumber));
		shape = 'something else';
	end
	% Display in overlay above the object
	overlayMessage = sprintf('Object #%d = %s\ncirc = %.2f, s = %.2f', ...
		blobNumber, shape, circularities(blobNumber), solidities(blobNumber));
	text(blobMeasurements(blobNumber).Centroid(1), blobMeasurements(blobNumber).Centroid(2), ...
		overlayMessage, 'Color', 'r');
	button = questdlg(message, 'Continue', 'Continue', 'Cancel', 'Continue');
	if strcmp(button, 'Cancel')
		break;
	end
end

7 Comments

Image Analyst on 29 Jul 2012

Think of the convex hull as if you wrapped a rubber band around your object. If an object had no concavities, like a perfect square or circle, then the solidity = 1 because there are no points on the perimeter the rubber band does not touch. Now if the blob looked like a boomerang, then there would be a huge concavity where the rubber band would not touch the perimeter, so it's solidity would be much less than 1.

Tulips on 31 Jul 2012

can I know from the code given, how can I remove the rectangle such as in the photo http://www.flickr.com/photos/80166922@N06/7681815436/in/photostream/ I just want the inverted triangle shape only.many thanks.

Image Analyst on 31 Jul 2012

Detect the rectangle - it will have the smallest area. Then use ismember to remove it. Have you run my BlobsDemo? It goes over all this.

Image Analyst

Contact us