How to define a circle in an image and calculate the percentage it is filled.
1 view (last 30 days)
Show older comments
Jack Newcomb
on 18 Feb 2022
Commented: Image Analyst
on 19 Feb 2022
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!
0 Comments
Accepted Answer
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
1 Comment
More Answers (0)
See Also
Categories
Find more on Detection 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!