これまでの記事では、ImageJのレコーダー機能を使いマクロで動かす方法を紹介しましたが、ImageJではPythonを利用した解析も行えます。PythonはImageJのマクロより汎用性が高く、マクロよりも複雑なタスクが行えるようになります。
この記事ではImageJ(Fiji)をPythonで操作し、サンプル画像のコロニー数をカウントする処理を紹介します。
Windows 11(22H2), ImageJ 1.54f
ImageJをPythonで利用するには
ImageJとJython(Java上に実装されたPython)の組み合わせにより、画像解析のプログラムをより柔軟に記述することができます。ImageJのスクリプトエディタでは、Pythonを選択してコードを入力し、そのまま実行することができます。さらに、PyImageJというパッケージを使用すれば、Python環境から直接ImageJの機能を利用することも可能です。
Jythonの特徴について
- Javaのクラスとのシームレスな統合:
- Jythonを使用すると、Pythonコード内で直接Javaのライブラリやクラスを呼び出すことができます。これにより、JavaとPythonの両方のエコシステムを活用することができます。
- 動的コンパイル:
- Jythonは動的にJavaのバイトコードにコンパイルされ、Java Virtual Machine (JVM) 上で実行されます。
- Python 2.x互換:
- JythonはPython 2.xシリーズの構文に基づいています。したがって、Python 3.xの機能やライブラリはサポートされていません。
ImageJでJythonを利用する際、Jythonのライブラリが存在しない場合には、自動的にそのライブラリをダウンロードします。一方、Fijiは初めからJythonが組み込まれています。今回は利用のしやすさも加味しFijiでの利用について紹介します。
ImageJでPythonを動かす
今回はImageJではなくImageJの拡張版のFijiを用います。Fijiのインストールの方法はこちらの記事で触れています。
File>New>Text Windowを選択すると以下のようなウィンドウが開きます。
この状態でLanguage>Python(Jython)で言語を切り替えることができます。では、以下を入力して動かしてみましょう。
print('Hello World!')
おなじみのHello Worldを入力し、「Run」もしくはCtrl+R (MacではCommand)を押すと、ウィンドウ下に実行結果が表示されます。
タイル画像を生成させる
次は試しに画像を生成してみましょう。
以下のコードをFijiのテキストウィンドウに入力し実行してみます。
# @ImageJ ij
from ij import IJ, ImagePlus
from ij.process import FloatProcessor
import jarray
def create_checkerboard(width, height, cell_size):
# セルの数を計算
n_cells_x = width // cell_size
n_cells_y = height // cell_size
# 空の配列を作成
pixels = jarray.zeros(width * height, 'f')
# 描画
for y in range(n_cells_y):
for x in range(n_cells_x):
if (x + y) % 2 == 0:
fill_color = 0 # 黒
else:
fill_color = 255 # 白
for dy in range(cell_size):
for dx in range(cell_size):
idx = (y * cell_size + dy) * width + (x * cell_size + dx)
pixels[idx] = fill_color
# FloatProcessor を作成して、ImagePlus に変換
ip = FloatProcessor(width, height, pixels, None)
return ImagePlus("Checkerboard", ip)
# 画像を作成
checkerboard = create_checkerboard(200, 200, 20)
checkerboard.show()
実行後、以下のような画像が表示されれば成功です。
このようにPythonを利用してFiji上で画像を生成することも可能です。
コロニー数をカウントする
次に、Fijiで用意されたサンプル画像を使ってコロニー数をカウントします。
画像は以下のようなものです。ここで黒色に表示されたところがコロニーと思われます。この数をPythonを使用してカウントします。
以下のコードをFijiのテキストウィンドウに入力し実行します。
# @ImageJ ij
from ij import IJ
from ij.plugin.filter import ParticleAnalyzer
from ij.measure import ResultsTable
# サンプル画像を開く
image = IJ.openImage("http://imagej.nih.gov/ij/images/Cell_Colony.jpg")
image.show()
# 画像の二値化
IJ.setAutoThreshold(image, "Default dark")
IJ.run(image, "Convert to Mask", "")
# ノイズ除去
IJ.run(image, "Median...", "radius=2")
# 画像の反転
IJ.run(image, "Invert", "")
# 粒子解析(コロニー)をカウント
min_size = 10 # コロニーの最小サイズを指定。
max_size = 1000 # コロニーの最大サイズを指定。
results = ResultsTable()
pa = ParticleAnalyzer(ParticleAnalyzer.SHOW_OUTLINES + ParticleAnalyzer.INCLUDE_HOLES, 0, results, min_size, max_size)
pa.analyze(image)
# 結果の表示
colony_count = results.getCounter()
IJ.log("Number of colonies: " + str(colony_count))
以下のような画像と実行結果が表示されればOKです。
この解析結果では、元画像には192個のコロニーがあると出力されています。どのサイズまでコロニーとして判定させるかによって結果は変わりますが、自動でカウントしてくれるのは大変便利ですね。
コードの解説
1. モジュールのインポート
# @ImageJ ij
from ij import IJ
from ij.plugin.filter import ParticleAnalyzer
from ij.measure import ResultsTable
@ImageJ ij は、ImageJのインスタンスを注入するためのマジックコマンドです。これにより、スクリプト内でImageJのAPIにアクセスできるようになります。次に、ImageJの主要なクラスや関数をインポートしています。
2. サンプル画像の読み込み
image = IJ.openImage("http://imagej.nih.gov/ij/images/Cell_Colony.jpg")
image.show()
ImageJの公式サイトから “Cell_Colony.jpg” というサンプル画像を読み込み、その画像を表示しています。
3. 画像の二値化
IJ.setAutoThreshold(image, "Default dark")
IJ.run(image, "Convert to Mask", "")
画像を二値化しています。具体的には、暗い部分を強調するデフォルトのしきい値を適用し、その結果をもとに画像をマスク化(二値化)しています。
4. ノイズの除去
IJ.run(image, "Median...", "radius=2")
メディアンフィルタを適用してノイズを除去しています。このフィルタは、各ピクセルの周囲の値を考慮して、その中央値を新しいピクセルの値として設定します。
5. 画像の反転
IJ.run(image, "Invert", "")
白と黒のピクセルを反転しています。この後のParticleAnalyzerによる解析処理では、デフォルトで白い領域をカウントするため反転させます。
6. 粒子解析
min_size = 10
max_size = 1000
results = ResultsTable()
pa = ParticleAnalyzer(ParticleAnalyzer.SHOW_OUTLINES + ParticleAnalyzer.INCLUDE_HOLES, 0, results, min_size, max_size)
pa.analyze(image)
ParticleAnalyzerを使用して、指定されたサイズ範囲内のオブジェクト(ここではコロニー)をカウントしています。この解析では、オブジェクトの輪郭を表示し、内部に穴があるオブジェクトも含めて解析を行います。
今回は、10ピクセル以上、1000ピクセル未満を一つのコロニーとしてカウントしました。
6. 結果の表示
colony_count = results.getCounter()
IJ.log("Number of colonies: " + str(colony_count))
解析の結果得られたコロニーの数をカウントし、Fijiのログウィンドウに表示します。
最後に
今回はImageJ(Fiji)を利用して、Pythonでの簡単な画像解析について紹介しました。
PythonはImageJのマクロよりも汎用性が高く、すでにある程度Pythonが使える方は簡単にImageJの操作を行うことができます。
ぜひ、Pythonを利用したImageJの画像解析を試していただければと思います。