LabCanvas

ImageJ macros for beginners: record a macro and batch-process a folder

Record an ImageJ macro with Plugins › Macros › Record, run it from the editor, then batch-process a folder with Process › Batch › Macro. Step by step.

ImageJ 1.54f running a recorded macro: the macro editor with eight recorded lines, the Summary table with 70 nuclei and an average size of 40.394 µm², and the numbered outlines of the nuclei
ImageJ 1.54f running a recorded macro: the macro editor with eight recorded lines, the Summary table with 70 nuclei and an average size of 40.394 µm², and the numbered outlines of the nuclei.
Contents

To make an ImageJ macro without writing code, choose Plugins › Macros › Record…, do your analysis once with the normal menus, then click Create in the Recorder: the commands you used appear as macro lines in the editor, and Run (Ctrl R) repeats them. To run the same macro on a whole folder, choose Process › Batch › Macro…, set the input and output folders, paste the lines without the open() line and click Process; ImageJ opens every file in turn and the Summary table gets one row per image.

This page shows each step with a screenshot of ImageJ 1.54f: we record a short nuclei count (threshold, clean-up, Analyze Particles), turn it into a macro, run it, and then run it over a folder of three images.

What you need: ImageJ 1.x or Fiji (the steps are the same in both). An image of bright objects on a dark background; we use our synthetic nuclei sample (a generated image with 70 nuclei, 512 × 512 pixels, 16-bit, 0.325 µm per pixel). About 15 minutes.

What is an ImageJ macro?

A macro is a text file of ImageJ commands that runs them in order, the same way every time. It is written in the ImageJ macro language, a small scripting language built into ImageJ; files end in .ijm. Most lines look like this:

run("Watershed");
run("Analyze Particles...", "size=7-Infinity show=Outlines display summarize");

The first part is the menu command's name; the second holds the dialog settings you chose. You rarely need to type these yourself: the Recorder writes them while you click.

Record a macro, step by step

Step 1: Open the Recorder

Choose Plugins › Macros › Record…. A window called Recorder opens with an empty text area. Leave Record: on Macro. You can type a name such as Count_Nuclei.ijm in Name; the Create button is for the end.

ImageJ Recorder window opened from Plugins › Macros › Record, empty, with Record set to Macro, the Name field and the Create button marked
Step 1: the Recorder, empty. Keep Record: Macro 1, give the macro a name 2 and click Create only when you have finished 3.

Keep the Recorder open for the whole job. Everything you do from now on is written into it, including mistakes, which you can delete later.

Step 2: Open the image

Choose File › Open… and pick your image. The Recorder writes an open() line with the full path of the file.

ImageJ with the nuclei sample open and the Recorder showing the line open/root/Images/nuclei.tif;
Step 2: the nuclei sample opens 1 and the Recorder writes open…/nuclei.tif; with the file's path 2. This is the one line you remove later for batch processing.

Step 3: Threshold the nuclei

Choose Image › Adjust › Threshold…. Pick Otsu in the left list, tick Dark background (the nuclei are brighter than the background) and click Apply. The nuclei turn red first, then the image becomes a black-and-white mask.

ImageJ Threshold window with Otsu chosen, Dark background ticked and the Apply button marked; the Recorder shows setAutoThresholdOtsu dark
Step 3: Otsu 1 with Dark background 2 selects 10.22% of the image, the nuclei in red. Apply 3 makes the mask. The Recorder writes setAutoThresholdOtsu dark; 4.

When you click Apply, ImageJ records two more lines: setOption("BlackBackground", true); and run("Convert to Mask");.

Step 4: Clean up the mask

Choose Process › Binary › Fill Holes, then Process › Binary › Watershed. Fill Holes closes any dark gaps inside a nucleus; Watershed cuts touching nuclei apart with a one-pixel line.

ImageJ mask of the nuclei, white on black, and the Recorder showing Convert to Mask, Fill Holes and Watershed
Step 4: the mask, nuclei white on black 1. Both commands appear in the Recorder 2, one line each.

