2

I try to write Java Plugin to ImageJ, which should:

  • Load image (24-bit).
  • Do some preprocessing operations.
  • Threshold the image in numerous of methods.
  • Do some other operations.

I have problem with threshold operation. Part of my code looks like this:

Opener opener = new Opener();
ImagePlus imp = opener.openImage(source);
// Preprocessing
IJ.run("Threshold..." , method);
// Other operations e.g. "open", "outline" etc.
IJ.saveAs(destination);

My goal is to get binarized image in various methods (e.g. "Default", "Huang", "Intermodes", "IsoData", "Li" etc.). Only way which I can get binarized image is to run:

IJ.run(imp, "8-bit", "");
IJ.run(imp, "Make Binary", "");

however, I get an image binarized by only one method. How to do automatic threshold by running Java code (ImageJ plugin)?

trojek
  • 3,078
  • 2
  • 29
  • 52
  • this does not answer the question: maybe you should openImaj (http://www.openimaj.org/) give a try. There are some methods concerning threshold. – chris Jun 22 '15 at 13:24

2 Answers2

1

You seem to use the IJ.run method the wrong way. The first parameter is a string containing an ImageJ command and the second parameter is a string containing the options of this command. From the documentation:

public static void run(java.lang.String command, java.lang.String options)

Runs an ImageJ command, with options that are passed to the GenericDialog and OpenDialog classes. Does not return until the command has finished executing. To generate run() calls, start the recorder (Plugins/Macro/Record) and run commands from the ImageJ menu bar.

You can also use the GUI to record a macro, Plugins->Macros->Record..., set the record mode to Java, and select the methods and threshold values you want. You will obtain something like this:

// Color Thresholder 1.49i
// Autogenerated macro, single images only!
min=newArray(3);
max=newArray(3);
filter=newArray(3);
a=getTitle();
run("HSB Stack");
run("Convert Stack to Images");
selectWindow("Hue");
rename("0");
selectWindow("Saturation");
rename("1");
selectWindow("Brightness");
rename("2");
min[0]=139;
max[0]=254;
filter[0]="pass";
min[1]=48;
max[1]=110;
filter[1]="pass";
min[2]=189;
max[2]=255;
filter[2]="pass";
for (i=0;i<3;i++){
  selectWindow(""+i);
  setThreshold(min[i], max[i]);
  run("Convert to Mask");
  if (filter[i]=="stop")  run("Invert");
}
imageCalculator("AND create", "0","1");
imageCalculator("AND create", "Result of 0","2");
for (i=0;i<3;i++){
  selectWindow(""+i);
  close();
}
selectWindow("Result of 0");
close();
selectWindow("Result of Result of 0");
rename(a);
// Colour Thresholding-----------------
Ortomala Lokni
  • 56,620
  • 24
  • 188
  • 240
  • Be careful, the code recorded by the *Threshold Color* plugin is **macro code**, not Java. You can however get valid Java code with the recorder if you convert your RGB image to 8-bit first, or you split the channels via *Image > Color > Split Channels*. – Jan Eglinger Jun 22 '15 at 16:07
  • @JanEglinger you are right that above code is not Java code - it is not useful in that case. If I change image to 8-bits I lost part of information. What if I split channels? Can I do binarization as effective as with 24-bit image? – trojek Jun 22 '15 at 17:57
  • Ortomala Lokni - My code (after modifications) is from "Plugins->Macros->Record...". Threshold metod recorded is: "//IJ.run("Threshold...");". As you can see at the begining there are "//" (Java comment sign) - probably because in Threshold Color window there is no options like "OK" or "Apply". I can't figure out what is correct form of threshold comand for 24-bit images. – trojek Jun 22 '15 at 18:06
  • @JanEglinger I splitted channels as you suggested. I was looking at macro records while using threshold method on 8-bits image. There is Java method: "IJ.setAutoThreshold(imp, "Li dark")" which works fine on 8-bit images. I'm looking for analogous method for 24-bit images. – trojek Jun 22 '15 at 19:01
  • @trojek If you **set the record mode to Java**, you obtain valid Java code. The code in my answer is valid java code. All methods are static methods of the [IJ class](http://rsbweb.nih.gov/ij/developer/api/ij/IJ.html). You juste have to do a static import like this : `import static ij.IJ.*` – Ortomala Lokni Jun 23 '15 at 14:26
  • @OrtomalaLokni How do you want to use static functions outsie of the class (in plugin class)? it doesn't suit to object oriented programming approach. – trojek Jun 23 '15 at 20:03
  • @trojek Sure you can, read http://docs.oracle.com/javase/1.5.0/docs/guide/language/static-import.html – Ortomala Lokni Jun 23 '15 at 20:35
1

The auto-threshold methods in the Threshold dialog all are algorithms working on single channel (8-bit or 16-bit) images. In the Color Threshold dialog, they are applied exclusively to the Brightness channel of your 24-bit color image.

To reproduce this in Java, use the following code:

IJ.run(imp, "HSB Stack", "");
imp.setSlice(3);
IJ.setAutoThreshold(imp, "Triangle dark");
Prefs.blackBackground = true;
IJ.run(imp, "Convert to Mask", "only");

(Converting your image to 8-bit is nothing else than using the Brightness channel, discarding the Hue and Saturation information. Unless you really make use of the other sliders in the Color Threshold dialog, you can just as well convert the image to 8-bit before applying the threshold.)

Jan Eglinger
  • 3,995
  • 1
  • 25
  • 51
  • Your code look correct, but when I change method (e.g. method=IsoData, method=Huang etc.) I'm allways getting result as I use "default" method. – trojek Jun 22 '15 at 21:35
  • The code was missing an `IJ.setAutoThreshold` call. I edited my answer accordingly. Apparently, the method chosen in the "Convert to Mask" dialog is being ignored, which might be a bug: you can report this via *Help > Report a bug* in the menu. – Jan Eglinger Jun 23 '15 at 11:14