Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

To resolve issues starting MATLAB on Mac OS X 10.10 (Yosemite) visit: http://www.mathworks.com/matlabcentral/answers/159016

how to find dent in a circle?

Asked by Sivakumaran Chandrasekaran on 8 May 2013

how to find dent in a circle?

0 Comments

Sivakumaran Chandrasekaran

1 Answer

Answer by Image Analyst on 8 May 2013
Accepted answer

Not exactly sure what you mean by "find" - for example is it just a binary image of the dent alone, or is it an array of all the (row, column) pairs of pixels that comprise the dent. But anyway, you can just get a binary image of the bojects and then use bwconvhull

dentsImage = bwconvhull(binaryImage) - binaryImage; % Get image.
[rows columns] = find(dentsImage); % Get (y,x) coordinates.

4 Comments

Image Analyst on 8 May 2013

You can get the convex hull from regionprops.

Otherwise, here's a demo, for what it's worth:

% Demo to show a use case for the overall convex hull of a group/cluster/collection of binary blobs,
% as well as a demo of two different ways to do the convex hull of the group (mine and Steve's),
% and a way to do convex hull of individual blobs rather than the whole collection of them.
function convexhulldemo()
% Clean up.
clc;
clear all;
close all;
workspace;
% Open up an image -- the standard MATLAB demo image of the coins.
folder = fullfile(matlabroot, '\toolbox\images\imdemos');
filename = fullfile(folder, 'coins.png'); % Standard demo image.
originalImage = imread(filename);
subplot(3, 3, 1);
imshow(originalImage, []);
title('Original Image');
set(gcf, 'units','normalized','outerposition',[0 0 1 1]); % Maximize figure.
% Threshold the image.
binaryImage = originalImage > 100;
subplot(3, 3, 2);
imshow(binaryImage, []);
title('Thresholded Image');
% Take the convex hull of all 10 coins.
[convexHullImage hullVerticesX hullVerticesY] = imConvexHull(binaryImage);
subplot(3, 3, 3);
imshow(convexHullImage, []);
title('Convex Hull of All 10 Coins');
% Show original image with convex hull outline plotted over it.
subplot(3, 3, 4);
imshow(originalImage, []);
hold on;
plot(hullVerticesX, hullVerticesY, 'r');
title('Convex Hull Outline of All 10 Coins');
% Calculate the Euclidean Distance Map.
edmImage = bwdist(binaryImage);
subplot(3, 3, 5);
imshow(edmImage, []);
title('Original EDM Image - note high values in corners');
% Mask it by the convex hull.
edmImage2 = edmImage .* single(convexHullImage);
maxDistance = max(max(edmImage2));
edmImageNorm = edmImage2 / maxDistance;
subplot(3, 3, 6);
imshow(edmImage2, []);
title('Masked EDM Image');
% Get the histogram of the masked EDM Image.
[counts gls] = imhist(edmImageNorm, 40);
maxY = max(counts(2:end));
subplot(3, 3, 7);
bar(gls, counts);
ylim([0 maxY * 1.05]);
xlim([0 1]);
title('Histogram of Masked EDM Image');
% Skeletonize it so that we get just the ridgelines of the EDM.
skeletonImage = edmImage2>0;
skeletonImage2 = bwmorph(skeletonImage, 'skel', inf);
subplot(3, 3, 8);
imshow(skeletonImage2, []);
title('Skeleton of the Masked EDM Image');
% Multiply the masked EDM by the skeleton so we have ONLY ridgeline pixels.
ridgeImage = (edmImage2 .* single(skeletonImage2)) / maxDistance;
[counts gls] = imhist(ridgeImage, 40);
maxY = max(counts(2:end));
subplot(3, 3, 9);
bar(gls, counts);
ylim([0 maxY * 1.05]);
xlim([0 1]);
title('Histogram of only the Ridgelines of the Masked EDM Image');
%-------------------------------------------------------------
% Now let's try Steve Eddins's function.
hFig2 = figure; % Open up new, separate figure window.
set(gcf, 'Position', 0.75 * get(0, 'ScreenSize')); % Maximize figure.
CenterFigure(hFig2);
% Open up an image.
subplot(2, 3, 1);
imshow(originalImage, []);
title('Original Image');
% Cut some notches in the coins so we can see the effect of individual convex hulls.
notchedCoinsImage = originalImage;
notchedCoinsImage(40:60, 40:82) = 65;
notchedCoinsImage(20:40, 130:180) = 65;
notchedCoinsImage(60:80, 200:250) = 65;
notchedCoinsImage(140:160, 80:130) = 65;
notchedCoinsImage(110:130, 160:210) = 65;
notchedCoinsImage(60:90, 100:120) = 65;
notchedCoinsImage(140:180, 230:240) = 65;
notchedCoinsImage(100:140, 30:40) = 65;
notchedCoinsImage(100:140, 30:40) = 65;
notchedCoinsImage(200:220, 80:140) = 65;
subplot(2, 3, 2);
imshow(notchedCoinsImage, []);
title('Notched Coins Image');
% Threshold the image.
binaryImage2 = notchedCoinsImage > 100;
subplot(2, 3, 3);
imshow(binaryImage2, []);
title('Thresholded Image');
% Take the convex hull using Steve's function (returns CH of all 10 coins.)
convexHullImage = bwconvhull(binaryImage2);
subplot(2, 3, 5);
imshow(convexHullImage, []);
title('Convex Hull of All 10 Coins');
% Label the image.
labeledImage = bwconncomp(binaryImage2);
% Call regionprops
blobMeasurements = regionprops(labeledImage, 'all');
numberOfBlobs = length(blobMeasurements);
[rows columns] = size(binaryImage2);
% Get convex hull of each blob in the image independently.
% It would sure be nice if this were easier.  
% The "ConvexImage" returned by regionprops doesn't return full size images, just subimages.
% So if we want the convex hull of each blob independently, we have to loop over all blobs
% getting the CH for each blob one at a time, then adding it to the cumulative CH image.
CHofEachBlob = false(rows, columns);
for blob = 1 : numberOfBlobs
	CHofThisBlob = [blobMeasurements(blob).ConvexHull];
	CHImageForThisBlob = poly2mask(CHofThisBlob(:,1), CHofThisBlob(:,2), rows, columns);
	CHofEachBlob = CHofEachBlob | CHImageForThisBlob;
end
subplot(2, 3, 6);
imshow(CHofEachBlob, []);
title('Convex Hull of each coin independently');
return;  % End of the main convexhulldemo() routine.
%-------------------------------------------------------------------------------------
% Mark Hayworth's version to get the convex hull of the entire group of blobs.
function [convexHullImage hullVerticesX hullVerticesY] = imConvexHull(binaryImage)
	[rows columns] = size(binaryImage);
	boundaries = bwboundaries(binaryImage);	
	numberOfBlobs = size(boundaries, 1);
	blobVertices = [];
	for k = 1 : numberOfBlobs
		thisBoundary = boundaries{k};
		blobVertices = [blobVertices; thisBoundary];
		hold on;
		plot(thisBoundary(:,2), thisBoundary(:,1), 'g', 'LineWidth', 2);
	end
	hullIndexes = convhull(blobVertices(:,2), blobVertices(:,1));
	hullVerticesX = blobVertices(hullIndexes,2);
	hullVerticesY = blobVertices(hullIndexes,1);
	convexHullImage = poly2mask(hullVerticesX, hullVerticesY, rows, columns);	
	return;
	
	
%-------------------------------------------------------------------------------------
% Steven L. Eddins's version to get the convex hull of the entire group of blobs.
function out = bwconvhull(in)
%BWCONVHULL Convex hull of binary image
%   bw2 = bwconvhull(bw) computes the convex hull of the input binary image, bw,
%   and returns it as another binary image, bw2.  bw2 has the same size as bw.
%
%   bw must be two-dimensional.
%   Steven L. Eddins
%   Copyright 2009 The MathWorks, Inc.
if ~islogical(in)
    in = in ~= 0;
end
% Convert input from logical to uint8.  This will cause regionprops to treat
% it as a label matrix, and so every foreground pixel will be treated as part of
% the same object.
in = uint8(in);
s = regionprops(in, 'BoundingBox', 'ConvexImage');
% regionprops returns an image only big enough to just cover the bounding box of
% the "object."  Compute the row and column indices corresponding to that
% bounding box.
m = s.BoundingBox(4);
n = s.BoundingBox(3);
r1 = s.BoundingBox(2) + 0.5;
c1 = s.BoundingBox(1) + 0.5;
r = (1:m) + r1 - 1;
c = (1:n) + c1 - 1;
out = false(size(in));
out(r,c) = s.ConvexImage;
%-------------------------------------------------------------------------------------
% Function to center a figure on the screen (if it's not maximized).
function CenterFigure(handleToFigure)
	% The figure Position property
	% does not include the window borders, so this example uses a width of 5 pixels
	% on the sides and bottom and 30 pixels on the top.
	borderWidth = 5;
	titleBarWidth = 30;
	% Ensure root units are pixels and get the size of the screen:
	set(0, 'Units', 'pixels');
	set(handleToFigure, 'Units', 'pixels');
	% Get the screen size in pixels.
	screenSize = get(0,'ScreenSize');
	% Get the size of the window.
	initialFigurePosition = get(handleToFigure, 'Position');
	% Create an array that will center it.
	centeredX = (screenSize(3) - initialFigurePosition(3)) / 2;
	centeredY = (screenSize(4) - initialFigurePosition(4)) / 2;
	centeredPosition  = [centeredX,... 
		centeredY,...
		initialFigurePosition(3),...
		initialFigurePosition(4)];
	set(handleToFigure, 'Position', centeredPosition);
	return; % from CenterFigure()
	

Thank you so much image analyst. I am getting error in s.BoundingBox(4);Field reference for multiple structure elements that is followed by more reference blocks is an error.What does it indicates. is there any problem in the input image which i gave.

Image Analyst on 9 May 2013

I just ran it again and it works fine. What error did you get? You probably modified it so that it doesn't work.

Image Analyst

Contact us