Estimation of particle size in the image
Show older comments
Hi,
I am trying to estimate size of the particle in the attached image. As this image has both the particles and other shapes, hence, it is bit difficult to estimate the size of the particle alone. Could someone help with this?
Accepted Answer
More Answers (1)
Image Analyst
on 3 May 2024
Try this:
% Demo by Image Analyst
% Initialization steps:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
%--------------------------------------------------------------------------------------------------------
% READ IN BACKGROUND IMAGE
folder = pwd;
baseFileName = "BACKGROUND.bmp";
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~isfile(fullFileName)
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
% Read in image file.
backgroundImage = imread(fullFileName);
% Get size
[rows, columns, numberOfColorChannels] = size(backgroundImage)
if numberOfColorChannels == 3
% Convert to gray scale if needed.
backgroundImage = rgb2gray(backgroundImage);
end
% Display the image.
subplot(2, 3, 1);
imshow(backgroundImage);
axis('on', 'image');
impixelinfo;
title('Background Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Maximize window.
g = gcf;
g.WindowState = 'maximized';
g.Name = 'Demo by Image Analyst';
g.NumberTitle = 'off';
drawnow;
%--------------------------------------------------------------------------------------------------------
% READ IN TEST IMAGE
folder = pwd;
baseFileName = "image 1.bmp";
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~isfile(fullFileName)
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
% Read in image file.
grayImage = imread(fullFileName);
% Get size
[rows, columns, numberOfColorChannels] = size(grayImage)
if numberOfColorChannels == 3
% Convert to gray scale if needed.
grayImage = rgb2gray(grayImage);
end
% Display the image.
subplot(2, 3, 2);
imshow(grayImage);
axis('on', 'image');
impixelinfo;
title('Original Image', 'FontSize', fontSize, 'Interpreter', 'None');
%--------------------------------------------------------------------------------------------------------
% DIVIDE THE TEST IMAGE BY THE BACKGROUND IMAGE.
backgroundCorrectedImage = double(grayImage) ./ double(backgroundImage);
% Crop out middle part
backgroundCorrectedImage = backgroundCorrectedImage(:, 400:600);
subplot(2, 3, 3);
imshow(backgroundCorrectedImage, []);
axis('on', 'image');
impixelinfo;
title('Background corrected Image', 'FontSize', fontSize, 'Interpreter', 'None');
subplot(2, 3, 4);
% Show histogram.
histogram(backgroundCorrectedImage)
grid on;
title('Histogram of Background Image', 'FontSize', fontSize, 'Interpreter', 'None');
%--------------------------------------------------------------------------------------------------------
% CREATE MASK
% It's where the image is not near 1.
tolerance = 0.4; % Adjust as needed.
mask = abs(backgroundCorrectedImage - 1) > tolerance;
subplot(2, 3, 5);
imshow(mask);
axis('on', 'image');
impixelinfo;
title('Initial Mask Image', 'FontSize', fontSize, 'Interpreter', 'None');
%--------------------------------------------------------------------------------------------------------
% Fill any holes.
mask = imfill(mask, 'holes');
% Delete top stream and any blobs touching the edge of the image (because they are partial droplets not full droplets).
mask = imclearborder(mask);
% Label each blob with 8-connectivity, so we can make measurements of it
[labeledImage, numberOfBlobs] = bwlabel(mask, 8);
% Apply a variety of pseudo-colors to the regions.
coloredLabelsImage = label2rgb (labeledImage, 'hsv', 'k', 'shuffle');
% Display the pseudo-colored mask image.
subplot(2, 3, 6);
imshow(coloredLabelsImage);
axis('on', 'image');
impixelinfo;
%--------------------------------------------------------------------------------------------------------
% GET AREAS AND DIAMETERS
blobMeasurements = regionprops(mask, 'Area', 'EquivDiameter');
numberOfDroplets = size(blobMeasurements, 1)
allAreas = [blobMeasurements.Area]
allDiameters = [blobMeasurements.EquivDiameter]
caption = sprintf('Final Mask Image with %d Droplets', numberOfDroplets);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');

numberOfDroplets =
5
allAreas =
586 561 447 569 55
allDiameters =
Columns 1 through 4
27.3151674571987 26.7261554398762 23.8566149421207 26.9160417029382
Column 5
8.368283871884
Answers are in pixels. Multiply by microns per pixel to get your answers in microns or square microns.
25 Comments
Turbulence Analysis
on 3 May 2024
Turbulence Analysis
on 4 May 2024
Image Analyst
on 4 May 2024
No you don't need to crop though I just did that to make sure I didn't have any noise blobs included. You could just blacken the mask in those regions, if necessary, and keep the image the same size.
mask(:, 1:400) = false;
mask(:, 600:end) = false;
Turbulence Analysis
on 4 May 2024
Turbulence Analysis
on 4 May 2024
Turbulence Analysis
on 4 May 2024
Image Analyst
on 5 May 2024
Your image is 1024 pixels wide, I guess. What is the field of view in mm?
What is the centroid? Each image will have several droplets and thus several centroids. Which one(s) are you plotting?
Turbulence Analysis
on 5 May 2024
Image Analyst
on 5 May 2024
So you just do this (for one image):
blobMeasurements = regionprops(mask, 'Area', 'EquivDiameter', 'Centroid', 'Eccentricity');
xy = vertcat(blobMeasurements.Centroid)
xInPixels = xy(:, 1);
xInMm = xInPixels / 17.5;
figure;
subplot(1, 2, 1)
histogram(xInMm);
grid on;
title('Histogram of x values');
subplot(1, 2, 2);
y = 1 : numel(xInMm);
plot(x, y, 'b.', 'MarkerSize', 20)
grid on;
xlabel('x location in mm')
ylabel('Droplet number')
for multiple images, accumulate all the x of each individual image into one vector and show that.
Turbulence Analysis
on 5 May 2024
Image Analyst
on 5 May 2024
Attach your m-file. It looks like you maybe used 'XData' and 'YData' options in imshow(). The x values should be the distance from the left side of the image unless you somehow introduced a shift in the axis values.
What do you want? Do you want both negative and positive coordinates, or do you just want positive coordinates? Or do you want displacement from the centerline of the stream?
Turbulence Analysis
on 5 May 2024
Image Analyst
on 5 May 2024
You forgot to attach the m-file like I asked. You attached just a snippet from it. Attach the whole thing.
Since different images have different droplets all over the place, where is your global x=0 location? Or does it vary image to image, like each image's origin depends on where the central stream is?
Turbulence Analysis
on 7 May 2024
Image Analyst
on 8 May 2024
Did you try subtracting 350?
xy = vertcat(blobMeasurements.Centroid)
xInPixels = xy(:, 1) - 350;
xInMm = xInPixels / 17.5;
Turbulence Analysis
on 8 May 2024
Image Analyst
on 8 May 2024
Did you attach the correct image? I get
Error using imread>get_full_filename (line 579)
Unable to find file "0_40ml_1_C001H001S0001000001.bmp".
Error in imread (line 372)
fullname = get_full_filename(filename);
Error in Particle_size (line 27)
grayImage = imread(fullFileName);
Turbulence Analysis
on 8 May 2024
Turbulence Analysis
on 8 May 2024
Turbulence Analysis
on 14 May 2024
Image Analyst
on 14 May 2024
Assuming you have the bottom y (row), you can get the x value(s) like this
lastRow = mask(row, :);
leftMostX = find(lastRow, 1, 'first')
rightMostX = find(lastRow, 1, 'last')
allX = find(lastRow)
meanX = mean(allX)
Turbulence Analysis
on 14 May 2024
Image Analyst
on 14 May 2024
Then how did you draw the bounding box on the upper part of the stream? If you drew that red box with something like rectangle then you must know the row of the bottom y value.
Turbulence Analysis
on 14 May 2024
Turbulence Analysis
on 14 May 2024
Categories
Find more on Switches and Breakers in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!

