简介
ImageJ2和Fiji利用SciJava脚本框架,它many languages中的scripts。机制——#@参数、脚本指令、服务、脚本编辑器——语言与无关;仅支持其他语言的语法发生变化。介绍了这些机制。
本页上的大多数示例都是用 Groovy 编写的。它们可以直接适应大多数其他 SciJava 支持的语言。SciJava 脚本不是原始 ImageJ 的部分;对于 ImageJ 1.x 宏,请参阅macro language页面和original ImageJ developer documentation。
This page is about writing scripts. For running them from the command line, see Scripting Headless.
导入类、服务和函数
SciJava 脚本可以访问应用程序类路径上的任何类:ImageJ 和ImageJ2 API、SciJava 服务以及与Fiji 几十或通过update sites的任何其他安装。常规语言import语句指示常工作。
服务(由SciJava和ImageJ2提供的长期辅助对象)使用#@符号注入到脚本中——与用户输入所使用的符号相同。例如,PrefService负责将先前输入的值存储在内存中。
// Import the PrefService under the variable name pref
#@ PrefService pref
// Assign the currently opened image to variable imp
#@ ImagePlus imp
// Import a class from the original ImageJ
import ij.IJ
陈述脚本语言
文件由其扩展名来脚本标记(.groovy、.py、.bsh、…)。两个 SciJava 指令脚本允许显式声明其语言,覆盖(或替换)扩展提示。
语言社帮
顶部脚本的第 #! 行直接命名语言:
#!Python
print("Hello from a script declared as Python via shebang")
shebang 仅采用语言名称(或扩展名)。它必须出现在第一行。
脚本指令
更通用的#@script指令允许脚本声明其他模块元数据,包括其语言。语法为#@script(key1=value1, key2=value2, …)。支持的按钮包括:
| 关键 | 意义 |
|---|---|
name |
剧本的内部名称。 |
label |
人类歧视的标签(在菜单中使用)。 |
description |
更长的描述(工具提示文本)。 |
language |
按名称或扩展名的脚本语言(例如"Python"、"groovy")。 |
menuPath |
脚本出现在结构菜单中的;使用>作为分隔符。 |
menuRoot |
脚本菜单的标识符。 |
iconPath |
菜单旁边显示图标的路径。 |
priority |
模块优先级:first、extremely-high、very-high、high、normal、low、very-low、extremely-low、last。 |
| §§§20§§§ | 提示式脚本可以安全地无头运行。仅当未脚本进行显着的AWT/Swing调用时才设置。 |
| (其他) | 任何其他键/值对都存储为模块属性。 |
例子:
#@script(language="Python", headless=true, menuPath="Image > Import > My Text Importer...")
对图像进行操作
首先,我们要学习选择图像并执行其操作的不同方法。在原始的ImageJ中,图像由ImagePlus对象表示。选择ImagePlus对象的推荐方法是使用Script Parameters:
#@ ImagePlus imp
#@ Integer(label='Filter radius',description='The sigma of the gaussian filter.',value=2) sig
print(imp)
import ij.IJ
IJ.run(imp, "Gaussian Blur...", "sigma=" + sig)
脚本参数放置在脚本文件的开头。如果仅使用一个 ImagePlus,则选择最前面的图像。第二个脚本参数用于获取高斯芦荟的萃取物。通过使用 print(imp)我们验证 ImagePlus对象已分配给标记。
要对选定的图像执行操作,我们使用IJ.run()。因此我们必须导入IJ类。run() method有不同的版本,我们三个参数的版本。第一个参数是要执行图像操作的,第二个参数需要定义操作(称为命令),最后一个参数用于配置操作(这里我们设置过滤半径)。替换命令的最简单方法是使用Recorder。
第二种方法类似于如何使用 macro language 执行此操作:
import ij.IJ
imp = IJ.getImage()
sig = IJ.getNumber('Filter radius:', 2)
IJ.run(imp, "Gaussian Blur...", "sigma=" + sig)
第一步是使用IJ的方法getImage()选择最前面的图像。步骤是使用方法getNumber()显示一个对话框来输入过滤器半径。运行过滤器与前面的示例相同。
最后我们要使用WindowManager来选择最前面的图像:
import ij.IJ
import ij.WindowManager
imp = WindowManager.getCurrentImage()
sig = IJ.getNumber('Filter radius:', 2)
IJ.run(imp, "Gaussian Blur...", "sigma=" + sig)
这与IJ.getImage()的使用几乎相同,因此不推荐。WindowManager类包含一些有用的方法,可用于选择多个图像(例如getImageTitles()和getIDList()。
##打开图片
在 ImageJ 和 ImageJ2 中,有几种不同的方式来打开图像(到底通用的数据集)。我们想介绍其中的一些。
第一个示例使用DatasetIOService。它是SCIFIO的部分,这是一个针对 SCientific Image Format Input 和 Output 的灵活框架。打开两种类型的图像文件。第一个是从互联网下载的示例图像。第二个图像可以由用户选择。两个数据集均使用属于SciJava项目部分的UIService显示。
#@ DatasetIOService ds
#@ UIService ui
#@ String(label='Image URL', value='https://imagej.net/images/clown.jpg') fileUrl
#@ File(label='local image') file
// Load a sample file from the internet and a local file of your choice.
dataset1 = ds.open(fileUrl)
dataset2 = ds.open(file.getAbsolutePath())
// Display the datasets.
ui.show(dataset1)
ui.show(dataset2)
如果脚本仅依赖于 ImageJ 1.x 功能,则可以使用函数 IJ.openImage()。将返回一个 ImagePlus 对象。
#@ String(label='Image URL', value='https://imagej.net/images/clown.jpg') fileUrl
#@ File(label='local image') file
import ij.IJ
// Load a sample file from the internet and a local file of your choice.
imagePlus1 = IJ.openImage(fileUrl)
imagePlus2 = IJ.openImage(file.getAbsolutePath())
// Display the datasets.
imagePlus1.show()
imagePlus2.show()
IJ.openImage()基于类ij.io.Opener。您可以直接使用它来打开图像和其他文件(例如文本文件)。该示例使用类ij.io.OpenDialog来选择文件。这是使用脚本参数File的替代方法。
import ij.io.Opener
import ij.io.OpenDialog
// Use the OpenDialog to select a file.
filePath = new OpenDialog('Select an image file').getPath()
// Open the selected file.
imagePlus = new Opener().openImage(filePath)
// Display the ImagePlus.
imagePlus.show()
ImagePlus、ImageStack 和 ImageProcessor 转换
使用 ImageJ API 时,您会遇到以下问题: ImageProcessor,但你现在需要ImagePlus。
相当于一种转换为另一种,请使用以下命令:
// ImagePlus to ImageProcessor:
ip = imp.getProcessor()
// ImageProcessor to ImagePlus:
imp = new ImagePlus('title', ip)
// ImagePlus to ImageStack:
stack = imp.getImageStack()
// ImageStack to ImagePlus:
imp = ImagePlus('title', stack)
// ImageStack to ImageProcessor:
ip = stack.getProcessor(nframe)
// ImageProcessor to ImageStack:
stack.addSlice(ip)
以下方案描述了不同类之间的关系。 
在 ROI Manager 中循环 ROI
这个 ImageJ 宏脚本循环遍历小型 ROI 管理器中的 ROI,选择一次。
for (i = 0; i < roiManager("count"); i++){
roiManager("Select", i);
// do some operation
}
在 Jython 和其他脚本语言中,您可以直接迭代RoiManager:
from ij.plugin.frame import RoiManager
# Assume a RoiManager is opened
for roi in RoiManager.getInstance():
print roi
从另一个脚本调用一个脚本
通常,被调用脚本与调用脚本在同一线程中执行,这意味着调用脚本等待被调用脚本终止,然后再继续执行其余部分。
使用 ImageJ 1.x 命令
ImageJ 提供了另一个插件、宏或脚本中调用插件、宏或脚本的可能性。
如果插件已经是菜单的一部分,则宏记录器返回的简单命令run(PluginName, string Arguments)(或IJ.run对于其他脚本语言)将被启用。
不过,当想要调用不属于ImageJ菜单的自制本地宏时,可以使用不同的命令(见下文)。
这是 mainMacro 调用 subMacro 的示例。
- 主宏
IJ.log("Hello world, I'm mainMacro"); runMacro("C:/structure/temp/subMacro.ijm"); - 子宏
IJ.log("Hello world, I'm subMacro");也可以将参数传递给subMacro,其工作方式相当于命令行执行。
subMacro 使用 getArgument()(或 ImageJ API 的IJ.imageJ.getArgs)来恢复传递给它的参数字符串。
- 主宏
IJ.log("Hello world, I'm mainMacro"); runMacro("C:/structure/temp/subMacro.ijm", "Arg1,Arg2"); - 子宏
Arguments = getArgument() IJ.log(Arguments);命令
runMacro仅适用于ijm宏。要调用用其他脚本语言编写的脚本,应使用runMacroFile(PathToScript, Arguments)(分别为ImageJ API的IJ.runMacroFile)。仍然使用getArgument将变量从mainScript传递到subScript。
然而,第一个选项仅限于 ImageJ 1.x 代码样式,这意味着不能使用脚本,或调用 subScript 中的任何服务。幸运的是,ImageJ2 也有自己的方法来在脚本中调用 script。
使用 ImageJ2 命令
可以使用 SciJava 中的ScriptService在脚本中运行脚本。
下面是 Jython 中 mainScript 调用 subScript 的示例。
- mainScript.py
#@ ScriptService scriptService from ij import IJ IJ.log("Hello world, I'm mainScript"); Arguments = ["some_string", "val1", "some_int", 5] scriptService.run(r"SomePath/subScript.py", True, Arguments); - 子脚本.py
#@ String (label="some_string") some_string #@ Integer (label="some_int") some_int IJ.log(some_string) IJ.log(str(some_int))subScript 必须使用
#@脚本参数作为输入,并且 mainScript 将参数作为field, value列表提交给 subScript
调用外部程序
与宏语言类似,可以使用通过 java.lang.Runtime 类提供的 exec 方法。
在 Jython 中,看起来像:
from java.lang import Runtime
run = Runtime.getRuntime()
# Option 1: provide a single string command
proc = run.exec("someCommand")
# Option 2: Provide a string array of command and argument
proc = run.exec(["someExe", "Arg1", "Arg2"])
# Optionally: wait for the external command to finish before proceeding
proc.waitFor()
# ... do more things ...
print("Done")