Step 5: Count with Analyze Particles

Choose Analyze › Analyze Particles…. Type 7-Infinity in Size (micron^2) to ignore specks smaller than 7 µm², set Show to Outlines, tick Display results and Summarize, and click OK.

ImageJ Analyze Particles dialog with size 7-Infinity, Show Outlines, Display results and Summarize ticked, next to the mask and the Recorder
Step 5: Size 7-Infinity 1, Show: Outlines 2, Summarize ticked 3, then OK 4. The size is in µm² because the image carries its pixel size.

ImageJ counts 70 nuclei. You will see that number again in Step 7.

Step 6: Click Create

Go back to the Recorder. It now holds your whole workflow, one line per step. Click Create. The lines open in the macro editor, a new text window with its own menus.

ImageJ Recorder with eight recorded lines from open to Analyze Particles, with the Create button marked
Step 6: the Recorder after the job. Click Create 1; the eight lines 2 become a macro.

The line //run("Threshold..."); starts with two slashes, so it is a comment: ImageJ skips it. It only reminds you that the Threshold window was open.

Step 7: Run the macro

Close the image and its results, then click Run in the editor (or press Ctrl R). ImageJ opens the file again and repeats every step on its own. Save the macro with File › Save As in the editor; keep the .ijm ending.

ImageJ macro editor with the recorded macro and the Run button marked
Step 7: the macro editor. Run 1 repeats the steps. Change a setting here, for example the size range, and run again.

The result is the same as by hand: the Summary table, the Results table and the outline drawing.

ImageJ after running the recorded macro: the editor, the Summary table with Count 70 and Average Size 40.394, and the numbered outlines
The macro's result on the nuclei sample: Count 70 1, Total Area 2827.581 µm², Average Size 40.394 µm² 2, %Area 10.212, and the outline drawing with every nucleus numbered 3.

The Mean in the Summary is 255 because the macro measured the mask, not the original image. If you need intensities, set Analyze › Set Measurements… › Redirect to the original image before you record Step 5.

The macro, line by line

Here is the recorded macro with a comment on each line. Anything after // is a note for people; ImageJ ignores it.

open("/root/Images/nuclei.tif");        // open one file (fixed path: remove for batch)
setAutoThreshold("Otsu dark");          // Otsu threshold, objects brighter than background
//run("Threshold...");                  // a comment: the Threshold window was open
setOption("BlackBackground", true);     // masks are white objects on black
run("Convert to Mask");                 // apply the threshold: an 8-bit mask
run("Fill Holes");                      // close gaps inside each nucleus
run("Watershed");                       // split touching nuclei
run("Analyze Particles...", "size=7-Infinity show=Outlines display summarize");
                                        // count objects of 7 µm² or more, draw outlines,
                                        // list every object and add a Summary row

To change the analysis, edit the text, not the menus: "size=7-Infinity" to "size=10-Infinity", or "Otsu dark" to "Triangle dark". Settings you leave out of the options string take their default values, so keep everything the Recorder wrote.

Batch-process a folder, step by step

The recorded macro works on one fixed file. Process › Batch › Macro… runs the same lines on every image in a folder without that open() line. We made a folder with three copies of the nuclei sample to try it.

Step 1: Put the images in one folder

Make a folder that holds only the images to analyse (here nuclei_01.tif, nuclei_02.tif and nuclei_03.tif). Make a second, empty folder for the output.

A file dialog showing the folder /root/Images/in with three files: nuclei_01.tif, nuclei_02.tif and nuclei_03.tif
Step 1: the input folder 1 with three copies of the sample. Keep other files out of it, or use File name contains in the next step to filter them.

Step 2: Fill in Process › Batch › Macro…

Choose Process › Batch › Macro…. Click Input… and pick the image folder; click Output… and pick the empty folder. Leave Output format on TIFF. Paste the recorded lines into the big text box, without the open() line: Batch opens each file for you.

