% Identifying Circles From An Image
% Using Image Processing Toolbox
% In MATLAB 2025

function displayImage(image, name)
    figure,
    imshow(image, 'InitialMagnification', 'fit') % will fill window size
    title(name)
end

colored_image = imread("pillsetc.png");
% colored_image = imread("shapes.png"); % test custom image 
displayImage(colored_image, "Original Image")

% PREPROCESS THE IMAGE
% Step 1: Convert to black and white

grayed = im2gray(colored_image); % turns all colors to shade of gray
bw = imbinarize(grayed);         % turns shade of gray to black or white
displayImage(bw, "Black and White Image")

% Step 2: remove unwanted pixels and fix empty space

minSize = 30;
bw = bwareaopen(bw,minSize); % remove objects less than 30 pixels
displayImage(bw, "Filtered Image")

% THIS SECTION IS USED WHEN USING PILLSETC.PNG 
% can remove when testing custom image 
se = strel("disk",2);
bw = imclose(bw,se); % fill small gaps and holes
displayImage(bw, "Unfilled Fixed Image")
% END OF SECTION 

bw = imfill(bw,"holes"); % fill any holes in objects
displayImage(bw, "Filled Fixed Image")

% Step 3: find boundaries of the shapes
% in a binary image background is 0 and object is 1

[B,L] = bwboundaries(bw,"noholes");
% B contains coordinates of the edges of the object
% L contains a matrix of the entire image but instead of pixels it has 
% numbers where 0 is the background and then 1, 2, 3 and so on for each 
% different object

% overlay some color over the white while maintaining the boundary
labeled_image = label2rgb(L,@jet,[.5 .5 .5]);
displayImage(labeled_image, 'Objects with Boundaries in White')
hold on
for k = 1:length(B)
  boundary = B{k};
  plot(boundary(:,2),boundary(:,1),"w",LineWidth=2)
end

% *** START CODING HERE ***
% FIND SHAPES IN IMAGE
% Step 1: find circles
stats = regionprops(L,"Circularity","Centroid");
% Circularity: how circular the object is, close to 1 for circle
% Centroid: center point of the object

% range 0 to 1 by how perfect the circle is
% lower threshold to allow more objects to be a circle
% increase threshold to be more strict on what to classify as a circle
threshold = 0.95; 

% loop through each object and compare its circularity to the threshold
for k = 1:length(B)
    boundary = B{k};
    circ_value = stats(k).Circularity;

    if circ_value > threshold
        shape = "Circle";
    else
        shape = "Other";
    end

    centroid = stats(k).Centroid;
    text(boundary(1, 2)-35, boundary(1, 1)+13, shape, Color="y", FontSize=14, FontWeight="bold")
end
    title("Circle Shapes")




