how to measure the diameter of a circle
7 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
Victor Falola
il 14 Nov 2019
Commentato: Image Analyst
il 9 Nov 2020
im trying to write a script to measure the diameter of this photo and dont know how to go about it.
2 Commenti
Rik
il 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
il 16 Nov 2019
Rik, you put this up in the comments, when I think it should be down in the Answers section.
Risposta accettata
Image Analyst
il 19 Nov 2019
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
0 Commenti
Più risposte (2)
Walter Roberson
il 14 Nov 2019
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 Commenti
Image Analyst
il 16 Nov 2019
Modificato: Image Analyst
il 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.
Image Analyst
il 16 Nov 2019
See attached demo.
6 Commenti
ren chongyu
il 9 Nov 2020
Image Analyst
il 9 Nov 2020
If you don't have a background gradient (like that image), then just skip the background correction.
Vedere anche
Categorie
Scopri di più su Image Data Workflows in Help Center e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!