ImageJ Batch Processing for Analyze Particles Function

I am pulling my hair out trying to figure this out! I really appreciate these forums, but despite my best effort to put it all together, my Image J code keeps failing. I would really really REALLY appreciate some help with this specific code. When I execute this code via PROCESS>BATCH it just takes my original photos and puts them into the Output folder unchanged. When I execute this code via Plugins>Macros>Run, nothing at all happens! What I hope to see in the Output folder is one CSV with the Analyze Particle results for each image (JPG) that is in the Input folder. Also, I will need the CSV name to contain the original JPG name in it. Bonus if I could get the “outline” drawing saved somehow that also results from the Analyze Particles, but I haven’t seen any code on that. Thank you so much for your help in advance!

function action(input, output, filename) {
open(input + filename);
run(“Set Measurements…”, “area display redirect=None decimal=3”);
//setTool(“line”);
makeLine(208, 624, 344, 622);
run(“Set Scale…”, “known=10 unit=cm global”);
run(“Color Threshold…”);
// Color Thresholder 1.52a
// 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]=0;
max[0]=255;
filter[0]=“pass”;
min[1]=0;
max[1]=255;
filter[1]=“pass”;
min[2]=0;
max[2]=118;
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-------------
run(“Close”);
run(“Analyze Particles…”, “size=0.5-Infinity show=Outlines display include”);
saveAs(“csv”, output + filename);
close();
}
input = “C:\Users\Katrina\Desktop\Example Images\Cropped”
output = “C:\Users\Katrina\Desktop\Example Images\Output”
setBatchMode(true);
list = getFileList(input);
for (i = 0; i < list.length; i++)
action(input, output, list[i]);
setBatchMode(false);

I tried this too, thinking the simpler code would work, but to no avail. I don’t care which works, just as long as I can get the results csvs to save and ideally the outline drawings as well.

function action(input, output, filename) {
open(input + filename);
run(“8-bit”);
run(“Set Measurements…”, “area display redirect=None decimal=3”);
//setTool(“line”);
makeLine(208, 624, 346, 625);
run(“Set Scale…”, “known=10 unit=cm global”);
setAutoThreshold(“Default”);
//run(“Threshold…”);
//setThreshold(0, 108);
setOption(“BlackBackground”, false);
run(“Convert to Mask”);
run(“Close”);
run(“Analyze Particles…”, “size=0.5-Infinity show=Outlines display include”);
selectWindow(“InkedCapture1_LI-1.jpg”);
selectWindow(“Drawing of InkedCapture1_LI-1.jpg”);
saveAs(“Results”, output+filename);
close();
}
input = “C:\Users\Katrina\Desktop\Example Images\Cropped”
output = “C:\Users\Katrina\Desktop\Example Images\Output”
setBatchMode(true);
list = getFileList(input);
for (i = 0; i < list.length; i++)
action(input, output, list[i]);
setBatchMode(false);

Hi @mamabirdblue, welcome to the forum !

I think most of your problems come from the fact that your directory is not correct. A / (or ) is probably missing.
You should add + File.separator between input and filename (and same with output)

for the .csv, you could add a + “.txt” at the end.
For saving the outline drawing, you could consider save them either as ROI either as overlay.

Nico

1 Like

@VirtualSlide thank you so much for you prompt response. Unusually, the input and output directory when I go to edit shows with a slash at the end (like below) but when I publish it, the last slashes disappear. No idea what is up with that. For your first recommendation, is that what you meant, adding a \ at the end? Or did you mean something different? Replace \ with /?

input = “C:\Users\Katrina\Desktop\Example Images\Cropped”
output = “C:\Users\Katrina\Desktop\Example Images\Output”

For your second suggestion, I don’t understand where I should add the command +File.separator exactly. Can you show me how it should be applied to Input and Output?

And for the outline drawing, your recommendations is totally over my head! Some more guidance would be great, but this is a secondary priority of mine.

Thank you! Thank you!

There are several flaws here.

  1. Avoid jpegs in your analysis since it produces artifacts.

  2. Don’t use you first macro example in the Process->Batch->Macro GUI because you already iterate over the folder with the last part of the code:

setBatchMode(true);
list = getFileList(input);
for (i = 0; i < list.length; i++) {	
    action(input, output, list[i]);
}
action(input, output, list[i]);
setBatchMode(false);
  1. At the end of your first example you close all images so there is nothing to analyze for the Particle Analyzer.

Here I extracted the core of your macro for a reproducible example (I changed the coordinates of the makeLine function for this example, too). Please debug to see that all images are closed. The last image is closed after the line:
// Colour Thresholding-------------
run("Close");

