How to count number of small dots in a picture

I have this picture of small particles in a polymer film. I want to count how many particles in the figure, so that I can have a rough estimation of the particle density. But the image quality is poor, I had a hard time to do it.

,

I have tried several ways to do it, but failed. below is the code. The first method I tried is:

SetDirectory["C:\\Users\\mayao\\documents"]
image = Import["Picture3.jpg"];
imag2 = Binarize[image, {0.0, 0.8}];
cells = SelectComponents[DeleteBorderComponents[imag2], "Count", -400];

circles = ComponentMeasurements[ImageMultiply[image,cells],"Centroid", "EquivalentDiskRadius"}][[All, 2]]; Show[image, Graphics[{Red, Thick, Circle @@ # & /@ circles}]]


Here is what I got:

So it does not count all the particle. Plus, it sometimes take several particle as one.

obl[transit_Image] := (SelectComponents[
MorphologicalComponents[
DeleteSmallComponents@
ChanVeseBinarize[#, "TargetColor" -> Black],
Method -> "ConvexHull"], {"Count", "SemiAxes"},
Abs[Times @@ #2 Pi - #1] < #1/100 &]) &@
transit; GraphicsGrid[{#, obl@# // Colorize,
ImageMultiply[#,
Image@Unitize@
obl@#]} & /@ (Import /@ ("C:\\Users\\mayao\\documents\\" <> # \
& /@ {"Picture1.jpg", "Picture2.jpg", "Picture3.jpg",
"Picture1.jpg"}))]


But it does not recognize the single particles:

Is there any other method to do this task? Thanks a lot for any suggestions.

get the binarize image

 img = Import["http://i.stack.imgur.com/0OJd7.jpg"];


The effect like this:

    big = ImageDemosaic[binimg // ColorConvert[#, "Grayscale"] &,
"RGGB"] // MinDetect // SelectComponents[#, "Count", # > 100 &] &;
DistanceTransform[big] // MaxDetect]) // Colorize


array // Max


1650

Update===========================================================

Use the Closing to optimize the binarize image.

binimg = Closing[LocalAdaptiveBinarize[img, 25], 3]


Then we get the array and verify the effect.

(array = WatershedComponents[GradientFilter[binimg, 2],
DistanceTransform[binimg // ColorNegate] //
MaxDetect]) // Colorize


Or you can like this:

Show[img,
Graphics[{Red,
Point[(array /. 1164 -> 0 //
ComponentMeasurements[#, "Centroid"] &)[[All, 2]]]}]]


So the number of your component is:

array // Max


1340

• Awesome, this is the most accurate result! One question, what does 1164->0 mean? why specifically 1164? – BNHSX Dec 11 '15 at 1:32

You could try something like this

HighlightImage[
ImageTake[img, {100, 400}, {100, 400}],
ImageCorners[
ImageTake[img, {100, 400}, {100, 400}],
1.0,
0.0002,
10
]
]


for visualization and then

Length@
ImageCorners[
ImageTake[img, {100, 400}, {100, 400}],
1.0,
0.0002,
10
]


to get an estimate of the numbers of particles. In any case I would start by selecting a subsection of the image where the lighting is as homogenous as possible. As you can see at the above example there's still a number of false positives and false negatives, and you'll also have to guesstimate the actual area your image is covering in order to calculate the density.

In the post referenced in the comment, the key ideas is

In order to separate the overlapping cells, I extract a set of markers by finding local maximas of the DistanceTransform and use these as markers in WatershedComponents

However exactly following that example verbatim won't work (because there are hyperparameters) and would give something like this:

Here are the preprocessing steps I would take:

s1 = GradientFilter[img, 5] // ImageAdjust;
s2 = Threshold[s1, {"Hard", "Cluster"}];
s3 = FillingTransform[s2];
s4 = DeleteSmallComponents[s3, 30];


The bottom line is that it is tough for a human to delineate the blobs, so it is for a computer. However you can play with the "minimum saliency" threshold as follows:

marker = MaxDetect[DistanceTransform[s4, Padding -> 0] // ImageAdjust,
0.1];

Manipulate[
Method -> {"MinimumSaliency", ms}];
10 < #1 < 1000 && #2 > 4 &];
measures =
ComponentMeasurements[{cells, img}, {"Centroid",
Show[img,
Graphics[{Thickness[0.003], Opacity[0.6, Yellow],
Circle @@ # & /@ (measures[[All, 2, 1 ;; 2]])}],
ImageSize -> 800], {ms, 0, 1}]


To manually to achieve to desired cell separations:

which will look much better:

• Wow! That looks pretty accurate. If, for some reason, this approach tends to either overestimate or underestimate the density and a human eye could do a bit better, one might consider a statistical sampling scheme where the whole image is done with your method and then a random sample of smaller rectangles are counted by eye (small enough so that counting would be easy but large enough to contain say at least 10 particles). The automated estimate would be adjusted by the ratio of the sampled by-eye particles to the sampled counts by the automated method. – JimB Dec 2 '15 at 16:06

The local binarization can help with the uneven lighting. Dilation helps disconnect some particles that remain connected, and DeleteSmallComponents removes small portions caused by noise.

img = Import["http://i.stack.imgur.com/0OJd7.jpg"];
comps = MorphologicalComponents[DeleteSmallComponents[

• The use of MorphologicalComponents will lead the result to smaller obviously. – yode Dec 9 '15 at 5:52
• @yode -- so do the Dilation and DeleteSmallComponents`! – bill s Dec 9 '15 at 15:07