Particle size calculation from given image

80 views (last 30 days)
I want to calculate sizes of each particle from the input image using image processing technique.

Answers (2)

Thiago Henrique Gomes Lobato
The size for each particle is a task which is extremely hard to automatize, you will always get some error due to different light conditions, particle distribution, overlapping particles etc. A problem that is way more tractable and realistic is to calculate the rock size distribution, which will give you how the sizes are statistically distributed in the image. I took some inspirations from Image Analyst tutorial and made a code that could be used as a start for you to fine tune it. In this way you could at least get a estimation of particle size distribution:
I = imread('image.jpeg');
Ibinary = rgb2gray(I) > 150; % Try different values for your problem
Ibinary = imfill(Ibinary, 'holes');
C = 0.008; % Conversion factor m/pixel. This was a guess, you should be able to find the real one
[labeledImage, numberOfBlobs] = bwlabel(Ibinary);
blobMeasurements = regionprops(labeledImage, 'Centroid','EquivDiameter'); % I believe equivalent diameter is a good way to measure size,
% you can also check different metrics
% Get equivalent diameter
EquivDiameter = [blobMeasurements.EquivDiameter];
ValidDia = find(EquivDiameter>10); % Some empiric threshold
blobMeasurements = blobMeasurements(ValidDia);
EquivDiameter = EquivDiameter(ValidDia);
% Probability estimation of size
figure,histogram(EquivDiameter*C,'Normalization','probability'),xlabel('Size[m - uncalibrated]'),ylabel('Probability')
% Display some particles
figure,imshow(Ibinary); hold on
% Display areas on image
for idx = 1:2: length(ValidDia) % Loop through all blobs.
Centroid = [blobMeasurements(idx).Centroid(1), blobMeasurements(idx).Centroid(2)];
DiamSize = ['Diam. = ', num2str((EquivDiameter(idx)*C))];
text(Centroid(1), Centroid(2), DiamSize, 'Color', 'c');
viscircles(Centroid,EquivDiameter(idx)/2);
end
  3 Comments
Thiago Henrique Gomes Lobato
Edited: Thiago Henrique Gomes Lobato on 10 May 2020
The longest size of the particle can be achieve with the MajorAxisLength property
regionprops(labeledImage, 'Centroid','EquivDiameter','MajorAxisLength');
For getting the distribution one nice thing you can consider is that you don't need to get all particles right, but rather only a subset of them. As I said in the initial answer it will be extremely difficult to find all and I don't believe this shouldn't be your goal.
In order to improve the results you can consider that the main problem of the rocks is that they overlap too much. So threshold methods like Otsu (graythresh(Iobrcbr)) will mostly likely not work, neither trying to close too much of the holes. I believe the best way to get this, in a binary segmentation paradigm, is to use a very high binary treshold or high amount of erosion in order to separate the intersection as much as possible and them rely in the subset assumptions, so even though you may remove some rocks the result will still remain reasonable. Also note the idx = 1:2: length(ValidDia). To plot all blobs remove this 2, I initially let it there so the image wouldn't be too much filled.
Vikrant Pratap
Vikrant Pratap on 10 May 2020
Please help with plotting MajorAxisLength on the binary image.

Sign in to comment.


Image Analyst
Image Analyst on 10 May 2020
Since your particles can't be segmented by itnensity, I think you need to look at granulometry. Wikipedia Granulometry

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!