NOTICE! This is a static HTML version of a legacy Fiji BugZilla bug.

The Fiji project now uses GitHub Issues for issue tracking.

Please file all new issues there.

Bug 938 - Bug in the Intermodes algorithm of threshold
Bug in the Intermodes algorithm of threshold
Status: RESOLVED FIXED
Product: Fiji
Classification: Unclassified
Component: Plugins
unspecified
PC Windows
: P4 normal
Assigned To: ImageJ Bugs Mailing List
Depends on:
Blocks:
 
Reported: 2014-10-03 09:59 CDT by Gadea Mata
Modified: 2014-10-07 01:29 CDT
5 users (show)

See Also:

Description Gadea Mata 2014-10-03 09:59:56 CDT
Dear all,

We're looking for what is the best threshold algorithm for our images. We've seen that if we use the function "Auto Threshold" to obtain the differents threshold values for each algortithm, the Intermodes algorithm returns a different threshold value, that if we use the function "Threshold..." choosing the Intermodes method.

We've studied the code of both algorithms, and we think that the algorithm developed in the plugin "Threshold..." has a bug. We've studied the code available at http://imagej.nih.gov/ij/source/ij/process/AutoThresholder.java, and we think that the problem arises in Line 199 of such a code. The loop in Line 199 concerns the computation of the new values of the histogram. For each step of the loop, the new value of the histogram is calculated using the values of the updated histogram instead of using the values of the original histogram. 

However, the Intermodes algorithm in the plugin "Auto Thresholder" is correct.

We attached you a minimal macro that reproduces this bug:

run("Neuron (1.6M, 5 channels)");
run("Split Channels");
//close all channels minus channel 2
selectWindow("C5-Rat_Hippocampal_Neuron.tif");
close();
selectWindow("C4-Rat_Hippocampal_Neuron.tif");
close();
selectWindow("C3-Rat_Hippocampal_Neuron.tif");
close();
selectWindow("C2-Rat_Hippocampal_Neuron.tif");
selectWindow("C1-Rat_Hippocampal_Neuron.tif");
close();
selectWindow("C2-Rat_Hippocampal_Neuron.tif");
//AUTO THRESHOLD
run("Auto Threshold", "method=[Try all] white show");
//the threshold value of Intermodes method: 525
close();
selectWindow("C2-Rat_Hippocampal_Neuron.tif");
//THRESHOLD
setAutoThreshold("Intermodes dark");
//run("Threshold...");
setThreshold(1713, 6238); //here, the threshold value is 1713
run("Convert to Mask");
run("Close");

Best regards,

--Gadea Mata Martínez
gadea.mata@unirioja.es
Department of Mathematics and Computer Science
University of La Rioja
Logroño, La Rioja (Spain)

Information about your version of Java:

  os.arch => x86
  os.name => Windows 7
  os.version => 6.1
  java.version => 1.6.0_24
  java.vendor => Sun Microsystems Inc.
  java.runtime.name => Java(TM) SE Runtime Environment
  java.runtime.version => 1.6.0_24-b07
  java.vm.name => Java HotSpot(TM) Client VM
  java.vm.version => 19.1-b02
  java.vm.vendor => Sun Microsystems Inc.
  java.vm.info => mixed mode
  java.awt.graphicsenv => sun.awt.Win32GraphicsEnvironment
  java.specification.name => Java Platform API Specification
  java.specification.version => 1.6
  sun.cpu.endian => little
  sun.desktop => windows
  file.separator => \

The up-to-date check says: REMIND_LATER

Information relevant to JAVA_HOME related problems:

  JAVA_HOME is set to: C:\Users\gamata\PROGRA~1\Fiji.app/java/win32/jdk1.6.0_24//jre
  imagej.dir => C:\Users\gamata\PROGRA~1\Fiji.app

Information about the version of each plugin:

Activated update sites:
ImageJ: http://update.imagej.net/ (last check:20140925235708)
Fiji: http://fiji.sc/update/ (last check:20141002110637)
Comment 1 Curtis Rueden 2014-10-03 11:59:31 CDT
Thanks for the report, and macro to reproduce!

The ImageJ 1.x implementation is in a class called AutoThresholder:

https://github.com/imagej/ImageJA/blob/v1.49h/src/main/java/ij/process/AutoThresholder.java#L176-L220

And the "Auto Threshold" implementation, which is part of Fiji, can be found at:

https://github.com/fiji/Auto_Threshold/blob/0565751243a83688c84857475adb51ae836a843e/src/main/java/fiji/threshold/Auto_Threshold.java#L493-L541

The ImageJ 1.x implementation returns 1713 when "Dark background" is checked.
The Fiji Auto_Threshold implementation returns 525.

It was not clear to me from your bug report which algorithm you believe to be correct, and which incorrect. However, seeing as how the minimum data value of the entire "Neuron" sample image is 526, the value 525 seems obviously wrong to me. So I conclude that the ImageJ 1.x result is correct, while the Fiji Auto_Threshold result is incorrect. Right?

As an aside: there is a third implementation, recently ported from Fiji's Auto_Thresold, in the ImageJ OPS library:

https://github.com/imagej/imagej-ops/blob/114183192d41e9dcbe0e6450512170f8a566dc6e/src/main/java/net/imagej/ops/threshold/global/methods/ComputeIntermodesThreshold.java#L58-L100

Since it was ported from Fiji's Auto_Threshold, it also suffers from this bug.

