Image segmentation of these pellets

58 visualizaciones (últimos 30 días)
Saye Vikram
Saye Vikram el 29 de Mzo. de 2024
Comentada: Saye Vikram el 6 de Abr. de 2024 a las 19:11
Hello, I have a task which needs me to perform image segmentation for every pellet for this image (pellet being defined as every "flat-ish" pellet that is visible from the side of the screen, no pellets that I cannot see the whole side-view of) :
I tried to use watershed segmentation and Distance transform in order to separate out the pellets as below:
clear
rgb = imread("matlab_test.png");
I = im2gray(rgb);
gmag = imgradient(I);
L = watershed(gmag);
Lrgb = label2rgb(L);
se = strel("disk",5);
Io = imopen(I,se);
Ie = imerode(I,se);
Iobr = imreconstruct(Ie,I);
Ioc = imclose(Io,se);
Iobrd = imdilate(Iobr,se);
Iobrcbr = imreconstruct(imcomplement(Iobrd),imcomplement(Iobr));
Iobrcbr = imcomplement(Iobrcbr);
fgm = imregionalmax(Iobrcbr);
I2 = labeloverlay(I,fgm);
se2 = strel(ones(3,3));
fgm2 = imclose(fgm,se2);
fgm3 = imerode(fgm2,se2);
fgm4 = bwareaopen(fgm3,20);
I3 = labeloverlay(I,fgm4);
bw = imbinarize(Iobrcbr);
D = bwdist(bw);
DL = watershed(D);
bgm = DL == 0;
gmag2 = imimposemin(gmag, bgm | fgm4);
L = watershed(gmag2);
labels = imdilate(L==0,ones(3,3)) + 2*bgm + 3*fgm4;
I4 = labeloverlay(I,labels);
Lrgb = label2rgb(L,"jet","w","shuffle");
figure
imshow(I)
hold on
himage = imshow(Lrgb);
himage.AlphaData = 0.3;
title("Colored Labels Superimposed Transparently on Original Image")
This code however only segments to a certain extent, as such:
How do I tweak my code so that it segments every individual pellet as much as possible?
  1 comentario
DGM
DGM el 1 de Abr. de 2024 a las 21:37
Editada: DGM el 1 de Abr. de 2024 a las 21:38
Edited only to attach the images locally.

Iniciar sesión para comentar.

Respuestas (2)

Taylor
Taylor el 1 de Abr. de 2024 a las 20:07
Have you tried a different colorspace? I converted the image to HSV and used the Color Thresholder app. Just with that I was able to get the following mask. The function below will recreate the mask for you.
function [BW,maskedRGBImage] = createMask(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder app. The colorspace and
% range for each channel of the colorspace were set within the app. The
% segmentation mask is returned in BW, and a composite of the mask and
% original RGB images is returned in maskedRGBImage.
% Auto-generated by colorThresholder app on 01-Apr-2024
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.009;
channel1Max = 0.112;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.103;
channel2Max = 0.275;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.347;
channel3Max = 0.687;
% Create mask based on chosen histogram thresholds
sliderBW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end
  2 comentarios
DGM
DGM el 1 de Abr. de 2024 a las 21:30
Editada: DGM el 1 de Abr. de 2024 a las 21:31
This doesn't answer the question. The goal is to segment individual pellets. This does not do that.
inpict = imread('pellets.png');
mk = mymask(inpict); % create a mask using global thresholds
mk = bwareaopen(mk,100); % get rid of a thousand tiny specks
S = regionprops(mk,'area'); % look at the distribution
% generate an alternating CT
CT = hsv(numel(S));
CT(2:2:end,:) = flipud(CT(2:2:end,:));
% the result is one giant conglomerate blob
% and several smaller conglomerate blobs
alpha = 0.8;
outpict = labeloverlay(inpict,bwlabel(mk), ...
'transparency',1-alpha,'colormap',CT);
imshow(outpict,'border','tight')
Saye Vikram
Saye Vikram el 2 de Abr. de 2024 a las 4:51
Great response and answer first off. I just wanted to ask, would this not treat the whole red-portion as one giant blob? Is there no way to segment that portion so you can retrieve information about each pellet in that red-region?

Iniciar sesión para comentar.


Image Analyst
Image Analyst el 2 de Abr. de 2024 a las 18:26
It would be very very difficult to segment every single individual pellet, particulary since some are very small, some are "touching" adjacent pellets, and they have every conceivable shape, even down to powder particles.
In cases like these you need to really ask yourself what is really needed. You have some attribute that you need to quantify. Perhaps it's shape, perhaps it's volume of pellets in the container, perhaps it's just the quality of the pellet shapes, perhaps it's the colors of the pellets. Perhaps it's how easily they flow in a pipe or how easily they can get crushed or burned. Maybe you need to run the pile of pellets through sieves of different sizes and weigh them or photograph them.
It's difficult to answer the question because we don't know the full context. Finding evey pellet would be difficult even if you were to tediously hand-trace each pellet. So we need to find something else -- some other metric -- that will correlate with the attribute that you really need to know. For example, maybe we can segment the whole pile into one blob and look at the standard deviation of gray levels in that region and maybe that correlates well with how easily a pile can flow in a pipe, or get crushed, or burn completely. Maybe you can then make a plot (by analyzing the range of samples you have) that relates standard deviation to crushability. Then once you have that plot (calibration curve) created, you can predict the crushability of the particles by using it to input the StDev and getting out an estimate of crushability.
So please tell us what you REALLY need to know and we'll tell you if you really need to find each and every pellet or is there some bulk measurement that will give us the correlation we need. You may not need to find every pellet like you asked us -- there may be a much easier way. See
  1 comentario
Saye Vikram
Saye Vikram el 6 de Abr. de 2024 a las 19:11
Sorry caught up with stuff, could not get to your response. What I REALLY need is either the center position and orientation (angle relative to the horizontal) of each pellet across a whole video in order to form a Langrangian description of flow. I either need that OR I need the average of Xi (Position of a pellet i) or Thetai in a small spatial region at time T in order to form a Eulerian description of flow. Ultimately I am trying to find the governing equations for X(x, y, t) and Theta(x, y, t)

Iniciar sesión para comentar.

Categorías

Más información sobre Image Processing Toolbox en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by