How to define a circle in an image and calculate the percentage it is filled.

1 view (last 30 days)
I'm looking to calculate the percentage of each dotted circles that is filled by the red spots within the attached image. Also attached is a code I have previously ceated that calculates the size of the red spots by filtering the image and using region props, as well as the size of the dotted circle by defining its diameter. However, this only provides a size comparison between the two circles regardless of their location. I want to alter the code to find the percentage of the black dotted circle that is covered by the red. My idea was to define the area of the dotted circles and determine the area of each regionprop within that circle, but I am struggling to do so. Any guidence would be greatly appreciated.
Thank You!

Accepted Answer

Simon Chan
Simon Chan on 19 Feb 2022
Some modification from your code as follows:
(1) Use your code to detect the red circles
(2) Generate convex hull image to calculate the centroid of each red circle
(3) Find the dotted circles by thresholding
(4) Separate the entire image into 3 parts
(5) Find the dots belongs to the dotted circle and fit a circle
(6) Generate a mask from the fitted circle
(7) Union red circle mask and the dotted circle mask, gives your required percentage.
clc; close all;
img = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/899000/circlesize.jpg');
[R,G,B] = imsplit(img);
gray_img = rgb2gray(img);
xz_red = imsubtract(R,gray_img);
xz_red = imadjust(xz_red,stretchlim(xz_red),[]);
bw = im2bw(xz_red);
%% Use your code to detect the red circles above
bw1 = bwconvhull(bw,'object'); % Generate convex hull image
s1 = regionprops(bw1);
centroid = cat(1,s1.Centroid); % Find the centroid of each red circle
%% Find the dotted circles
red_range = [60,120];
mask1 = R>red_range(1) & R<red_range(2);
bw11 = imclearborder(mask1); % Clear border
bw12 = bwareaopen(bw11,50); % Remove small objects
%
[Ny,Nx,Nc] = size(img);
x_coord = [1;round(centroid(1:2,1)+diff(centroid(:,1))/2);Nx]; % Separate into 3 pictures
t = tiledlayout(2,2,'TileSpacing','compact','Padding','compact');
%
for k = 1:length(x_coord)-1
xstart = x_coord(k); % Start x-coordinates
xend = x_coord(k+1); % End x-coordinates
regionA = bw1(:,xstart:xend); % Extract the red circle
regionB = bw12(:,xstart:xend); % Extract the dotted circle
nexttile
imshow(img(:,xstart:xend,:),[]); % Showing original image
hold on;
[row,col] = find(bwperim(regionA)); % For display purpose only
plot(col,row,'g.','MarkerSize',3); % Display the peimeter of red circle
%% Fit a circle for the dotted circle
[row,col] = find(regionB); % Find all white dots belongs to the dotted circle
row = row(:);
col = col(:);
a = [row col ones(size(row))]\(-(row.^2+col.^2));
yCircle = -.5*a(1); % y-center of fitted circle
xCircle = -.5*a(2); % x-center of fitted circle
rCircle = sqrt((a(1)^2+a(2)^2)/4-a(3)); % radius of fitted circle
%
[Nyroi,Nxroi] = size(regionB);
[xx,yy] = meshgrid(1:Nxroi,1:Nyroi);
mask = false(Nyroi,Nxroi);
mask = mask | hypot(xx - xCircle, yy - yCircle) <= rCircle; % Creating a mask for the fitted circle
insideA = sum(regionA & mask)/sum(mask); % Calculate the percentage
rectangle('Position',[xCircle-rCircle yCircle-rCircle, 2*rCircle, 2*rCircle],'Curvature',[1 1]); %Display only
title(sprintf('Image #%d, Percentage = %.1f %%',k,100*insideA));
hold off;
end

More Answers (0)

Products


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!