用 Python 脚本实现 ImageJ 图像的批处理

使用 Imagej 进行图像处理时,常常会遇到存在大量图片,但处理方法相同的情况。如果耗费大量时间用鼠标进行相同的操作,难免会感到无聊,甚至出错。通过编写 ImageJ 的脚本 Script,我们可以实现 ImageJ 的自动化,从而节省时间,“一劳永逸”。

本方法有 3 个步骤:

  1. 通过 Recorder 记录操作的 Command
  2. 用自己喜欢的编程语言编写脚本(本例采用 Python 示范)
  3. 运行脚本

Command Recorder

使用 Command Recorder 能够为后续的脚本编写提供便捷。

Command Recorder 与 Macro 宏

Command Recorder 是在我们操作 ImageJ 时,同时记录下内部指令的软件。据 ImageJ 官方的介绍

Macro 宏 是一个简单的程序,可以自动执行一系列 ImageJ 指令。创建宏的最简单方法是使用 Command Recorder 指令记录器 记录指令系列,并保存为文本文件,这个文本文件即为。通过选择菜单命令、按键或单击 ImageJ 工具栏中的图标来执行保存的宏。

为什么不直接使用 Macro 编写脚本?

官方对 ImageJ 宏的特性描述是

ImageJ 宏语言不如其他脚本语言强大,但设计为易于学习和使用。

当你需要更复杂的功能,或与 ImageJ 之外的程序进行交互时,宏就显得不是那么方便了。在此,因为我有一定的 Python 基础,所以我果断地选择了 Python。ImageJ 官方对 Python 的描述是:

Python是科学家的热门选择。您可以在 ImageJ 内部使用其 script editor(/scripting/script-editor)编写 Jython scripts(/scripting/jython)(一种基于 Java 的 Python 2 语言),或者使用 PyImageJ(/scripting/pyimagej) 从 Python 脚本调用 ImageJ 函数。

ImageJ 脚本还支持采用其他语言编写,如 Groovy, JavaScript, Ruby (JRuby), Lisp (Clojure), R (Renjin), Java, MATLAB, BeanShell, Java.

Scripting (imagej.net)

编写脚本

采用 Python 编写 ImageJ 脚本有 2 种方式,官方对其作了比较 Python (imagej.net)

  1. 在 ImageJ 内部编写、运行,类似于采用其他语言脚本的方法。
    - 优点:能够利用 SciJava 脚本参数,并在支持 SciJava 的多个工具中运行。
    - 缺点:将无法使用许多需要本地代码(如 numpy 或 scipy)的 Python 模块。
    - 缺点:目前仅支持 Python2
  2. 采用 pyimagej · PyPI 将 ImageJ 嵌入到 Python 代码中。
    - 优点:可以将 ImageJ 与其他图像分析库(如 scikit-image,ITK,OpenCV 等)在单个Python 程序中结合使用。
    - 缺点:在 Python 中封装 ImageJ 存在一些限制,有一些 ImageJ 的功能无法很好地发挥作用。

本文采用 方案 1 ,因为作者在使用 方案 2 的时候,出现了一些尚未解决的问题(尴尬)。

从哪里开始?

新建一个脚本文件十分简单,仅需 File - New - Script,若要使用 Python,则在脚本编辑器的菜单中选择 File - New - Script

几乎所有的 ImageJ 中的 Python 脚本的头部都包含一行:

from ij import IJ

Package 包 "ij" 导入Namespace 命名空间 "IJ" 。 命名空间 是一组函数。是一组命名空间。

关于采用 Python 编写 Script 的更多指南,可以从 Fiji Programming Tutorial (cam.ac.uk)Welcome to Python.org 获取。本文重点在脚本中插件的使用。

如何在 Python 脚本中使用插件?

有 2 种方法在 Python 脚本中使用插件

  1. ij.plugin.<模块名>
  2. 通过 IJ.run() 直接执行 Macro Command 宏指令

通过 ij.plugin 引入模块

