See also the Introduction into Macro Programming and Batch Processing articles.
##介绍
ImageJ的一大优势是其自动化工作流程的能力。如果您需要自动化工作流程,有多种选择:
1.The macro recorder 2.Batch Processing 3.Script Templates 4.Multiple Image Processor
请注意,上面的列表并不好看!在本教程中,我们将探索选项#1。但是,建议尝试上述其他选项 - 您可能会发现替代方法(或者可能是方法的组合)更适合您的要求。
本教程概述
本教程演示了如何
- 使用the macro recorder一系列命令,形成宏的基础 2.编辑宏录制器的输出,以便它可以在任何打开的图像上运行 3.将步骤2中的代码包含在一个循环中,以便它在多个图像上运行 4.添加一些细节更新 5.添加一个表单,以便用户可以在执行之前修改宏的参数
本教程使用了来自Image Data Resource的数据,which is browsable online。从IDR下载图像的说明为here。下面我们概述了一个简单的宏,旨在对10个此类图像中的细胞核进行统计;这是这样的图像的示例:

使用宏记录器记录命令
启动宏录制器
要启动宏录制器,请转到File › Save As…:

您现在通过 ImageJ 菜单访问的每个命令都将在记录宏器中记录为一行文本。
The vast majority of the functionality in ImageJ/Fiji’s menus is macro-recordable. Occasionally, some commands will not be recorded, or not recorded correctly. Please refer to the documentation and image.sc in such cases.
执行一个简单的工作流程
执行一系列您想要使用宏自动执行的命令。

下面记录的命令来自:
- 使用Bio-Formats打开图像,将通道分割成单独的窗口。 2.选择包含细胞核的第一个通道

3.应用高斯模糊

4.使用默认方法对图像进行阈值处理

5.使用Watershed算法分离边界对象

- 使用Analyze Particles工具中的
summarize选项生成人口统计。
上面记录的命令的结果如下所示:

编辑宏录制器的输出
直接可以在宏录制器中编辑命令,但使用Script Editor可能更容易。您可以通过单击Create按钮直接从宏录制器启动脚本编辑器。