ImageJ Batch Process dialog with input and output folders, TIFF output format, the recorded macro lines pasted without open, and the Process button
Step 2: Input 1 and Output 2 folders, TIFF 3, the recorded lines minus open 4. Test runs the code on the first image only; Process 5 runs it on all of them.

Click Test first if you are unsure: it runs the code on the first image only, so you can check the result before committing to a folder of 500 files.

Step 3: Click Process and read the Summary

Click Process. ImageJ opens each file, runs the lines and saves the result in the output folder. With Show: Outlines, the saved files are the outline drawings. Because the code has summarize in it, the Summary table gets one row per file.

ImageJ Summary table after Process › Batch › Macro with three rows, nuclei_03.tif, nuclei_01.tif and nuclei_02.tif, each with Count 70
Step 3: the Summary after the batch. Each copy gives 70 nuclei 1, 2827.581 µm² in total and 40.394 µm² on average, as it should for identical images.

Save it with File › Save As… in the Summary window (a .csv opens in any spreadsheet). On our Linux test the files were processed in the order the system listed them (03, 01, 02), not alphabetically; match rows by the file name in the first column, not by row number.

A folder loop, if you want to go one step further

Batch › Macro is the easy route. The same job as a stand-alone macro uses getFileList() and a for loop. It does not need the Batch dialog, asks for the folder when it starts, and is a good first piece of real macro code to read:

// Count nuclei in every TIFF in a folder
input = getDirectory("Choose the folder of images");   // a folder dialog opens
list = getFileList(input);                              // every file name in it
setBatchMode(true);                                     // work without drawing windows
for (i = 0; i < list.length; i++) {
    if (!endsWith(list[i], ".tif")) continue;           // skip anything that is not a TIFF
    open(input + list[i]);
    setAutoThreshold("Otsu dark");                       // the recorded lines start here
    setOption("BlackBackground", true);
    run("Convert to Mask");
    run("Fill Holes");
    run("Watershed");
    run("Analyze Particles...", "size=7-Infinity summarize");
    close();                                             // close the mask before the next file
}
setBatchMode(false);

Paste it into Plugins › New › Macro, click Run and choose the folder. On our three copies it gave the same Summary as Batch › Macro (70 nuclei each), with the files in alphabetical order.

Pitfalls

  • The open() line in Batch. Batch opens each file itself. Leaving open() in makes every pass open the first image again, so every row describes the same file.
  • Fixed window titles. A recorded selectWindow("nuclei.tif") breaks on the second file. Use getTitle() to store the title, or the image ID.
  • The Threshold window's numbers. The Recorder writes the method (setAutoThreshold("Otsu dark")), not a fixed value. That is usually what you want: each image gets its own Otsu threshold. If you dragged the sliders to a fixed value, the Recorder writes setThreshold(lower, upper) instead, which suits images taken with identical settings only.
  • Measuring the mask. Mean, IntDen and other intensity columns refer to the mask (255) unless Set Measurements redirects them to the original image.
  • Mixed images in one folder. A different bit depth or pixel size changes what a threshold or a size in µm² means. Check a few files by hand, then batch.
  • An output folder that is not empty. Batch overwrites files with the same name. Use a new folder for each run.

Reporting it

Nuclei were counted in [ImageJ 1.54f / Fiji] with a recorded macro applied to every image through Process › Batch › Macro: Otsu threshold (dark background), Fill Holes, Watershed and Analyze Particles (size ≥ 7 µm²). The macro is provided as Supplementary File 1.

Sharing the .ijm file is the best methods description you can give: it states every setting exactly.

Switch to LabCanvas: batch counting without a macro

