我知道编辑这个网站吗?

给开发者的建议

您可能会发现有用的未排序提示列表。

编译并执行一个类

您不需要使用长 classpath 自己调用 javac

$ ./fiji --javac YourClass.java

你也可以简单地调用它的main()方法:

$ ./fiji YourClass.class argument1 argument2

快速构建插件原型

从 Jython、JRuby 或 BeanShell 脚本开始通常更容易,因为您不必关心严格的类型、异常或重新编译。只需将脚本(具有正确的扩展名 - .py、.rb 或 .bsh)放入 plugins/ 文件夹中并执行脚本即可。 Fiji 将始终执行当前版本的脚本,因此您可以重新启动 Fiji 即可编辑并运行脚本。

当然,使用Script Editor就更方便了…

一旦有了工作代码,您就可以将其转换为适当的插件(这对于 BeanShell 来说是最简单的,因为它的语法已经最接近 Java),根据需要添加严格的类型和异常处理。

查找包含某个类的.jar文件

有时,编译器会抱怨某个类没有特定的方法或接口,但您必须“知道”包含它。通常,该类存在于类路径中的不同版本中。查找与

$ ./fiji bin/find-jar-for-class.py the.class.youre.looking.For

如果您想在已安装的 Fiji 上执行此操作(即当 bin/丢失时),您可以启动 Script Editor 并执行 BeanShell,如下所示:

 import ij.IJ;

 print(IJ.getClassLoader()
         .loadClass("the.class.youre.looking.For")
         .getResource("For.class").toString());

这将输出 .class 文件的 URL,包括封闭的 .jar 文件的路径。

有效使用 ImageJ

ImageJ 有一个简单的 API,但它也很大,所以这里有一些指向一些有用部分的指针。

如何将文件读入 ImagePlus

 ImagePlus image = IJ.openImage(path);

如何获取当前图片

ImagePlus img = WindowManager.getCurrentImage();  // current image
ImageProcessor ip = img.getProcessor();  // current slice

制作一个新的图像堆栈——快!

ImagePlus image = IJ.createImage("my image", "RGB", 640, 480, 20);

如何在窗口中显示异常

这在 Windows 上特别有用,因为你通常看不到控制台:

IJ.handleException(exception);

自 ImageJ 1.43g 起可用,以及使用设置不同异常处理程序的选项

 IJ.setExceptionHandler(new IJ.ExceptionHandler() {
    public void handle(Throwable exception) {
       // do something
    }
 });

如何显示情节

ImageJ 提供了 ij.gui.Plot 类来创建显示绘图的窗口。就像这样使用它:

Plot plot = new Plot("The window title", "labels on the x-axis", "labels on the y-axis",
    float_array_of_x_values, float_array_of_y_values);
plot.show();

您还可以使用 double 存储来代替 float 存储。

如果需要在某个阶段更新绘图,则需要保存 show() 的返回值:

Plot plot = new Plot("The window title", "labels on the x-axis", "labels on the y-axis",
    float_array_of_x_values, float_array_of_y_values);
PlotWindow window = plot.show();
// ...
Plot update = new Plot("Dummy", "x labels", "y labels", x_values, y_values);
window.drawPlot(update);

为了将另一个绘图添加相同到窗口,请使用 addPoints() 方法:

plot.addPoints(float_array_of_x_values, float_array_of_y_values, Plot.LINE);

这些图可以使用不同的颜色,如下所示:

Plot plot = new Plot("The window title", "labels on the x-axis", "labels on the y-axis",
    float_array_of_x_values, float_array_of_y_values);
plot.setColor(Color.RED);
plot.draw();
plot.addPoints(float_array_of_x_values, another_float_array_of_y_values, Plot.LINE);
plot.setColor(Color.BLUE);
plot.draw();

如果第二个图与第一个图的边界框不匹配,您可能需要在调用 plot.draw(); 之前使用 setLimits() 方法调整边界框

复制或在 ImageProcessor 类型之间转换

ImageProcessor类有几个有用的方法:duplicate()convertToByte()convertToFloat()convertToRGB()convertToShort()

这个class还有一些其他的好处,例如擀面法。

如何持久存储设置

ImageJ(以及斐济)有一种持久存储键/值对的方法,即它们在重新启动后也可用。这些设置存储在主目录中名为 .imagej/ 的子目录中名为 IJ_Prefs.txt 的文件中(在 Windows 上,直接在主目录中;在 Mac 上,在 ~/Library/Preferences 中)。

The settings are only saved upon regular exit of Fiji; If you kill the process, or if the Java Runtime crashes, they are not saved. You can ask for the settings to be saved explicitly, though.

原文:

import ij.Prefs;

...

    // save key/value pairs
    Prefs.set("my.persistent.name", "Grizzly Adams");
    Prefs.set("my.persistent.number", 10);

    ....

    // retrieve the values (with default values)
    int myNumber = Prefs.get("my.persistent.number", 0);

    // explicitly save the preferences _now_
    Prefs.savePreferences();

<div class="notice notice-note" style="font-size: 2;"><div class="notice-icon"><img alt="" src="/media/icons/note.svg" width="32"></div><div class="notice-content"><p>Do <em>not</em> use the <code class="language-plaintext highlighter-rouge">getString()</code> or <code class="language-plaintext highlighter-rouge">getInt()</code>; These methods do not have any setter methods, and they do <em>not</em> access the same values as the <code class="language-plaintext highlighter-rouge">get()</code> method (<code class="language-plaintext highlighter-rouge">get()</code> actually prefixes the keys with a dot)!</p>
</div>
</div>