在 Command Finder 中,能够查找到,为实现一个功能,应该引用哪个模块。具体操作如下:

  1. 打开 Command Finder:Plugins - Utilities - Find commands...
  2. 输入与命令相关的关键词,便会找到一系列指令
  3. 在指令的 "Class" 栏中,列出了实现它的插件类,注意寻找 ij.plugin 打头的

ImageJ_Command_Finder

如此一来我们便能实现插件在 Python 脚本中的使用。但还有一点,参数该填什么

有 2 个方法寻找参数:

  1. Fiji java documentation ,也能够通过 Tools - Open help for class (with frames) 打开
  2. 插件存储在网络上的 source code,在搜索引擎中进行搜索

综上,这种方法较为困难。我们需要一种更为直观而简便的方法来编写程序。

通过 IJ.run() 执行宏指令

这种方法较为简单快速,采用 Command Recorder,在用鼠标操作 ImageJ 时,便会记录下宏指令。将宏指令直接粘贴到 IJ.run() 中,即可执行。本例即采用此法。

ImageJ_Command_Recorder

举例

本例需要批量处理一系列 .ims 格式的荧光显微镜图片,将其 3 个通道分出,再两两不同通道 merge,随后人工观察一些蛋白的 foci,及共定位现象。加黑部分采用 ImageJ 完成。

# 敬告,路径中不可有空格,且输出文件夹不需要预先建立
# 敬告,请使用双反斜杠

from ij import IJ
import os

folder = "D:\\samples" # 打开文件夹
# 限定各通道显示阈值
c_MinMax = {"0": [100, 500],
            "1": [100, 500],
            "2": [130, 180]}
# 需要合并哪些通道及对应的颜色
c_Merge = {"01": "01", "02": "02", "12": "12"}
os.mkdir(os.path.join(folder, 'out')) # 新建输出文件夹

# 对每张图片进行操作
for i, filename in enumerate(os.listdir(folder)):
    if filename[-4:] == '.ims': # 判断是否为 ims 图片文件
        img_path = os.path.join(folder, filename) # 图片路径
        # 采用 Bio-Formats 读入图片
        img_open_attr = "open=" + img_path + " autoscale \
                color_mode=Default rois_import=[ROI manager] \
                split_channels view=Hyperstack stack_order=XYCZT"
        IJ.run("Bio-Formats Importer", img_open_attr)
        save_path = os.path.join(folder, 'out', filename)  # 新生成图片保存路径
        # 保存拆分开各通道的图片
        for c in ["0", "1", "2"]:
            IJ.selectWindow(filename + " - C=" + c) # 焦点选择该通道读入图片
            IJ.run("Brightness/Contrast...") # 打开调整明暗、对比的窗口
            IJ.setMinAndMax(c_MinMax[c][0], c_MinMax[c][1]) # 调整明暗对比
            IJ.saveAs("PNG", save_path+" - C="+c+".png") # 保存图片
        # 保存任意 2 个通道合并的图片
        for pic_n in c_Merge.keys():
            pic1, pic2 = pic_n[0], pic_n[1]
            IJ.run("Merge Channels...", "c1=[%(filename)s - C=%(pic1)s.png] c3=[%(filename)s - C=%(pic2)s.png] create keep"
                   % {"filename": filename, "pic1": pic1, "pic2": pic2})
            IJ.saveAs("PNG", save_path + "Composite_%s.png" % c_Merge[pic_n])
            IJ.run("Close")
        # 保存 3 个通道全部合并的图片
        IJ.run("Merge Channels...", "c1=[%s - C=2.png] c2=[%s - C=1.png] c3=[%s - C=0.png] create keep"
               % (filename, filename, filename))
        IJ.saveAs("PNG", save_path + "Composite_B_G_R.png")
    # 关闭全部窗口
    IJ.run("Close All")

ImageJ_Sample_20220212

posted @ 2022-02-14 00:45  ZihanlinSam  阅读(2936)  评论(0编辑  收藏  举报