保存宏并运行它
为您的宏指定一个合理的名称,然后转到脚本编辑器中的§§0§§§来保存它。现在尝试通过从菜单中选择Plugins › Macros › Record来运行宏。您的宏应该会产生与您之前录制的一系列命令相同的输出。如果您想复制上面的代码,请复制如下:
run("Bio-Formats Importer", "open=[C:/Users/barryd/Downloads/FrancisCrickInstitute-introduction-to-image-analysis-be5d061 (1)/FrancisCrickInstitute-introduction-to-image-analysis-be5d061/Data/idr0028/003003-10.tif] autoscale color_mode=Default rois_import=[ROI manager] split_channels view=Hyperstack stack_order=XYCZT");
selectImage("003003-10.tif - C=0");
run("Gaussian Blur...", "sigma=2");
setAutoThreshold("Default dark");
//run("Threshold...");
setOption("BlackBackground", false);
run("Convert to Mask");
run("Watershed");
run("Analyze Particles...", "exclude summarize");
saveAs("PNG", "C:/Users/barryd/Downloads/FrancisCrickInstitute-introduction-to-image-analysis-be5d061 (1)/FrancisCrickInstitute-introduction-to-image-analysis-be5d061/Data/segmentation_masks/003003-10.tif - C=0.png");
成就你的宏
当前形式的宏的明显问题是,它只能首先记录构成宏基础的命令时加载的图像作业。修改前两行是“百年”宏的第一步,以便它在_any_上图像运行:
run("Bio-Formats Importer", "autoscale color_mode=Default rois_import=[ROI manager] split_channels view=Hyperstack stack_order=XYCZT");
selectImage(1);
run("Gaussian Blur...", "sigma=2");
setAutoThreshold("Default dark");
setOption("BlackBackground", false);
run("Convert to Mask");
run("Watershed");
run("Analyze Particles...", "exclude summarize");
outputDir = getDirectory("Select Output Directory");
saveAs("PNG", outputDir + "segmentation_output.png");
上面有3个变化:
- 在第一行,提交之前给 Bio-Formats 的
open参数现在已被删除。因此,ImageJ 将生成一个文件打开对话框,要求用户指定他们使用生物格式打开哪个图像 - 在第二行中,
selectImage命令已修改为选择第一个图像窗口(假设这是带有细胞核信号的通道)。或者,我们可以通过Bio-Formats Importer语句来只打开图像中的第一个通道。 3.最后两行现在要求用户在维护分段掩码之前指定输出目录。
虽然这个宏现在可以在任何图像上运行,但它只允许我们一次处理一张图像,这并不理想!
创建一个在多个图像上运行的循环
其中,我们的宏选择一次只处理一张图像,要求用户将其作为输入。要自动分析文件夹中的多个图像,我们必须设置for循环。
将代码包含在 for 循环中
我们可以多次运行代码来处理多个图像,方法只需其包含在 for 循环中:
for (i = 0; i < 10; i++) {
run("Bio-Formats Importer", "autoscale color_mode=Default rois_import=[ROI manager] split_channels view=Hyperstack stack_order=XYCZT");
selectImage(1);
run("Gaussian Blur...", "sigma=2");
setAutoThreshold("Default dark");
setOption("BlackBackground", false);
run("Convert to Mask");
run("Watershed");
run("Analyze Particles...", "exclude summarize");
outpuDir = getDirectory("Select output directory");
saveAs("PNG", outputDir + "segmentation_output.png");
}
然而,上述代码存在一些问题: 1.要求用户在循环的每次迭代中指定输入图像和输出目录 2.循环将始终运行大约10次…
- …这将导致打开大量图像窗口
- 循环的每次迭代的输出图像将具有相同的名称
让我们一次处理其中的每一个。
获取输入目录
让我们在for循环之前添加一些代码以获取输入目录并从该输入目录获取文件列表。我们还可以将指定输出目录的代码行移动到此处,这样每次执行循环时就不会调用它:
inputDir = getDirectory("Select Input Directory");
images = getFileList(inputDir);
outputDir = getDirectory("Select Output Directory");
现在我们需要更新运行Bio-Formats Importer的命令,以便它在循环的每次迭代中打开不同的图像:
run("Bio-Formats Importer", "open=[" + inputDir + File.separator() + images[i] + "] autoscale color_mode=Composite rois_import=[ROI manager] view=Hyperstack stack_order=XYCZT");
The + sign allows for concatenating strings, while using the File.separator() command takes care of differences between operating systems in conventional file separator characters. Enclosing a folder path or file name with squared brackets [...] ensures that they are read as a single string even in the presence of spaces.
使用完毕后关闭窗口
当前形式的宏将在每次执行for循环时打开四个窗口(假设输入图像有四个通道)。其余值乘以循环执行的次数(当前为10),这就是很多窗口。我们通过在for循环内的代码块添加close语句来处理这个问题。在close语句中使用通符配(*)指示ImageJ关闭_所有_图片窗口:
close("*");
完整的宏现在看起来像这样……
inputDir = getDirectory("Select Input Directory");
images = getFileList(inputDir);
outputDir = getDirectory("Select Output Directory");
for (i = 0; i < 10; i++) {
run("Bio-Formats Importer", "open=[" + inputDir + File.separator() + images[i] + "] autoscale color_mode=Default rois_import=[ROI manager] split_channels view=Hyperstack stack_order=XYCZT");
selectImage(1);
run("Gaussian Blur...", "sigma=2");
setAutoThreshold("Default dark");
setOption("BlackBackground", false);
run("Convert to Mask");
run("Watershed");
run("Analyze Particles...", "exclude summarize");
saveAs("PNG", outputDir + "segmentation_output.png");
close("*");
}
…现在应该在运行时产生一些有意义的输出:

运行循环所需的次数
目前,无论输入目录有多少个图像,for循环中的代码将始终执行10次。我们可以更改此行为,以便在条件语句i < 10中放置更有意义的内容,例如:
for (i = 0; i < lengthOf(images); i++) {
这里,lengthOf命令返回images阵列的容量,for循环将继续执行,直到分析完成相应阵列中的所有图像。
更改输出图像的名称
最后,为了拥有一个功能齐全的(如果是初级的)宏,我们需要在 for 循环的每次迭代中更新分割输出图像的名称 - 目前,名称为 segmentation_output.png 的图像重复覆盖。我们可以修改被saveAs 的语句以在文件名中包含 i 的当前值,如下所示:
saveAs("PNG", outputDir + "segmentation_output_" + i + ".png");
这将导致输出保存图像为:
segmentation_output_0.png
segmentation_output_1.png
segmentation_output_2.png
...
为了提供更多信息,我们可以在输出图像文件名中包含输入文件名,如下所示:
saveAs("PNG", outputDir + "segmentation_output_" + images[i] + ".png");
对于名为 003003-10 的输入图像,此命令将返回 segmentation_output_003003-10.png 作为输出名称。
完整的剧本简介如下:
inputDir = getDirectory("Select Input Directory");
images = getFileList(inputDir);
outputDir = getDirectory("Select Output Directory");
for (i = 0; i < lengthOf(images); i++) {
run("Bio-Formats Importer", "open=[" + inputDir + File.separator() + images[i] + "] autoscale color_mode=Default rois_import=[ROI manager] split_channels view=Hyperstack stack_order=XYCZT");
selectImage(1);
run("Gaussian Blur...", "sigma=2");
setAutoThreshold("Default dark");
setOption("BlackBackground", false);
run("Convert to Mask");
run("Watershed");
run("Analyze Particles...", "exclude summarize");
saveAs("PNG", outputDir + "segmentation_output_" + images[i] + ".png");
close("*");
}
添加一些细节更新
在代码运行时让用户了解进度通常是一个好主意。我们可以通过在宏中的不同点添加print语句来实现这个点,这样就能打印到日志窗口中:
inputDir = getDirectory("Select Input Directory");
images = getFileList(inputDir);
outputDir = getDirectory("Select Output Directory");
setBatchMode(true);
print("\\Clear");
print("Found " + images.length + " files in " + inputDir);
print("0% of images processed.");
for (i = 0; i < lengthOf(images); i++) {
print("\\Update:" + (100.0 * i / images.length) + "% of images processed.");
run("Bio-Formats Importer", "open=[" + inputDir + File.separator() + images[i] + "] autoscale color_mode=Default rois_import=[ROI manager] split_channels view=Hyperstack stack_order=XYCZT");
selectImage(1);
run("Gaussian Blur...", "sigma=2");
setAutoThreshold("Default dark");
setOption("BlackBackground", false);
run("Convert to Mask");
run("Watershed");
run("Analyze Particles...", "exclude summarize");
saveAs("PNG", outputDir + "segmentation_output_" + images[i] + ".png");
close("*");
}
print("\\Update:100% of images processed.");
setBatchMode(false);
setBatchMode语句导致ImageJ进入然后退出“批处理模式”,这会抑制图像窗口。这使得宏执行得更快。
添加评论
向宏添加注释将提高其他以及我们未来自己的可重用性。您可以在行前使用 ImageJ 宏中的 // 符号添加注释:这将确保该行不会被执行。添加宏的注释如下所示:
// Ask user for input directory and obtain file list
inputDir = getDirectory("Select Input Directory");
images = getFileList(inputDir);
// Ask user for output directory
outputDir = getDirectory("Select Output Directory");
// Suppress image windows (not displayed to screen)
setBatchMode(true);
// Initialise progress update
print("\\Clear");
print("Found " + images.length + " files in " + inputDir);
print("0% of images processed.");
// Loop through images
for (i = 0; i < lengthOf(images); i++) {
// Update progress
print("\\Update:" + (100.0 * i / images.length) + "% of images processed.");
// Open image with Bio-Formats (split channels)
run("Bio-Formats Importer", "open=[" + inputDir + File.separator() + images[i] + "] autoscale color_mode=Default rois_import=[ROI manager] split_channels view=Hyperstack stack_order=XYCZT");
// Select the first channel
selectImage(1);
// Perform Gaussian blurring with sigma=2
run("Gaussian Blur...", "sigma=2");
// Threhold using the default algorithm
setAutoThreshold("Default dark");
setOption("BlackBackground", false);
run("Convert to Mask");
// Run Watershed to separate adjacent objects
run("Watershed");
// Measure morphological features
run("Analyze Particles...", "exclude summarize");
// Save segmentation mask
saveAs("PNG", outputDir + "segmentation_output_" + images[i] + ".png");
// Close all images
close("*");
}
// Print message when the analysis is finished
print("\\Update:100% of images processed.");
// Turn off batch mode
setBatchMode(false);
创建一个对话框来获取用户输入
作为使用上面的 getDirectory 语句的替代方案,可以创建一个功能更强大、独立的对话框来接收用户的输入。
指定输入和输出
我们可以和自定义Generic Dialog来获取用户的各种不同输入。我们还可以使用这个界面向用户提供指令。让我们从一个简单的创建对话框开始,提示用户指定输入和目录输出:
// Initialise variables
var inputDir;
var outputDir;
// Create dialog box
Dialog.create("Batch Counting");
Dialog.addDirectory("Input Directory:", inputDir);
Dialog.addDirectory("Output Directory:", outputDir);
Dialog.show();
// Update variables with user input
inputDir = Dialog.getString();
outputDir = Dialog.getString();
上面的代码做了三件事:
- 初始化输入和输出目录的两个变量。在示例中,这些变量被初始化为空变量,但如果需要,我们可以在此处添加特定的文件位置(例如
var inputDir = "C:/Users/barryd";) 2.创建一个包含两个目录选择字段和按钮的对话框 - 当用户通过单击
OK关闭对话框时获取用户指定的输入和输出目录。如果单击Cancel,则宏退出。
现在运行宏应该会产生以下对话框:

通过对话框修改参数
除了指定输入和输出目录之外,还有一系列其他用户控件可以添加到对话框中。例如,我们可以添加字段,允许指定… 1.高斯平滑的软骨半径
- ImageJ中可用的完整列表中的特定阈值方法 3.哪个通道对应原子核
请注意,我们可以使用默认值初始化对话框。
// Initialise variables
var inputDir;
var outputDir;
var gaussRad = 1.0;
var thresholdMethod = "Default";
var allThreshMethods = getList("threshold.methods");
var nucleiIndex = 1;
// Create dialog box
Dialog.create("Batch Counting");
Dialog.addDirectory("Input Directory:", inputDir);
Dialog.addDirectory("Output Directory:", outputDir);
Dialog.addNumber("Nuclear Channel:", nucleiIndex);
Dialog.addNumber("Gaussian Filter Radius:", gaussRad);
Dialog.addChoice("Threshold Method:", allThreshMethods);
Dialog.show();
// Update variables with user input
inputDir = Dialog.getString();
outputDir = Dialog.getString();
nucleiIndex = Dialog.getNumber();
gaussRad = Dialog.getNumber();
thresholdMethod = Dialog.getChoice();
For a full list of controls that can be added to a Dialog, see the relevant macro language documentation.
运行宏现在将产生一个如下所示的对话框:

为了使从模块中捕获的变量发挥作用,我们必须修改代码的其余部分,将变量放置在需要的位置。
请注意以下事项:
selectImage命令现在将nucleiIndex参数作为run("Gaussian Blur...")命令现在从gaussRad中获取其sigma参数setAutoThreshold使用thresholdMethod指定的任何方法 ```javascript // Obtain file list images = getFileList(inputDir);
// Suppress image windows (not displayed to screen) setBatchMode(true);
// Initialise progress update print(“\Clear”); print(“Found “ + images.length + “ files in “ + inputDir); print(“0% of images processed.”);
// Loop through images for (i = 0; i < lengthOf(images); i++) {
// Update progress
print("\\Update:" + (100.0 * i / images.length) + "% of images processed.");
// Open image with Bio-Formats (split channels)
run("Bio-Formats Importer", "open=[" + inputDir + File.separator() + images[i] + "] autoscale color_mode=Default rois_import=[ROI manager] split_channels view=Hyperstack stack_order=XYCZT");
// Select the channel containing nuclei
selectImage(nucleiIndex);
// Perform Gaussian blurring with specified sigma
run("Gaussian Blur...", "sigma=" + gaussRad);
// Threhold using the specified algorithm
setAutoThreshold(thresholdMethod + " dark");
setOption("BlackBackground", false);
run("Convert to Mask");
// Run Watershed to separate adjacent objects
run("Watershed");
// Measure morphological features
run("Analyze Particles...", "exclude summarize");
// Save segmentation mask
saveAs("PNG", outputDir + "segmentation_output_" + images[i] + ".png");
// Close all images
close("*"); }
// Print message when the analysis is finished print(“\Update:100% of images processed.”);
// Turn off batch mode setBatchMode(false);
完整的宏(包括对话框)现在如下所示:
```javascript
// Initialise variables
var inputDir;
var outputDir;
var gaussRad = 1.0;
var thresholdMethod = "Default";
var allThreshMethods = getList("threshold.methods");
var nucleiIndex = 1;
// Create dialog box
Dialog.create("Batch Counting");
Dialog.addDirectory("Input Directory:", inputDir);
Dialog.addDirectory("Output Directory:", outputDir);
Dialog.addNumber("Nuclear Channel:", nucleiIndex);
Dialog.addNumber("Gaussian Filter Radius:", gaussRad);
Dialog.addChoice("Threshold Method:", allThreshMethods);
Dialog.show();
// Update variables with user input
inputDir = Dialog.getString();
outputDir = Dialog.getString();
nucleiIndex = Dialog.getNumber();
gaussRad = Dialog.getNumber();
thresholdMethod = Dialog.getChoice();
// Obtain file list
images = getFileList(inputDir);
// Suppress image windows (not displayed to screen)
setBatchMode(true);
// Initialise progress update
print("\\Clear");
print("Found " + images.length + " files in " + inputDir);
print("0% of images processed.");
// Loop through images
for (i = 0; i < lengthOf(images); i++) {
// Update progress
print("\\Update:" + (100.0 * i / images.length) + "% of images processed.");
// Open image with Bio-Formats (split channels)
run("Bio-Formats Importer", "open=[" + inputDir + File.separator() + images[i] + "] autoscale color_mode=Default rois_import=[ROI manager] split_channels view=Hyperstack stack_order=XYCZT");
// Select the channel containing nuclei
selectImage(nucleiIndex);
// Perform Gaussian blurring with specified sigma
run("Gaussian Blur...", "sigma=" + gaussRad);
// Threhold using the specified algorithm
setAutoThreshold(thresholdMethod + " dark");
setOption("BlackBackground", false);
run("Convert to Mask");
// Run Watershed to separate adjacent objects
run("Watershed");
// Measure morphological features
run("Analyze Particles...", "exclude summarize");
// Save segmentation mask
saveAs("PNG", outputDir + "segmentation_output_" + images[i] + ".png");
// Close all images
close("*");
}
// Print message when the analysis is finished
print("\\Update:100% of images processed.");
// Turn off batch mode
setBatchMode(false);
安装宏
可以“install” macros in ImageJ,使它们出现在插件菜单上。虽然这对于运行宏来说并不是必需的,因为宏总是可以按原样打开和执行,但如果您需要定期运行脚本,这可能是添加一个好主意。因此,我们首先需要将宏包装在macro块中。macro之后,我们完整的宏现在如下所示:
macro "Batch Nuclei Counter" {
// Initialise variables
var inputDir;
var outputDir;
var gaussRad = 1.0;
var thresholdMethod = "Default";
var allThreshMethods = getList("threshold.methods");
var nucleiIndex = 1;
// Create dialog box
Dialog.create("Batch Counting");
Dialog.addDirectory("Input Directory:", inputDir);
Dialog.addDirectory("Output Directory:", outputDir);
Dialog.addNumber("Nuclear Channel:", nucleiIndex);
Dialog.addNumber("Gaussian Filter Radius:", gaussRad);
Dialog.addChoice("Threshold Method:", allThreshMethods);
Dialog.show();
// Update variables with user input
inputDir = Dialog.getString();
outputDir = Dialog.getString();
nucleiIndex = Dialog.getNumber();
gaussRad = Dialog.getNumber();
thresholdMethod = Dialog.getChoice();
// Obtain file list
images = getFileList(inputDir);
// Suppress image windows (not displayed to screen)
setBatchMode(true);
// Initialise progress update
print("\\Clear");
print("Found " + images.length + " files in " + inputDir);
print("0% of images processed.");
// Loop through images
for (i = 0; i < lengthOf(images); i++) {
// Update progress
print("\\Update:" + (100.0 * i / images.length) + "% of images processed.");
// Open image with Bio-Formats (split channels)
run("Bio-Formats Importer", "open=[" + inputDir + File.separator() + images[i] + "] autoscale color_mode=Default rois_import=[ROI manager] split_channels view=Hyperstack stack_order=XYCZT");
// Select the channel containing nuclei
selectImage(nucleiIndex);
// Perform Gaussian blurring with specified sigma
run("Gaussian Blur...", "sigma=" + gaussRad);
// Threhold using the specified algorithm
setAutoThreshold(thresholdMethod + " dark");
setOption("BlackBackground", false);
run("Convert to Mask");
// Run Watershed to separate adjacent objects
run("Watershed");
// Measure morphological features
run("Analyze Particles...", "exclude summarize");
// Save segmentation mask
saveAs("PNG", outputDir + "segmentation_output_" + images[i] + ".png");
// Close all images
close("*");
}
// Print message when the analysis is finished
print("\\Update:100% of images processed.");
// Turn off batch mode
setBatchMode(false);
}
在 ImageJ/Fiji 安装中找到 scripts 文件夹,将宏保存在 Plugins 子目录中。当您重新启动应用程序时,您现在应该会在“插件”菜单的底部看到您的宏出现:
