Particle size calculation from given image

81 ビュー (過去 30 日間)
Vikrant Pratap
Vikrant Pratap 2020 年 5 月 10 日
回答済み: Image Analyst 2020 年 5 月 10 日
I want to calculate sizes of each particle from the input image using image processing technique.

回答 (2 件)

Thiago Henrique Gomes Lobato
Thiago Henrique Gomes Lobato 2020 年 5 月 10 日
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 件のコメント
Thiago Henrique Gomes Lobato
Thiago Henrique Gomes Lobato 2020 年 5 月 10 日
編集済み: Thiago Henrique Gomes Lobato 2020 年 5 月 10 日
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 2020 年 5 月 10 日
Please help with plotting MajorAxisLength on the binary image.

サインインしてコメントする。


Image Analyst
Image Analyst 2020 年 5 月 10 日
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!

Translated by