open("https://rsb.info.nih.gov/ij/images/leaf.jpg")
run("Set Measurements...", "area display redirect=None decimal=3");
//setTool("line");
makeLine(208, 324, 344, 322);
run("Set Scale...", "known=10 unit=cm global");
run("Color Threshold...");
// Color Thresholder 1.52a
// 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] = 0;
max[0] = 255;
filter[0] = "pass";
min[1] = 0;
max[1] = 255;
filter[1] = "pass";
min[2] = 0;
max[2] = 118;
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-------------
run("Close");
run("Analyze Particles...", "size=0.5-Infinity show=Outlines display include");
  1. It would also be nice to see at least some of your images so that the forum can reproduce and debug the code sufficiently. However a complete reproducible example is preferred to minimize the amount of time to help efficiently.

  2. Make sure that your core macro with one image works before you apply it on a folder of images, see:

  1. The file paths on windows should be with a forward slash or use the function File.separator as @VirtualSlide suggested. So do something like:

input = “C:/Users/Katrina/Desktop/Example Images/Cropped”

or Windows specific only:
input = “C:\\Users\\Katrina\\Desktop\\Example Images\\Cropped”

The meaning of File.separator:
https://imagej.nih.gov/ij/developer/macro/functions.html#File.separator

The function File.separator was introduced e.g., in Java to to give you a OS independant function
for the separator string (for a maybee not yet known different implementations of a new OS). However all major OS support the forward slash.

A further comment, you do not need this line:

run("Color Threshold...");

because after it, you already recorded the procedures that threshold a colour image.

Wow! This community is impressive! Thank you for all your feedback @VirtualSlide, @Bio7, @gabriel. I don’t have a lot of formal training for coding, as I am sure is quite evident, but I am doing my best. I have found a very easy solution, and I will share it here for other newbies like me.

I just wanted to apply a specific sequence of actions to all the files in a single folder. When researching batch processing, I went down a vast and deep rabbit hole of complex (for me!) coding recommendations that, no matter how easy the forum or youtube video made it look, could not pull off no matter how hard I tried. It was not until I watched these very simple videos (links below) did I realize that there was no need for that extensive batch processing code when using the Process>Batch menu item. Also, I learned that the whole “make sure that your core macro with one image works before you apply it on a folder of images” recommended by @Bio7 is super important. Recently, I tried this and found that when I would do a workflow, save, then apply to the same image, it would fail (i.e. the results were not the same as the first go around). I never identified why it failed, but I just tried a few iterations with steps in different orders until I got it to work on the original image. Then, just opened that recorded macro into the Process>Batch and it worked flawlessly on all pictures in the INPUT folder directory!

Here are the SHORT videos I watched that took days of flopping around and helped me solve my problems quite quickly:

Recording and Running a Macro: https://www.youtube.com/watch?v=r6vB22Zj7PI&t=1s
Batch Macro Analysis: https://www.youtube.com/watch?v=Cq1e7n_ULlU&t=13s

I also found issues with the Color Threshold command I was executing, as it would not work consistently across all photos. So, I switched to having my photos convert to 8-bit, then just ran the Threshold command instead of the Color Threshold. Using Process>Batch, her is my simplified macro here:

run(“Set Measurements…”, “area display redirect=None decimal=3”);
run(“8-bit”);
//setTool(“line”);
makeLine(212, 622, 344, 622);
run(“Set Scale…”, “distance=132 known=10 pixel=1 unit=cm global”);
//run(“Threshold…”);
setAutoThreshold(“Default”);
//run(“Threshold…”);
run(“Analyze Particles…”, “size=0.8-Infinity show=Outlines display include”);
saveAs(“Results”, “C:/Users/Katrina/Desktop/Example Images/Output/Results.csv”);
saveAs(“Tiff”, “C:/Users/Katrina/Desktop/Example Images/Output/Drawing of InkedCapture1_LI.tif”);
close();

I am still working on trying to get the saveAs to save to the OUTPUT folder indicated in the Batch Output selection so that I don’t have to edit the code if using on another computer or folder. Also, still trying to get all of the “Drawings of InkedCaptured#_LIs” for all images in the folder to save instead of just the 1 that I used to record the macro. Simple things, but still haven’t gotten those to work out, but I’m getting close! If you had any ideas for those few remaining things, that would be great!

Once again, thank you! This has been really helpful!

I was able to solve one of the two remaining issues above by deleting the close() at the end of the macro. This allows each image being batch processed to save an “Outline”. Before using this script, I will also make sure to resize each image so that the “Set Scale” is consistent across all images.