MATLAB Answers

0

how to measure the diameter of a circle

Asked by Victor Falola on 14 Nov 2019 at 23:20
Latest activity Answered by Image Analyst
on 19 Nov 2019 at 16:59
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 at 23:44
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 at 15:06
Rik, you put this up in the comments, when I think it should be down in the Answers section.

Sign in to comment.

3 Answers

Answer by Walter Roberson
on 14 Nov 2019 at 23:52

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

where?
Image Analyst
on 16 Nov 2019 at 14:32
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.

Sign in to comment.


Answer by Image Analyst
on 19 Nov 2019 at 16:59

Try this code:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clearvars;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
%=======================================================================================
% Have user browse for a file, from a specified "starting folder."
% For convenience in browsing, set a starting folder from which to browse.
startingFolder = pwd; % or 'C:\wherever';
if ~exist(startingFolder, 'dir')
% If that folder doesn't exist, just start in the current folder.
startingFolder = pwd;
end
% Get the name of the file that the user wants to use.
defaultFileName = fullfile(startingFolder, 'n*.*');
[baseFileName, folder] = uigetfile(defaultFileName, 'Select a file');
if baseFileName == 0
% User clicked the Cancel button.
return;
end
fullFileName = fullfile(folder, baseFileName);
rgbImage = imread(fullFileName);
% rgbImage = decorrstretch(rgbImage,'tol',0.01);
% imwrite(rgbImage, 'test.png');
% Get the dimensions of the image.
[rows1, columns1, numberOfColorChannels1] = size(rgbImage)
% Display the original image.
subplot(2, 2, 1);
imshow(rgbImage, []);
axis('on', 'image');
caption = sprintf('Original Color Image "%s"', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0.05 1 0.95]);
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by Image Analyst', 'NumberTitle', 'Off')
% Do a color segmentation
[mask,maskedRGBImage] = createMask(rgbImage);
% Display the mask image.
subplot(2, 2, 2);
imshow(mask, []);
axis('on', 'image');
caption = sprintf('Color Segmentation');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
% Delete blobs touching the border.
mask = imclearborder(mask);
% Fill holes, and take the largest blob.
subplot(2, 2, 3);
mask = imfill(mask, 'holes');
mask = bwareafilt(mask, 1);
% Display the image.
subplot(2, 2, 3);
imshow(mask, []);
axis('on', 'image');
title('Final Mask Image', 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Measure the equivalent circular diameter.
props = regionprops(mask, 'EquivDiameter', 'Centroid');
% Plot these over the upper left image.
subplot(2, 2, 1);
hold on;
xCentroid = props.Centroid(1)
yCentroid = props.Centroid(2)
diameter = props.EquivDiameter
viscircles([xCentroid, yCentroid], props.EquivDiameter/2);
plot(xCentroid, yCentroid, 'r+', 'LineWidth', 2, 'MarkerSize', 100);
% Mask the image using bsxfun() function to multiply the mask by each channel individually.
maskedRgbImage = bsxfun(@times, rgbImage, cast(mask, 'like', rgbImage));
% Display the image.
subplot(2, 2, 4);
imshow(maskedRgbImage, []);
axis('on', 'image');
caption = sprintf('Masked Image. Spot Diameter = %.2f', diameter);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0.05 1 0.95]);
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by Image Analyst', 'NumberTitle', 'Off')
function [BW,maskedRGBImage] = createMask(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder app. The colorspace and
% range for each channel of the colorspace were set within the app. The
% segmentation mask is returned in BW, and a composite of the mask and
% original RGB images is returned in maskedRGBImage.
% Auto-generated by colorThresholder app on 19-Nov-2019
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.000;
channel1Max = 0.175;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.366;
channel2Max = 1.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.512;
channel3Max = 1.000;
% Create mask based on chosen histogram thresholds
sliderBW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end
0001 Screenshot.png

  0 Comments

Sign in to comment.


Answer by Image Analyst
on 16 Nov 2019 at 15:05

See attached demo.
0000 Screenshot.png

  0 Comments

Sign in to comment.