# which is the best way to select threshold of a grayscale image

42 views (last 30 days)
Rohit Thokala on 9 Feb 2022
Commented: Walter Roberson on 10 Feb 2022
I have a set of grayscale images and I would like to take a constant threshold value to binarize these images. Each and every small droplet infomation is important for me in the binarized image. I tried imbinarize function with global, adaptive methods and also with different threshold values to binarize these images. "how could I explain the threshold value, if I choose some value (like I mentioned below)?" or "are there any better method to binarize a image?" I seen people using imhist() function to choose the threshold value, but I can't plot the histograms of these images. I have attached some images for reference. Thanks in advance
Binaryimage=imbinarize(tilt,0.15)
Walter Roberson on 10 Feb 2022
img1d = imsubtract(img1, img1b);
img1s = im2uint8(rescale(img1d,'inputmax',4095));
figure; imshow(rescale(img1,'inputmax',4095)); title('original')
figure; imshow(img1s); title('image difference');
figure; img1sg = rgb2gray(img1s); contourf(img1sg,32); colorbar; set(gca,'ydir','reverse'); axis equal; title('contour of difference');
Now, fiddle with that 32 that you see. If the 32 is too large then you start getting spurious background contours all over the place due to chance level fluctuations or oddities of processing. Adjust the 32 to smaller until you are sure that all of the chance bubbles are gone -- but the bubbles that seem to show structure are kept. By showing structure, I mean that the bubble that appear near the edges of the jets likely reflect actual information -- not necessarily true images of droplets, but at the very least, brightness differences due to reflection or refraction off of dropets. At the point where you see the dimmest bubbles that you think represent actual data (direct droplets or at least reflection / refraction), then use the data cursor to look at the Level information. It looked to me as if that point was roughly in the range of Level 6 to 10. That is, it looked to me as if level differences as small as 6 to 10 on the scale of 0 to 255 might be meaningful.
6 to 10 or so on the scale of 0 to 255 reflects differences in the original data on the order of about 100 to 150, because the original data is uint16 images whose actual values are in the range 0 to 4095 (12 bit data). roughly a 3% difference in brightness or more seems to be conveying information.

Image Analyst on 9 Feb 2022
There is no one best way to select a threshold. Nor, for any given image, is there always a best threshold. For your images, you can see that you have a continuum of gray levels and the possibility of picking any gray level for the threshold. It's basically a judgement call. You can use an interactive threshold selection tool, like mine:
to pick one. So, if you pick one, who's to say it's wrong? Nobody. There is nothing in the physics of the situation that says what the best threshold is. Maybe there could be if you had an image of a perfectly black background (like black velvet which is a cheap super dark background to use), and all your droplets are known to be brighter than the background. Then you could just set your threshold to be the maximum gray level of your background. However if your background is not uniform, meaning it might be brighter in some areas than your droplets are in other areas, then that might not work.
You need to make sure your background is as dark and uniform as possible. Not sure if you know about lens shading, but all lenses shade the image so the the edges and corners of the image are usually darker than the middle (optic axis). You need to correct for that. The usual way is to divide your test images by the background image, though for certain situations (x-ray, fluoresence) you need to subtract instead of divide. For example, if the corner of your image is 90% as bright as the middle, you'd need to divide the image by 0.90 there to "undo" the effect of lens shading. This will also handle lighting non-uniformity. A demo is attached.
However you are correct in saying that the best way is to use a fixed threshold. Whatever it is chosen to be, use that threshold for all your images otherwise you can't accurately compare the images that had a lot of spray with those that had not much spray since the threshold would be different with every image.
If you want to use an automatic threshold, often times I find the triangle threshold works very well. I'm attaching it.
% Threshold the image.
[pixelCounts, binEdges] = histcounts(grayImage, 255);
% Get the triangle threshold as the first guess.
lowThresholdIndex = triangle_threshold(pixelCounts, 'R', false)
lowThreshold = binEdges(lowThresholdIndex)
highThreshold = binEdges(end)
% Now call interactive tool to adjust and set the threshold.
% https://www.mathworks.com/matlabcentral/fileexchange/29372-thresholding-an-image?s_tid=srchtitle
[lowThreshold, highThreshold] = threshold(lowThreshold, highThreshold, grayImage)
mask = grayImage >= lowThreshold & grayImage <= highThreshold;
So once you've decided upon the threshold(s), via whatever method you choose, you need to use that value(s) for all your images.
Rohit Thokala on 10 Feb 2022
Hello @Image Analyst, I will check these links for more information. I used background subtraction for images that I have provided here. Since the spray cloud reflects some light the background subtraction didn't work well for large spray cloud images. Thank you for your notable suggestions.

yanqi liu on 10 Feb 2022
yes，sir，may be use threshold method can not adaptive to multi images，so may be consider use DeepLearning method，such as unet、mask rcnn
Walter Roberson on 10 Feb 2022
In order to use deep learning, you would need to have some labeled images that indicated ground truth. I do not think that is available.

R2021b

### Community Treasure Hunt

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

Start Hunting!

Translated by