Different thresholds for binarization of image

Hello, guys! The problem is as following:
I have to binarize image of an ice droplet (image 1), however simple thresholding with function graytresh (see image 2) does not meet all the complexities of the case. As you see from the image 2 in the bottom part conturs of the droplet are lost. As far as I can understand, the contrast of ice and background/surface is different at top and bottom, that is why automatic thresholding does not help. However, I am beginner and I am kinda confused and don't know how to solve this problem. I think that I have to divide image into the blocks with manually set borders and for each block give different threshold for the binarization. Could you explain how can I do that?

Respuestas (2)

Image Analyst
Image Analyst el 28 de Mzo. de 2022
Try this:
% 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 = 16;
markerSize = 40;
%--------------------------------------------------------------------------------------------------------
% READ IN IMAGE
folder = pwd;
baseFileName = 'ice.png';
% baseFileName = 'image_2732.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)
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
%--------------------------------------------------------------------------------------------------------
% Display the image.
subplot(2, 1, 1);
imshow(grayImage);
impixelinfo;
axis('on', 'image');
title('Original Gray Scale Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Maximize window.
g = gcf;
g.WindowState = 'maximized';
drawnow;
%--------------------------------------------------------------------------------------------------------
% Binarize the image to get a mask.
mask = imbinarize(grayImage);
% Erase everything outside +/- 50 pixels from the center.
middleColumn = columns/2;
column1 = middleColumn - 50;
column2 = middleColumn + 50;
mask(:, 1:column1) = false;
mask(:, column2:end) = false;
% Display mask image.
subplot(2, 1, 2);
imshow(mask);
hold on;
impixelinfo;
axis('on', 'image');
drawnow;
title('Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Find the top-most pixel
[y, x] = find(mask);
[yTop, indexOfTop] = min(y)
xTop = x(indexOfTop)
% Draw red lines
yline(yTop, 'Color', 'r', 'LineWidth', 2);
xline(xTop, 'Color', 'r', 'LineWidth', 2);
caption = sprintf('Binary Image. Top at (x,y) = (%d, %d)', xTop, yTop);
title(caption, 'FontSize', fontSize);
% Tell the user
message = sprintf('Done!\n');
uiwait(helpdlg(message))

4 comentarios

Nijat Azimzade
Nijat Azimzade el 30 de Mzo. de 2022
Thanks, I will try it this weekend! It seems that this code really gives the position of tip. But I don't quite understand why binarized image differ so much from the original. Shouldn't the initial shape be preserved?
Image Analyst
Image Analyst el 30 de Mzo. de 2022
Yes, it's the position of the tip that you said you were interested in.
I erased the original binarization outside of the central strip where the tip is known to be located. That removed much of the clutter and simplifies it greatly. We don't need all that junk that I erased if all we need is to find the line number of the tip.
To get the height in mm you'll need to find the bottom of the droplet and then get the distance from there to the tip in pixels. Then multiply that by your spatial calibration factor in mmPerPixel. See attached spatial calibration demo.
Nijat Azimzade
Nijat Azimzade el 30 de Mzo. de 2022
Sorry, I did not mention it, because I was not expecting such a complicated code, but I will also need points in the vicinity of the tip point, as I will also calculate tip angle. Does your code preserve the accuracy of the droplet over the line y=200? If not, do not worry, your code anyway gives very interesting approach that I can use at some point. Thank you for your effort!
Image Analyst
Image Analyst el 30 de Mzo. de 2022
Not sure what you mean by accuracy of the droplet near the tip. It's as accurate as your threshold is. My code. You can find the coordinates on each side of the tip and use polyfit() to fit them to lines.

Iniciar sesión para comentar.

Image Analyst
Image Analyst el 27 de Mzo. de 2022

0 votos

Can you get rid of the background clutter? If not, is your camera in a fixed position with respect to the scene so that you could use a fixed mask to basically erase the parts of the image that are background?
I don't think you need to find separate thresholds with blocks. I see no reason why that would help. In fact if a block was inside the droplet, if you forced it to find a threshold there automatically, like with graythresh() it may well pick the wrong one.
What are you going to do assuming you had the droplet well separated? Get the height, width, area, or what?
Another option is to use SegNet to do Deep Learning training on it, but you'd have to have lots (dozens or hundreds) or images where you've drawn/painted the "true" region of interest for each training image.

1 comentario

Nijat Azimzade
Nijat Azimzade el 28 de Mzo. de 2022
Thanks, I will try to remove the background!
After the binarization I want to write a code that will pick minimum (the one on the top) y value for a (given by me) x value from the line of contour of the droplet. Basically it must give me the position of tip.

Iniciar sesión para comentar.

Categorías

Más información sobre Image Processing Toolbox en Centro de ayuda y File Exchange.

Etiquetas

Preguntada:

el 27 de Mzo. de 2022

Comentada:

el 30 de Mzo. de 2022

Community Treasure Hunt

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

Start Hunting!

Translated by