如何使用给定的小数字将数字转换为字符串

使用ij.IJ类的d2s()方法:

String message = "The current temperature is " + IJ.d2s(degrees, 1) + "° Celsius";

如何完全中止插件

有时,您想要中止插件而不以最高级别捕获异常,也不让 ImageJ 显示异常窗口。您可以这样做:

throw new RuntimeException(Macro.MACRO_CANCELED);

特殊消息 Macro.MACRO_CANCELED 将告诉 ImageJ 不要在文本窗口中显示异常消息和堆栈跟踪。

与ROI经理互动

足以将 ROI 添加到 ROI 管理器,请执行以下操作:

RoiManager manager = RoiManager.getInstance();
if (manager == null)
    manager = new RoiManager();
manager.addRoi(roi);

如果您想添加标有投资回报率的切片标签,您必须跳过一个圈:

int currentSlice = image.getCurrentSlice();
RoiManager manager = RoiManager.getInstance();
if (manager == null)
    manager = new RoiManager();
// the first slice is 1 (not 0)
image.setSliceWithoutUpdate(slice);
manager.add(image, rois[i], slice);
image.setSlice(currentSlice);

要从ROI管理器搜索所有ROI,请执行以下操作:

RoiManager manager = RoiManager.getInstance();
if (manager != null) {
    Hashtable<String, Roi> table =
        (Hashtable<String, Roi>)manager.getROIs();
    for (String label : table.keySet()) {
        int slice = manager.getSliceNumber(label);
        Roi roi = table.get(label);
        ... <do something with the ROI and the slice> ...
    }
}

如果您需要在 ROI 管理器中保留 ROI 的顺序,不幸的是您访问 AWT 列表框:

import java.awt.List;
...
RoiManager manager = RoiManager.getInstance();
if (manager != null) {
    List labels = manager.getList();
    Hashtable<String, Roi> table = (Hashtable<String, Roi>)manager.getROIs();
    for (int i = 0; i < labels.getItemCount(); i++) {
        String label = labels.getItem(i);
        int slice = manager.getSliceNumber(label);
        Roi roi = table.get(label);
        ... <do something with the ROI and the slice> ...
    }
}

要仅获得指定的回报投资率,请使用与此类似的代码:

import java.awt.List;
...
RoiManager manager = RoiManager.getInstance();
if (manager != null) {
    String[] labels = manager.getList().getSelectedItems();
    Hashtable<String, Roi> table = (Hashtable<String, Roi>)manager.getROIs();
    for (String label : labels) {
        int slice = manager.getSliceNumber(label);
        Roi roi = table.get(label);
        ... <do something with the ROI and the slice> ...
    }
}

显示结果表

首先,您需要获取结果表实例(或创建一个):

ResultsTable rt = Analyzer.getResultsTable();
if (rt == null) {
        rt = new ResultsTable();
        Analyzer.setResultsTable(rt);
}

然后你可以添加一个新行:

rt.incrementCounter();

…并按列标签添加边界:

rt.addValue("slice", slice);
rt.addValue("bratwurst", -1);

最后确保结果表显示/更新:

rt.show("Results");

如何找到 ImageJ 1.x 和 ImageJ2 之间对应的 API 命令?

ImageJ1-ImageJ2 cheat sheet可用。

图形用户界面 (GUI) 编程技巧

使用 Swing 组件进行编程

使用 Swing 编程时,请注意 Swing 不是线程安全的。 Swing 的黄金法则指出:

一旦实现了 Swing 组件,所有可能影响或依赖于该组件状态的代码都应该在事件分派线程中执行。

Swing组件什么时候实现的?当它在Window或JFrame内可见时,调用了setVisible(true)。这意味着它的paint(Graphics)方法已经被调用或即将被调用。

这些是可以实现组件的方法,或者更理想地说,在 WindowFrameJFrame 上调用的方法将实现其所有子组件:

setVisible(true)
show()
pack() // this might surprise you

有一个课程可以帮助您解决所有这些问题:SwingUtilities。示例:从构造函数内调用pack()(可能也可能不会从事件线程调度调用):

if (SwingUtilities.isEventDispatchThread())
    pack();
else try {
    SwingUtilities.invokeAndWait(new Runnable() { public void run() {
        pack();
    }});
} catch (Exception e) { /* ignore */ }

Swing guide 中提取的信息(现在只能通过 web.archive.org 获取,因为 Oracle 删除了原始文档),其他信息可以在 Java 教程Concurrency in Swing 课程中找到。

#奥术怪癖

软引用和内存不足错误

我们最近明白了一个关于 Java SoftReference 的有趣事实以及OutOfMemoryError 的潜在发生。首先是结果:在有足够的可用内存之后可以释放SoftReferences这种情况下,可能会触发OutOfMemoryError。原因是正常的垃圾收集发生在独立的线程中,并且在分配内存时不会停止其他线程。只有显式的System.gc()才会等待内存被释放。结果是,只要您分配内存时,都应该使用以下子句来执行此操作:

final MyObject o;
try {
  o = new MyObject();
}
catch (OutOfMemoryError e) {
  System.gc();
  o = new MyObject();
}

我们通过使用 SoftReferencesHashMap 实现一个简单的存储来实现这一发现点,该存储最终在确定时会删除 HashMap 中的相应键。该存储用于存储使用 CATMAID 堆栈 (GitHub) ImgLib2事实证明,交互式查看器中的线程获取新图块的速度比垃圾收集器完成SoftReferences并以OutOfMemoryError停止的速度更快。我们用上面的结构来解决这个问题。