how to measure the diameter of a circle
Show older comments
im trying to write a script to measure the diameter of this photo and dont know how to go about it.

2 Comments
Rik
on 14 Nov 2019
I think I would go for an iterative approach where I would increase the circle radius. For every iteration, check if moving the center would decrease the number of white pixels inside the circle. When the number of white pixels starts to increase dramatically, stop the process.
What would be a good cutoff for that increase probably depends on the seed location and how much noise you expect inside the circle.
Once you have the circle, calculating the diameter is of course trivial.
Image Analyst
on 16 Nov 2019
Rik, you put this up in the comments, when I think it should be down in the Answers section.
Accepted Answer
More Answers (2)
Walter Roberson
on 14 Nov 2019
1 vote
bwareafilt to remove the small noise objects inside the circle. Invert the result so the open area becomes white. bwareafilt for the largest area. Now regionprops equivalent diameter.
5 Comments
Victor Falola
on 15 Nov 2019
Rik
on 15 Nov 2019
Have you tried reading the documentation pages that Walter mentioned?
Victor Falola
on 16 Nov 2019
Image Analyst
on 16 Nov 2019
Edited: Image Analyst
on 16 Nov 2019
Something like (untested):
binaryImage = bwareafilt(~binaryImage);
binaryImage = imfill(binaryImage, 'holes');
binaryImage = bwareafilt(binaryImage, 1);
props = regionprops(binaryImage, 'EquivDiameter');
diameter = props.EquivDiameter
There might be a better way. I highly doubt that the best first step was to take an edge image. Can you post the original gray scale image.
Victor Falola
on 19 Nov 2019
Image Analyst
on 16 Nov 2019
1 vote
See attached demo.

6 Comments
ren chongyu
on 29 Oct 2020
Its very good but how about this pic, the contrast ratio of the picture is low and I cant use your method to determine the circle center and diameter
Image Analyst
on 30 Oct 2020
ren, you need to create a background image and divide by it. See attached.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
imtool close all; % Close all imtool figures if you have the Image Processing Toolbox.
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
% Check that user has the Image Processing Toolbox installed.
hasIPT = license('test', 'image_toolbox');
if ~hasIPT
% User does not have the toolbox installed.
message = sprintf('Sorry, but you do not seem to have the Image Processing Toolbox.\nDo you want to try to continue anyway?');
reply = questdlg(message, 'Toolbox missing', 'Yes', 'No', 'Yes');
if strcmpi(reply, 'No')
% User said No, so exit.
return;
end
end
%===============================================================================
% Read in a standard MATLAB color demo image.
folder = pwd;
baseFileName = 'rsz_122.png';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
% 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.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(fullFileName);
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows, columns, numberOfColorBands] = size(grayImage);
if numberOfColorBands > 1
grayImage = rgb2gray(grayImage);
end
% Display the original color image.
subplot(2, 3, 1);
imshow(grayImage);
axis on;
title('Original Image', 'FontSize', fontSize);
impixelinfo;
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'Outerposition', [0, 0.1, 1, 0.9]);
subplot(2, 3, 2);
imhist(grayImage);
grid on;
title('Histogram of Gray Scale Image', 'FontSize', fontSize);
% Illumination is not the same from top to bottom so we need to do a background correction:
verticalProfile = mean(grayImage(:, 1:100), 2);
% Smooth profile a bit with movmean.
verticalProfile = movmean(verticalProfile, 9);
subplot(2, 3, 3);
plot(verticalProfile, 'b-', 'LineWidth', 2);
grid on;
xlabel('Row', 'FontSize', fontSize);
ylabel('Mean Gray Level', 'FontSize', fontSize);
% Fit a cubic through it
coefficients = polyfit(1 : rows, verticalProfile, 3);
yFit = polyval(coefficients, 1 : rows);
hold on;
plot(yFit, 'r-', 'LineWidth', 2);
legend('Smoothed Vertical Profile', 'Fit', 'Location', 'southeast');
title('Vertical Profile Through Background', 'FontSize', fontSize);
hold off;
% Normalize 0-1 so we can divide by it.
yFit = yFit / max(yFit);
% Create background image.
backgroundImage = repmat(yFit', [1, columns]);
subplot(2, 3, 4);
imshow(backgroundImage);
axis on;
title('Background Image', 'FontSize', fontSize);
impixelinfo;
% Divide the original gray scale image by the background image
grayImage = uint8(double(grayImage) ./ backgroundImage);
% Update the histogram.
subplot(2, 3, 2);
imhist(grayImage);
grid on;
title('Histogram of Gray Scale Image', 'FontSize', fontSize);
% Get the binaryImage
binaryImage = grayImage >= 97; % imbinarize(grayImage);
% There is a white frame around it. Get rid of that.
binaryImage = imclearborder(binaryImage);
% Display the image.
subplot(2, 3, 5);
imshow(binaryImage);
axis on;
title('Initial Binary Image', 'FontSize', fontSize);
subplot(2, 3, 6);
% It seems to be one connected giant blob.
% Use morphological opening to dissolve the tendrils that
% connect the large circular blob to all the other noise lines.
se = ones(5);
binaryImage = imopen(binaryImage, se);
binaryImage = bwareafilt(binaryImage, 1);
binaryImage = bwareafilt(binaryImage, 1);
imshow(binaryImage);
binaryImage = imfill(binaryImage, 'holes');
imshow(binaryImage);
binaryImage = bwareafilt(binaryImage, 1);
imshow(binaryImage);
axis('on', 'image');
% Now make the measurements.
props = regionprops(binaryImage, 'EquivDiameter', 'Centroid');
diameter = props.EquivDiameter
xCenter = props.Centroid(1);
yCenter = props.Centroid(2);
% Show the circle over the image
viscircles([xCenter, yCenter], diameter/2);
hold on;
plot(xCenter, yCenter, 'r+', 'LineWidth', 2, 'MarkerSize', 50);
caption = sprintf('Filled Binary Image. The equivalent diameter is %f pixels.', diameter);
title(caption, 'FontSize', fontSize);
message = sprintf('The equivalent diameter is %f pixels.', diameter);
msgbox(message);

ren chongyu
on 30 Oct 2020
Thank you very much sir, you saved my life : )
ren chongyu
on 30 Oct 2020
you are such a genius
ren chongyu
on 9 Nov 2020
Image Analyst
on 9 Nov 2020
If you don't have a background gradient (like that image), then just skip the background correction.
Categories
Find more on Image Processing Toolbox in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