Gadea: Could you please confirm that the ImageJ 1.x code produces the correct result, and the Fiji Auto_Threshold code an incorrect one? If so, I will fix the bug in the two affected libraries.
Comment 2 G. Landini 2014-10-03 14:34:39 CDT
Hi,
The command Edit>Adjust>Auto Threshold both in ImageJ1 (if you downloaded the Auto Threshold plugin from my site) and in Fiji (already there by default) actually return the same value for the Intermodes method with the macro you posted (i.e. 525).
This does a threshold on the 16bit data.

Furthermore, in both cases, the Log window says that a proper Intermodes threshold was not found after 10000 iterations, so the value, so you should take that result with caution, it is a guessed value, not a converged one.

However what you get from the drop box when you use Edit>Adjust>Threshold and then select the Intermodes from the drop list, this is a different adaptation of the algorithms above that Wayne added. I think in 16bit this is implemented as a mapped histogram with 256 bins, so you would expect some difference.

I am looking into this in more detail and because I found some unexpected behaviour if one chooses to set the threshold but not to convert to mask. It converts to 8bit anyway. Not sure why, but hope to update this soon.
Comment 3 G. Landini 2014-10-03 16:00:33 CDT
Hi, just a quick update. The Intermodes threshold method 'fails' in the 16bit image because the histogram is not bimodal. The value of 525 is just the min value of the image-1. I do not consider this is a bug because the plugin explains the situation in the Log window.

Now, about the issue of with why this works differently with the Adjust>Threshod command. I am almost sure that this is because that command packs the 16bit histogram into an 8 bit space (i.e. 256 bins) and thresholds that histogram. You get the 'correct' result by converting the image to 8 bits and using the Auto_Threshold plugin Intermodes method (if you do it you will find that the binary result is identical on that neuron image).
A bit counter-intuitive, but a 16bit image and the same converted to 8 bits are not the same, and we should not expect the same result for all the methods.

I am marking this as "Invalid" as I do not think there is a bug, just a confusing situation, but please feel free to reopen if you think otherwise.

By the way, the issue raised about line 199, I think it is correct as is. The histogram is sequentially, so this has to be done on the the same array.

One more thing, I could add to the code to return "-1" if the method fails. Now it returns the minimum grey value of the histogram-1. Not sure if that makes it any clear; suggestions are welcome.
Comment 4 Gadea Mata 2014-10-06 06:00:20 CDT
Thanks for all your answers. I am not completely sure about some parts of your answers.

1) Packing 16bit histogram into an 8 bit space. 

The problem that I commented not only appears when working with 16bits images, but also with 8bits images. For instance, you can find a problematic image in the link: https://www.dropbox.com/s/sm7p9f0n8z1mxdw/gfp-6.tif?dl=0. For this image (an 8bits-image), different threshold values are returned when using the Intermodes method of the plugins "Auto Threshold" and "Threshold...". Therefore, I think that the problem is not related to the packaging of a 16bit histogram into an 8 bit space. 

2) What is the class that contains the correct code?

From my point of view, the two correct implementations are (1) the "Auto Threshold" implementation (which is part of Fiji, and can be found at: https://github.com/fiji/Auto_Threshold/blob/0565751243a83688c84857475adb51ae836a843e/src/main/java/fiji/threshold/Auto_Threshold.java#L493-L541), and (2) the recently ported implementation from Fiji's Auto_Thresold, in the ImageJ OPS library 
(https://github.com/imagej/imagej-ops/blob/114183192d41e9dcbe0e6450512170f8a566dc6e/src/main/java/net/imagej/ops/threshold/global/methods/ComputeIntermodesThreshold.java#L58-L100).

On the contrary, the ImageJ 1.x implementation in the class AutoThresholder is not correct. I think that the problem appears when the “mean filter” is applied to smooth the histogram (https://github.com/imagej/ImageJA/blob/v1.49h/src/main/java/ij/process/AutoThresholder.java#L198-L199). If I understand properly, the process to apply the mean filter with radius 3 to an array A could be seen as follows. We have a new array B with the same length as A and the value of B[i] is (A[i-1] + A[i] + A[i+1])/3 (the values of the first and last element of B are computed using (A[0] + A[1])/3  and (A[A.length-2]+A[A.length-1])/3) ― these are the formulas used in Implementations (1) and (2). However, the formula that is used in the ImageJ 1.x implementation is B[i] = (B[i-1] + A[i] + A[i+1])/3.

In the case that the latter formula is the correct one, it should also be used in Implementations (1) and (2); otherwise, different results will be obtained.
Comment 5 Wayne Rasband 2014-10-06 12:12:50 CDT
This bug is fixed in the ImageJ 1.49i8 daily build. The ij.process.AutoThresholder class now uses the same algorithm as the Image>Adjust>Auto Threshold plugin.
Comment 6 G. Landini 2014-10-06 14:08:20 CDT
Hi Gadea,
Just answering 1)
ImageJ (Threshold command) takes a 16 or 32 bit images and histograms them in 256 bins. Then resolves the threshold with that histogram. IJ always did this. 

The Auto Threshold (in Fiji, Auto Threshold command) originally thresholded only 8bit images. Then Johannes modified the code so it can also process images using the whole histrograms as they are: with 2^8 bins for 8 bits and 2^16 bins for 16 bits.  The resolution that the Auto Threshold can achieve is therefore higher than the Threshold command.
So that is why the 2 commands might return different results when analysing 16bit images.

I hope this clarifies it.
Comment 7 Gadea Mata 2014-10-07 01:29:14 CDT
Hi, thanks for all your answers and your explanation. Thanks G. Landini, now I understand Point 1.

Best regards,