How to find the threshold that an image is binarized?

I have a binarized image. The binarization is done from the original greyscale image.
Is there any way to find what was the threshold for binarization?

Assuming you have 8bit images, you can measure the area in your thresholded image and then search for the threshold applied to your original that gives you the same area.

Here is a macro example:
(be aware that this macro expects the images named as defined in the macro)

// Assuming 8bit images

orig = "Orig_Gray_8bit";
thresholded = "Thresholded_Image";

selectWindow(thresholded);

run("Set Measurements...", "integrated redirect=None decimal=3");
setOption("BlackBackground", true);

run("Measure");

targetIntDen = getResult("IntDen", 0)
print(""+targetIntDen);

selectWindow("Results");
run("Close");

intDen = 1e12;
currentLowerThershold = 0;
while ( (intDen > targetIntDen) && (currentLowerThershold < 255)){
	selectWindow(orig);

	run("Duplicate...", " ");
	rename("ThresTest");

	currentLowerThershold++;
	setThreshold(currentLowerThershold, 255);
	run("Convert to Mask");
	
	run("Measure");
	
	intDen = getResult("IntDen", 0);
	
	selectWindow("Results");
	run("Close");

	selectWindow("ThresTest");
	close();
}

print("Threshold = "+(currentLowerThershold--));

Maybe this helps

Peter

1 Like

This is an interesting problem. Just a few more comments.
Here I am assuming that the object is binarised as 255 and the background is 0.
Was it automatic global thresholding with one of the built-in methods?
If so then the principle that phaub suggested should work (but see below).
Was it applied after some pre-processing? If so you need to reapply the pre-processing before applying the macro above.
Was it done with local thresholding? (the method above won’t work).
There are many other ways of binarising an image, for example texture thresholding, so obviously a histogram search won’t work.

So the method above works if there is a single threshold going from a given value up to 255 (that is segmenting the ‘bright’ part of the histogram).
You’ll need to search the greyscale space backwards if you are after the ‘dark’ part of the histogram.

Also remember that in IJ one can set minimum and maximum threshold values with the threshold applet (that is, a range). In such case you need to search through all the possible ranges with two nested loops.

Depending on the image, there might not be a single solution. Imagine an object with grey value 130 on a black 0 background. You could obtain the same result by thresholding anywhere in the range from 1 to 130 and 255 (maybe for your application it does not matter as far as obtaining one possible result is enough).

Another way of doing this without calling the IntDen is to threshold at the test value and do a XOR operation between the originally thresholded image and the test image, and get the histogram of the result. If the histogram contains any pixels with value 255 then you know that the two images are not the same. That being said, I am not sure if there is a computational advantage of doing it this way.
Hope it helps.

2 Likes

Thanks gabriel for discussing all this important details.