2

I have this image enter image description here

I need to count the number of coins in the image but I am having trouble with the overlapping coins, I am using this code to do this:

seg = imread('img.jpg');
lvl = graythresh(seg);
seg = imbinarize(seg,lvl);
seg = imfill(~seg,'holes');
[centres, radii, metric] = imfindcircles(seg, [30, 90]);
imshow(seg);
[l,c] = size(radii);

hold on;

plot(centres(:,1), centres(:,2), 'r*'); 
viscircles(centres, radii, 'EdgeColor', 'b'); 

This the output I got after drawing the circlesenter image description here How can I do this?

Somaye
  • 114
  • 1
  • 3
  • 11
P_Ferreira
  • 363
  • 1
  • 4
  • 21
  • 3
    There's just not enough information left after `imbinarize`. Instead of applying a grayscale threshold, you should look into using specularity to separate the coins from the shadows. – Ben Voigt Jan 03 '18 at 16:53
  • 1
    You could use morphology functions and also `regionprops` or `bwtraceboundary`. please look at `imreconstruct`. I think it's better to erase sub-objects which is small by `bwareaopen`. check this out:(https://stackoverflow.com/questions/26906928/separate-two-overlapping-circles-in-an-image-using-matlab) – Somaye Jan 04 '18 at 08:53

1 Answers1

2

Firstly, you can employ Canny edge detection method to find all edges. Secondly, it's better to use a high value of the sensitivity to find all circular-like shapes and then restrict your conditions to determine the right number of circles. For instance, you can utilize the distance of the circle centers (or correlations of circles). Here's my code to determine the number coins in the given image.

clc;clear all;close all;
%% Preporocessing
input = imread('img.jpg');
input_edges = edge(input,'Canny');
figure;imshow(input_edges);
input_edges=medfilt2(input_edges,[2 2]);% with this filter size, the edges can be strengthened!
figure;imshow(input_edges);
input_edges=bwareaopen(input_edges,130);%remove small edges
%% Applying  circular Hough transform
[centres, radii, metric] = imfindcircles(input_edges, [35, 90],...
    'ObjectPolarity','bright','Sensitivity',0.9,'EdgeThreshold',0.1);
figure;imshow(input_edges);
[l,c] = size(radii);
hold on;
plot(centres(:,1), centres(:,2), 'r*');
viscircles(centres, radii, 'EdgeColor', 'b');
%% Distinguishing circlar shadow
x_centres=centres(:,1);
y_centres=centres(:,2);
num=size(centres,1);
centre_dists = sqrt( bsxfun(@minus,centres(:,1),centres(:,1)').^2 + ...
    bsxfun(@minus,centres(:,2),centres(:,2)').^2 );

% [x_idx,y_idx] =find(centre_dists<50 & centre_dists>0);
% sort(centre_dists(centre_dists<50 & centre_dists>0));
coin_nm=size(centres,1)-0.5*numel(find(centre_dists<50 & centre_dists>0));

The output is obtained as below: output

Hossein Kashiani
  • 330
  • 1
  • 6
  • 18
  • 1
    +100 for your great answer. thank you so much for your great code, excellent. would you please explain about the line : sqrt( bsxfun(@minus,centres(:,1),centres(:,1)').^2 + ... bsxfun(@minus,centres(:,2),centres(:,2)').^2 ); what does @minus mean mainly? – Somaye Jan 06 '18 at 21:09
  • This line calculates the element-wise minus between two points and obtains the distance between two points(centers) for all points simultaneously .You can find more details in this link: https://stackoverflow.com/questions/14483468/calculating-distance-of-all-the-points-in-a-region-with-each-other – Hossein Kashiani Jan 06 '18 at 21:29