290 views (last 30 days)

Show older comments

Image Analyst
on 12 Dec 2015

Matt Kindig
on 21 Feb 2014

Edited: Matt Kindig
on 21 Feb 2014

Another approach is to calculate the best-fit bounding rectangle of each object, such that the bounding rectangle can be oriented at an arbitrary angle. I took the following approach:

1) Identify the boundary (i.e. perimeter) of each object, using bwboundaries()

2) Calculate the smallest rectangular bounding box that contains this perimeter. To do this, I used the minboundrect function available at http://www.mathworks.com/matlabcentral/fileexchange/34767-a-suite-of-minimal-bounding-objects/content/MinBoundSuite/minboundrect.m.

3) I calculated the width, height, and area of each bounding rectangle. The aspect ratio (ratio between the width and height) can be used to determine whether it is a square (aspect ratio ~= 1.0) or rectangle.

4) For a rectangle or square, the filled area of the object (from regionprops()) should be almost the same as the area of its bounding rectangle, whereas for a triangle it should be substantially less.

5) For the circularity condition, I used the ratio between perimeter and area like Image Analyst suggested.

Enjoy!

im = imread('http://www.mathworks.com/matlabcentral/answers/uploaded_files/8372/abc.jpg');

%convert to 2D black and white with colors inverted

BW = im(:,:,1) < 10;

%get outlines of each object

[B,L,N] = bwboundaries(BW);

%get stats

stats= regionprops(L, 'Centroid', 'Area', 'Perimeter');

Centroid = cat(1, stats.Centroid);

Perimeter = cat(1,stats.Perimeter);

Area = cat(1,stats.Area);

CircleMetric = (Perimeter.^2)./(4*pi*Area); %circularity metric

SquareMetric = NaN(N,1);

TriangleMetric = NaN(N,1);

%for each boundary, fit to bounding box, and calculate some parameters

for k=1:N,

boundary = B{k};

[rx,ry,boxArea] = minboundrect( boundary(:,2), boundary(:,1)); %x and y are flipped in images

%get width and height of bounding box

width = sqrt( sum( (rx(2)-rx(1)).^2 + (ry(2)-ry(1)).^2));

height = sqrt( sum( (rx(2)-rx(3)).^2+ (ry(2)-ry(3)).^2));

aspectRatio = width/height;

if aspectRatio > 1,

aspectRatio = height/width; %make aspect ratio less than unity

end

SquareMetric(k) = aspectRatio; %aspect ratio of box sides

TriangleMetric(k) = Area(k)/boxArea; %filled area vs box area

end

%define some thresholds for each metric

%do in order of circle, triangle, square, rectangle to avoid assigning the

%same shape to multiple objects

isCircle = (CircleMetric < 1.1);

isTriangle = ~isCircle & (TriangleMetric < 0.6);

isSquare = ~isCircle & ~isTriangle & (SquareMetric > 0.9);

isRectangle= ~isCircle & ~isTriangle & ~isSquare; %rectangle isn't any of these

%assign shape to each object

whichShape = cell(N,1);

whichShape(isCircle) = {'Circle'};

whichShape(isTriangle) = {'Triangle'};

whichShape(isSquare) = {'Square'};

whichShape(isRectangle)= {'Rectangle'};

%now label with results

RGB = label2rgb(L);

imshow(RGB); hold on;

Combined = [CircleMetric, SquareMetric, TriangleMetric];

for k=1:N,

%display metric values and which shape next to object

Txt = sprintf('C=%0.3f S=%0.3f T=%0.3f', Combined(k,:));

text( Centroid(k,1)-20, Centroid(k,2), Txt);

text( Centroid(k,1)-20, Centroid(k,2)+20, whichShape{k});

end

Image Analyst
on 19 Feb 2014

Edited: Image Analyst
on 19 Mar 2016

Look at the perimeter squared to area ratio. Use regionprops as shown in my Image Segmentation Tutorial: http://www.mathworks.com/matlabcentral/fileexchange/?term=authorid%3A31862

[EDIT]

See attached demo.

Image Analyst
on 18 Jan 2020

There is NO reason for you to use edge detection on those images. I don't know why all beginners think edge detection is the first step in any image processing problem just because an image has sharp edges in it. It is almost always NOT the best first step. What you need to do is first get a binary image of the shapes and for those computer graphic images you simply want to threshold.

For the monochrome image:

binaryImage = grayScaleImage < 128;

For the color image

% Find out where any pixel is not white.

binaryImage = min(rgbImage, [], 3) < 255;

phaneendra ch
on 22 Nov 2015

kaz
on 25 Apr 2016

Venkatesh A
on 12 Dec 2015

Image Analyst
on 12 Dec 2015

Venkatesh A, you forgot to give the link to your question where you attached your code and image.

If you do that, we can go to your question and tell you how to use imfill(binaryImage, 'holes') to fill holes in your image.

AKHIL RAJAGOPAL
on 23 Apr 2016

I am getting an error at isTriangle = ~isCircle & (TriangleMetric < 0.6); as: Error using & Matrix dimensions must agree.

Please help me solve this problem.

noor jahan m
on 8 Dec 2016

Rahul Chauhan
on 23 Oct 2017

Rahul Chauhan
on 25 Oct 2017

again sir i corrected the function but the code is not working here i am attaching the code and image file know help me.... here is the code :(1)file attached as test.m

(2)minboundrect.m

here is the image: abc.jpg

ty in advance sir for helping me.....

Pavel Vilbik
on 11 Dec 2017

Image Analyst
on 11 Dec 2017

Michelle de Bock
on 28 Dec 2018

Hi Sir,

Is it also possible to classify the direction of the triangle. e.g. left pointing triangle or right pointing triangle? Also classifying the thrid/fourth object in the picture? This is not really a rectangle, but how to separate this from a real rectangle?

Kind regards,

Michelle

Image Analyst
on 28 Dec 2018

Yes, I'm sure you could. Just modify my attached shape recognition demo. Once you have the blob, find its bounding box and centroid with regionprops. Then if the centroid is to the left of the centerline of the bounding box, it's pointing to the left. If it's below, it's pointing up.

For the other object, you'll also have to look for how many vertices it has and then perhaps scale a template to its size and see if enough pixels match to be considered that object. You could also do the template matching method with the triangles if you want. No, I don't have code for that but, being smart engineer, I'm sure you will find it easy to do.

Ahaana Khurana
on 4 Feb 2020

ROMIL can you pls provide the code for SHAPE DETECTION on ahaanakhurana@gmail.com.

Dina Abd El-twab
on 24 Feb 2020

I applied this code to draw a rectangle on the region of interest that i want after taining using faster RCNN .I want to convert the drawn rectangle to be circle in the next step , could you help me please ?

@Image Analyst

Image Analyst

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

Start Hunting!