Skip to main content

image processing - 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.


particle in film - grayscale, particle in film - color


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: enter image description here


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


I read another method from a thread here, the code is:


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:


enter image description here



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



Answer



get the binarize image


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

enter image description here


The effect like this:


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

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

enter image description here


Then your number is


array // Max


1650




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


Use the Closing to optimize the binarize image.


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

enter image description here


Then we get the array and verify the effect.


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


enter image description here


Or you can like this:


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

enter image description here


So the number of your component is:


array // Max



1340



Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

list manipulation - Selecting multiple columns from a matrix?

Sample data: data = { {{2013, 1, 1}, 24.13, 167.67, 231.82}, {{2013, 1, 2}, 32.15, 170.92, 225.99}, {{2013, 1, 3}, 35.43, 172.68, 221.67}, {{2013, 1, 4}, 36.73, 173.05, 218.32}, {{2013, 1, 5}, 58.19, 165.96, 197.05}, {{2013, 1, 6}, 69.99, 163.50, 187.52}, {{2013, 1, 7}, 71.37, 154.21, 175.58}, {{2013, 1, 8}, 72.51, 149.66, 163.25}}; I want a DateListPlot with three graphs, so for a matrix formed by columns 1 and 2, one for columns 1 and 3, and 1 for columns 1 and 4. At the moment I'm using this code: data2 = Transpose[{data[[All, 1]], data[[All, 2]]}]; data3 = Transpose[{data[[All, 1]], data[[All, 3]]}]; data4 = Transpose[{data[[All, 1]], data[[All, 4]]}]; DateListPlot[{data2, data3, data4}, Joined -> True, Filling -> {3 -> {1}}] but I have a hunch that this can be done more efficiently. I don't like the Transpose s in particular. Any ideas? edit (for extra credit) What if I need to multiply the second column by 2, which in my solution is simp...

plotting - How to draw some 2D curves in a 3D plot?

I want to plot several 2D curves ( Sin[x] at y=0 , Cos[x] at y=1 ) in a 3D plot, what function should i use? f[x_, y_] := Piecewise[{{0, y 0}, {Sin[x], y == 0}}] g[x_, y_] := Piecewise[{{0, y 1}, {Cos[x], y == 1}}] Plot3D[{f[x, y], g[x, y]}, {x, 0, 10}, {y, 0, 10}] doesn't work. Any ideas? Answer ParametricPlot3D[{{Sin[u], 0, u}, {Cos[u], 1, u}}, {u, 0, 20}, BoxRatios -> 1, PlotRange -> {{-2, 2}, {-.5, 2}, {0, 20}}] === update - general thoughts === I've seen the comments to this question and a few other approaches to the waterfall (or wire) plot are given in this question: Plotting several functions . Also I cannot not mention one of my favorite Mathematica blogs - Archery with this post on the story of discovery of 1st pulsar and an its infamous graphics - code is given in the post: