Set fixed Threshold in Macro

color-analysis
thresholding
macro
Tags: #<Tag:0x00007fb87b0f4bd8> #<Tag:0x00007fb87b0f49d0> #<Tag:0x00007fb87b0f4890>

#1

How do I set the threshold within a macro to be H 40-80 S 0-250 B 0-250?
The macro recorder only gives //run("Threshold...");


Saving values from a histogram
#2

When working with RGB color images, the Image > Adjust > Threshold menu command automatically runs the Threshold Color dialog. To get the macro code for the current threshold settings, simply press the Macro button:

// Color Thresholder 2.0.0-rc-44/1.50e
// 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]=40;
max[0]=80;
filter[0]="pass";
min[1]=0;
max[1]=255;
filter[1]="pass";
min[2]=114;
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-------------

#3

Thank you very much. Can this also be incorporated as to run with the multiple image processor? As I read on top of the code that it only works with single files.


#4

Just try it! :wink:

I think the comment in the autogenerated macro means that this block of code will not work on stacks, but only on single images.
I see no reason why it shouldn’t work with the multiple image processor, but if you want to have more granular control about how to process multiple files in a folder, have a look the the documentation on the wiki and start with the Process Folder template in the script editor (Templates > IJ1 Macro > Process Folder):


#5

Your code worked like a charm when run as you provided. I tried the following to make it run a batch, but after the prompts for input and output location, and filetype nothing happens. Also I thought I set the first two in the code, but apperently not.

/*
 * Macro template to process multiple images in a folder
 */

input = getDirectory("C:\Users\luuk\Documents\Stage\Julia");
output = getDirectory("C:\Users\luuk\Documents\Stage\Julia\Done");

Dialog.create("File type");
Dialog.addString("File suffix: ", ".tif", 5);
Dialog.show();
suffix = Dialog.getString();

processFolder(input);

function processFolder(input) {
    list = getFileList(input);
    for (i = 0; i < list.length; i++) {
        if(File.isDirectory(input + list[i]))
            processFolder("" + input + list[i]);
        if(endsWith(list[i], suffix))
            processFile(input, output, list[i]);
    }
}

function processFile(input, output, file) {
    // do the processing here by replacing
    // the following two lines by your own code
    makeRectangle(1212, 474, 2574, 2274);
    run("Crop");
    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]=40;
    max[0]=80;
    filter[0]="pass";
    min[1]=0;
    max[1]=255;
    filter[1]="pass";
    min[2]=114;
    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);
    makeLine(992, 364, 392, 1132);
    run("Set Scale...", "known=118 unit=mm");
    run("Analyze Particles...", "size=1000.00-Infinity display exclude include");
}
saveAs("Results", "C:\\Users\\luuk\\Documents\\Stage\\Results.xls");

#6

Please try to understand the code by going through it line by line: when you start running the processFile function, you have three input parameters (input, output and file) but there’s no open image yet.

You have to open your image using:

open(input + File.separator + file);

and you should close the current image at the end of the function, to avoid images piling up and filling memory:

close();

Please read the documentation of getDirectory. If you want to hardcode your directory instead of opening a dialog,

input = "C:\\Users\\luuk\\Documents\\Stage\\Julia";

will be sufficient.


#7

Hi Jan,

Thanks for the tip about the developer guide, although the documentation is very minimal it is of some use.
I thought it would be to start back at the basis, as this language is new for me, so I decided to run the code you provided at first as is. However that yields me no results. For some reason nothing gets printed.
I saw another macro as how to print text to a window ( http://imagej.net/macros/PrintToTextWindow.txt )
Since that worked I decided to add that to the code you initially provided resulting in this:

/*
 * Macro template to process multiple images in a folder
 */

input = getDirectory("Input directory");
output = getDirectory("Output directory");

Dialog.create("File type");
Dialog.addString("File suffix: ", ".jpg", 5);
Dialog.show();
suffix = Dialog.getString();



  requires("1.38m");
  title1 = "Text Window";
  title2 = "["+title1+"]";
  f = title2;
  if (isOpen(title1))
     print(f, "\\Update:"); // clears the window
  else
     run("Text Window...", "name="+title2+" width=72 height=8 menu");
  print(f, "test");


  processFolder(input);

function processFolder(input) {
    list = getFileList(input);
    for (i = 0; i < list.length; i++) {
        if(File.isDirectory(input + list[i]))
            processFolder("" + input + list[i]);
        if(endsWith(list[i], suffix))
            processFile(input, output, list[i]);
    }
}

function processFile(input, output, file) {
    // do the processing here by replacing
    // the following two lines by your own code
    print(f,"Processing: " + input + file);
    print(f,"Saving to: " + output);
}

The result is that it does open a text window, and it does print the line test. However still the print lines in the processFile function yield nothing.


#8

Did you select an input folder that actually contains some files with the suffix you provided? If the macro doesn’t find any matching file, it will not run the processFile function. These lines check the file suffix:

if(endsWith(list[i], suffix))
    processFile(input, output, list[i]);

#9

Yes there are 6 files which all have the suffix “.jpg”. Or would it be case sensitive, as my file explorer says “.JPG”, but I don’t think it makes a difference. I’ll also insert a print to indicate if there is an error and it does not reach the function processFile.

Edit: Yes it is case sensitive. There was the error -_-


#10

I think you made an error here, as this does not close the image. I looked in the documentation and close() closes the image and run(“Close”) closes everything if I am correct.


#11

Yep, you’re right. Glad that you figured out by yourself! I’ll edit my post above to correct this, so others reading up on this won’t get confused.


#12

Hi @imagejan,thanks for sharing this information! I started to work on ImageJ/fiji last week and so far, I’m surprised about this powerful tool to analyse images!! The code you shared, works for me, so, I would like to know why did you do three arrays (min, max and filter) instead of two (min and max)? and what is the meaning of “pass” in filter[…]=“pass”?
Do you have any information about threshold processing that you could share with me? I have not any experience with programming, so, any information should be useful to me.
Thank you very much in advance!


#13

Hi @JuanJimenez, welcome to the ImageJ forum!

The code from my first post above is what the Color Thresholder plugin records when you press the Macro button. The filter[] array is used to reflect the three pass checkboxes from the user dialog:

i.e. the result for the respective channel (Hue, Saturation, Brightness) will be inverted according to the status of these checkboxes, see the line:

if (filter[i]=="stop")  run("Invert");

in the recorded code.


First of all, have a look at the user guide section about thresholding. For general information, just read wikipedia. And if you want to dig in deeper on the Java level, the javadoc API documentation will help you.


#14

Thank you very much, @imagejan!!


#15

Dear @imagejan, I am working in a macro to separate different colors from a segmented image. Please see my segmented image below:

After image segmentation using the Trainable Weka Segmentation, I need to separate and measure different colors in the image. I have used the macro @ctrueden have shared in Counting areas with different colors topic. That code works perfect with individual images, but, I need to do this in a batch process. Please see below some lines I have written:

Input=getDirectory("Choose Direction File");
Outcome=getDirectory("Choose Output File");

    macro "Waterlogged Plants" {

	Images=getFileList(Input);

	for (j=0; j<Images.length; j++){
		open(Input + Images[j]);

	setBatchMode(true);

id = getImageID();
title = getTitle();

getHistogram(values, counts, 256);
for (i=0; i<256; i++) {
	if (counts[i] > 0) {
		setThreshold(values[i], values[i]);
		run("Create Mask");
		rename(title + "-" + values[i]);
		selectImage(id);
	}
}
	resetThreshold();
	
	selectImage(values[1]);
	saveAs("PNG", Outcome + title + "_Green" + ".png");
	
    selectImage(values[2]);
	saveAs("PNG", Outcome + title + "_Dead" + ".png");

	
	run("Set Measurements...", "area center perimeter area_fraction redirect=None decimal=3");
	run("Measure");
	}
}

All of mi pictures have the same pixel value (0, 128 and 255) from the histogram. I need to save and measure both the 0 and 128 labels (black and grey colors in picture). However, when I run my code it read all of the images in Input directory but just save and measure the picture number 1. I need to create a newArray according to values in the histogram (0, 128 and 255) and then save and measure it? Could you please give some hints to do that? I have been looking in forums and web but unfortunately I have had not succeed yet!
Hope I expressed it OK (English is not my first language). Happy to hear from you!
Regards,

Juan


#16

Hi

I am developing a macro in Mac.
I am not able to adjust my threshold once thresholded.
Recorder code:

setAutoThreshold("Huang dark");
//run("Threshold...") 

However this automatically thresholds the image with no ability to change the thresholded level.
Is there a way to threshold in a Mac macro whilst allowing for modification of the threshold level?

The macro works well in PC with just run("threshold…).

Thanks Gavin


#17

remove the comment slashes // to open the threshold dialog

setAutoThreshold("Huang dark");
run("Threshold...");

#18

Thanks i am now having trouble with the subsequent changes.

The thresholding or the make binary seems to have changed.

Do i need to press apply on threshold, or change the binary function?

run(“Make Binary”);


#19

maybe try something like this

run("Threshold...");
setAutoThreshold("Triangle");
setThreshold(0, 138);
waitForUser("adjust threshold slider, then hit OK");
run("Convert to Mask");

#20

If you specify:
setAutoThreshold(“Triangle”);
setThreshold(0, 138);
then you are not using an auto threshold method, but just setting the threshold manually to 138.
Please delete that line.