MATLAB Answers

how to find dent in a circle?

how to find dent in a circle?

  0 Comments

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

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.

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


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

MATLAB Academy

New to MATLAB?

Learn MATLAB today!