我知道编辑这个网站吗?

脚本基础知识

简介

ImageJ2Fiji利用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 脚本可以访问应用程序类路径上的任何类:ImageJImageJ2 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 模块优先级:firstextremely-highvery-highhighnormallowvery-lowextremely-lowlast
§§§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)

以下方案描述了不同类之间的关系。 Image_Class_Hierarchy.png

在 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")

链接