How do I properly binarize my image?

36 visualizaciones (últimos 30 días)
Matheo Schaaf
Matheo Schaaf el 20 de Jun. de 2022
Respondida: Image Analyst el 20 de Jun. de 2022
Hello,
I want to analyze the particle size distribution of my sample. I followed the example of 'ImageAnalyst'. The problem for my sample is that the grains I'm mostly interested in aren't binarized properly. The grains are the little dark gray and black circles. How do I get them binarized, so I can count them afterwards?

Respuesta aceptada

Image Analyst
Image Analyst el 20 de Jun. de 2022
You really need to take a blank shot of nothing so you know how the lighting and lens shading are affecting your image and making it darker at the bottom. Then you can divide by that blank iamge to flatten the image and make the exposure everywhere the same.
In the meantime, try this. You can experiment around with the various parameters to fine tune what you want to segment out.
% Demo by Image Analyst
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 = 22;
markerSize = 40;
%--------------------------------------------------------------------------------------------------------
% READ IN IMAGE
folder = pwd;
baseFileName = 'grains.png';
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% 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
rgbImage = imread(fullFileName);
% Get the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(rgbImage)
%--------------------------------------------------------------------------------------------------------
% Display the image.
subplot(3, 2, 1);
imshow(rgbImage);
impixelinfo;
axis('on', 'image');
title('Original Color Image', 'FontSize', fontSize, 'Interpreter', 'None');
if numberOfColorChannels > 1
% It's not really gray scale like we expected - it's color.
fprintf('It is not really gray scale like we expected - it is color\n');
% Extract the blue channel.
grayImage = rgbImage(:, :, 3);
else
grayImage = rgbImage;
end
% Update the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(grayImage)
% Maximize window.
g = gcf;
g.WindowState = 'maximized';
drawnow;
% Display histogram.
subplot(3, 2, 2);
histogram(grayImage);
grid on;
drawnow;
title('Histogram of Image', 'FontSize', fontSize, 'Interpreter', 'None');
%--------------------------------------------------------------------------------------------------------
% Binarize the image to get a mask.
lowThreshold = 150;
highThreshold = 255;
% https://www.mathworks.com/matlabcentral/fileexchange/29372-thresholding-an-image?s_tid=srchtitle
% threshold(lowThreshold, highThreshold, grayImage);
mask = grayImage >= lowThreshold & grayImage <= highThreshold;
% Put red threshold line on histogram so they know where it was thresholded at.
xline(lowThreshold, 'Color', 'r', 'LineWidth', 2)
xline(highThreshold, 'Color', 'r', 'LineWidth', 2)
% Clean up the mask
mask = imfill(mask, 'holes'); % Fill black holes in blobs.
mask = bwareaopen(mask, 1000); % Take only blobs larger than 1000 pixels.
mask = bwconvhull(mask, 'objects');
% Enlarge the blobs a few pixels to get rid of the edge.
se = strel('disk', 7, 0);
mask = imdilate(mask, se);
% Display mask image.
subplot(3, 2, 3);
imshow(mask);
hold on;
impixelinfo;
axis('on', 'image');
drawnow;
title('Mask, a Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Get areas of blobs so we know what to use in bwareaopen().
props = regionprops(mask, 'Area');
allAreas = sort([props.Area])
% The mask is the big, bright blobs. Erase those from the image.
grayImage(mask) = 0;
% Display image.
subplot(3, 2, 4);
imshow(grayImage, []);
hold on;
impixelinfo;
axis('on', 'image');
drawnow;
title('Gray Image', 'FontSize', fontSize, 'Interpreter', 'None');
se = strel('disk', 31, 0);
botHatImage = imbothat(grayImage, se);
% Display image.
subplot(3, 2, 5);
imshow(botHatImage, []);
hold on;
impixelinfo;
axis('on', 'image');
drawnow;
title('Bottom Hat Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Display histogram of non-masked (non-black) pixels.
subplot(3, 2, 6);
histogram(grayImage(grayImage > 0));
grid on;
drawnow;
title('Histogram of Bottom Hat Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Now threshold this
darkBlobsMask = botHatImage > 30;
% Clean up the mask
mask = imfill(mask, 'holes'); % Fill black holes in blobs.
mask = bwareaopen(mask, 20); % Take only blobs larger than 10 pixels.
% Display mask image.
subplot(3, 2, 6);
imshow(darkBlobsMask);
hold on;
impixelinfo;
axis('on', 'image');
drawnow;
title('Dark Blobs Mask, a Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');

Más respuestas (1)

Image Analyst
Image Analyst el 20 de Jun. de 2022
If regular global thresholding doesn't get them then you might try a bottom hat filter imbothat
  3 comentarios
Image Analyst
Image Analyst el 20 de Jun. de 2022
If you don't want to analyze the whole image by finding gray/dark blobs in the whole image, then exactly how are you defining an ROI that is just some part of the image? I was thinking you'd just want to find those dark blobs everywhere they occur in the image, not in some portion of the image.
Matheo Schaaf
Matheo Schaaf el 20 de Jun. de 2022
Editada: Matheo Schaaf el 20 de Jun. de 2022
So in the end I want to calculate the pixels and give a distribution. But the pixels I'm interested in are just inside the sample. The pixels outside AND inside the hole aren't interesting for me. What I wanted to do was drawing a polygon as my ROI to follow the sample and exclude the the other pixels. Maybe there is a better solution for this?

Iniciar sesión para comentar.

Community Treasure Hunt

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

Start Hunting!

Translated by