The same count runs in the browser in LabCanvas Image Analysis, with the settings on screen instead of in code: nothing to install, and no macro language to learn (LabCanvas has none).

  1. Open an image (or the nuclei sample on the start screen) and go to Count › Count particles. Pick Otsu, tick fill holes and watershed, set the size range, and click Count.
  2. Open Count › Batch and choose Files… (or run it on every open image). Each file is opened in turn with the same settings.
  3. Read the Summary: one row per image, and every particle if you ask for them. Send to Graphs plots the counts by image, with statistics.
  4. For a guided assay (colonies, foci, wound healing and others), Save as workflow keeps its settings under a name and runs them on many files.
Counting nuclei in LabCanvas Image Analysis
Counting nuclei: 70 nuclei counted Otsu threshold, watershed to split touching ones: mean area 40.47 µm², 10.2% of the field.

On the same nuclei sample LabCanvas counts the same 70 nuclei; its mean area is 40.47 µm² against ImageJ's 40.394 µm², a difference of 0.2% that comes from how the two outline the edge pixels.

Why switch for this job:

  • No code to maintain: the settings sit in the panel, and a saved workflow keeps them under a name.
  • An image check flags saturated pixels, JPEG compression and uneven light before a batch silently measures them.
  • Results straight to Graphs, with a methods sentence under every table.

What stays better in Fiji: a macro can do anything ImageJ can, in any order, on thousands of files, with plugins in the middle. For complex pipelines, keep the macro.

Open Image Analysis, free with a LabCanvas account (downloading files is part of Pro).

ImageJ and Fiji are independent open-source projects; LabCanvas is not affiliated with them.

References

  • Schneider CA, Rasband WS, Eliceiri KW (2012). NIH Image to ImageJ: 25 years of image analysis. Nature Methods 9(7), 671–675. doi:10.1038/nmeth.2089
  • Schindelin J, Arganda-Carreras I, Frise E, et al. (2012). Fiji: an open-source platform for biological-image analysis. Nature Methods 9(7), 676–682. doi:10.1038/nmeth.2019

Frequently asked questions

How do I record a macro in ImageJ?

Choose Plugins › Macros › Record…, leave Record set to Macro, then do your work with the normal menus. Each command you run is written into the Recorder window as one line of macro code. When you are done, click Create to open the lines in the macro editor, where Run (Ctrl R) repeats them.

How do I batch process a folder of images in ImageJ?

Put the images in one folder, choose Process › Batch › Macro…, set Input to that folder and Output to an empty folder, paste the recorded lines (without the open() line) into the text box and click Process. ImageJ opens each file, runs the code, saves the result in Output, and any Summary table collects one row per file.

What language are ImageJ macros written in?

The ImageJ macro language (IJM), a small scripting language built into ImageJ. Most lines are run("Command name", "options") calls, which is exactly what the Recorder writes, plus variables, if and for statements and built-in functions such as open(), getFileList() and setAutoThreshold(). Fiji also runs scripts in Python (Jython), Groovy and JavaScript.

Why does my recorded macro not work on other images?

The usual cause is the open() line with one fixed file path, or a window title that only exists for the first image (selectWindow("nuclei.tif")). Remove the open() line when you use Process › Batch › Macro, and use getTitle() or the image ID instead of fixed titles. Also check that the other images have the same bit depth and pixel size.

Where do I save an ImageJ macro?

In the macro editor, File › Save As, with the .ijm extension. To run it later, use Plugins › Macros › Run… or open it and click Run. Saved in the ImageJ (or Fiji) plugins folder with an underscore in its name, for example Count_Nuclei.ijm, it appears in the Plugins menu after a restart.

Is there a way to batch-process images without writing a macro?

Yes. LabCanvas Image Analysis runs the same threshold, watershed and Analyze Particles settings on a whole set of files from Count › Batch, in the browser, with no macro language. See the last section.

imagej macroimagej macrosmacro language imagejimagej macro recorderimagej batch processingbatch processing imagejProcess Batch MacroAnalyze ParticlesFiji macroautomate ImageJ

Try it in LabCanvas

Every app is free to start in your browser. Create an account and begin.

Start Image Analysis free in your browser