How to detect square shape in a photo
50 次查看(过去 30 天)
显示 更早的评论
Hi
I want to detect a square in a binary image that contains many shapes like circles , triangle , ... whit a different size
we have 2 rules to who to solve this question : 1- we can't compare any shape to detect a square . for example we can't have a sample square image and analyses main image and find witch shape is like a square . 2- main image is totally generated by random , so we haven't any location or coordinate of shapes .
0 个评论
回答(4 个)
Image Analyst
2011-9-21
Use bwconncomp, and regionprops. Then look at the perimeter squared to area ratio. It will pick them right out, especially for perfect shapes such as in your example. See my blobsDemo ( http://www.mathworks.com/matlabcentral/fileexchange/?term=authorid%3A31862 ) if you need an example of how to use regionprops to do filtering.
2 个评论
Paul Safier
2019-7-19
What're your thoughts on using bwconncomp/regionprops (as in your demo) versus imfindcircles for finding circles specifically? Do you have experience indicating one algorithm/approach is better or more robust than the other?
Image Analyst
2019-7-19
They're kind of unrelated. With bwconncomp/regionprops you need to already have used some other algorithm to segment the image into blobs, which should be the circles you want. Then bwconncomp/regionprops just finds the centers, diameters, and shapes of those blobs.
imfindcircles() uses a different algorithm - I think it's based on a Hough transform but then still has to threshold that to find likely circular regions. imfindcircles() will only give you centers and ECD (Equivalent Circular Diameters). regionprops can give you those plus more, like intensity within the circles, exactly how circular they are (like with "Solidity" or by taking the ratio of perimeter ^2 / (4*pi*area)). With imfindcircles, you can't get shapes or outlines of the regions it found, but with a regular segmentation method (e.g. thresholding) you can, with bwboundaries() for example.
Image Analyst
2011-9-22
Well you're in luck. It turns out I already have a demo I've written long ago do do just this. It should work with minor adaptations:
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;
% Change the current folder to the folder of this m-file.
if(~isdeployed)
cd(fileparts(which(mfilename)));
end
% Ask user if they want to use a demo image or a different image.
message = sprintf('Do you want use a standard demo image,\nOr pick one of your own?');
reply2 = questdlg(message, 'Which Image?', 'Demo','I will pick a different one...', 'Demo');
if isempty(reply2)
% They clicked the red x to close without clicking a button.
return;
end
% Open an image.
if strcmpi(reply2, 'Demo')
% Read standard MATLAB demo image.
message = sprintf('Which demo image do you want to use?');
selectedImage = questdlg(message, 'Which Demo Image?', 'Square', 'Triangle', 'Circle', 'Circle');
if strcmp(selectedImage, 'Circle')
fullImageFileName = 'Circle.jpg';
elseif strcmp(selectedImage, 'Square')
fullImageFileName = 'Square.jpg';
else
fullImageFileName = 'Triangle.jpg';
end
else
% They want to pick their own.
% Browse for the image file.
[baseFileName, folder] = uigetfile('*.*', 'Specify an image file');
fullImageFileName = fullfile(folder, baseFileName);
if folder == 0
return;
end
end
% Check to see that the image exists. (Mainly to check on the demo images.)
if ~exist(fullImageFileName, 'file')
message = sprintf('This file does not exist:\n%s', fullImageFileName);
uiwait(msgbox(message));
return;
end
% Read in image into an array.
[rgbImage storedColorMap] = imread(fullImageFileName);
[rows columns numberOfColorBands] = size(rgbImage);
% If it's monochrome (indexed), convert it to color.
% Check to see if it's an 8-bit image needed later for scaling).
if strcmpi(class(rgbImage), 'uint8')
% Flag for 256 gray levels.
eightBit = true;
else
eightBit = false;
end
if numberOfColorBands == 1
if isempty(storedColorMap)
% Just a simple gray level image, not indexed with a stored color map.
% Create a 3D true color image where we copy the monochrome image into all 3 (R, G, & B) color planes.
rgbImage = cat(3, rgbImage, rgbImage, rgbImage);
else
% It's an indexed image.
rgbImage = ind2rgb(rgbImage, storedColorMap);
% ind2rgb() will convert it to double and normalize it to the range 0-1.
% Convert back to uint8 in the range 0-255, if needed.
if eightBit
rgbImage = uint8(255 * rgbImage);
end
end
end
% Display the original image.
subplot(2, 2, 1);
imshow(rgbImage);
set(gcf, 'Position', get(0,'Screensize')); % Enlarge figure to full screen.
set(gcf,'name','Demo by ImageAnalyst','numbertitle','off')
drawnow; % Make it display immediately.
if numberOfColorBands > 1
title('Original Color Image', 'FontSize', fontSize);
grayImage = rgbImage(:,:,1);
else
caption = sprintf('Original Indexed Image\n(converted to true color with its stored colormap)');
title(caption, 'FontSize', fontSize);
grayImage = rgbImage;
end
% Display it.
subplot(2, 2, 2);
imshow(grayImage, []);
title('Grayscale Image', 'FontSize', fontSize);
% Binarize the image.
binaryImage = grayImage < 100;
% Display it.
subplot(2, 2, 3);
imshow(binaryImage, []);
title('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 numberOfObjcts] = bwlabel(binaryImage);
blobMeasurements = regionprops(labeledImage,'Perimeter','Area');
% for square ((a>17) && (a<20))
% for circle ((a>13) && (a<17))
% for triangle ((a>20) && (a<30))
circularities = [blobMeasurements.Perimeter.^2] ./ (4 * pi * [blobMeasurements.Area])
% Say what they are
for blobNumber = 1 : numberOfObjcts
if circularities(blobNumber) < 1.19
message = sprintf('The circularity of object #%d is %.3f, so the object is a circle',...
blobNumber, circularities(blobNumber));
elseif circularities(blobNumber) < 1.53
message = sprintf('The circularity of object #%d is %.3f, so the object is a square',...
blobNumber, circularities(blobNumber));
else
message = sprintf('The circularity of object #%d is %.3f, so the object is a triangle',...
blobNumber, circularities(blobNumber));
end
uiwait(msgbox(message));
end
2 个评论
Youcef Le prince
2021-12-15
hi ther
can you help me with thaht?
I have un image content des farme geometrique simple
cirle rectengles triangle
i want to dectect them any way :color the sme or affiche le nombre of the same farme ex : nombre rectengle 2,nombre circle 3 . nombre triangle 1...........
Image Analyst
2021-12-15
@Youcef Le prince Since that 10 year old answer I now have two shape recognition demos. I think the one based on using findpeaks() to count the number of vertices may be more reliable than the one above. They are attached. Also see this post:
Walter Roberson
2011-9-21
Can the shapes overlap (or even just touch), or are they always distinct? Will the squares always be perpendicular to the axes, or might they be rotated? Are you allowed to use the Image Processing Toolbox?
I suggest you start by looking at imlabel() and regionprops()
0 个评论
Florin Neacsu
2011-9-21
Hi,
What makes a square a square and not a circle, triangle or even rectangle? Think of an unique characteristic to describe a square. Then create a metric (maybe a weighted ratio?) that will allow you to identify squares.
After that, as Walter suggested, use imlabel and regionprops.
Regards, Florin
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 3-D Volumetric Image Processing 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!