pyimagej-fiji-bridge について
PyImageJは、PythonからImageJ2やFijiを呼び出すためのブリッジスキルです。Pythonの画像処理とFijiプラグイン、マクロ、測定を組み合わせたい研究者向けで、ヘッドレス処理とNumPy・ImageJ間のデータ変換に対応します。
主な機能
- 01PythonからFijiプラグインを呼び出し
- 02ImageJマクロファイルの実行
- 03ヘッドレスでのバッチ処理
- 04NumPyとImageJ画像の変換
- 05ImageJ Opsによる画像処理
- 06測定結果をDataFrameとして取得
活用シーン
- 01既存のFijiマクロを一括実行
- 02Bio-Formatsで顕微鏡画像を読み込み
- 03TrackMateで粒子を追跡
- 04ImageJの測定結果を統計解析に利用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jaechang-hits/ sciagent-skills --skill pyimagej-fiji-bridgeインストール後、Claude Code で/pyimagej-fiji-bridgeを入力して読み込まれたか確認します。
詳細
PyImageJ — ImageJ/Fiji への Python ブリッジ
概要
PyImageJ は、PyJNIus と scyjava を通じて ImageJ2 および Fiji の Python インターフェースを提供し、Python プロセス内に完全な Java 仮想マシンを組み込みます。NumPy 配列と ImageJ の ImagePlus/ImgLib2 データ構造の間で双方向のデータ交換が可能なため、Python で画像の前処理を行って Fiji プラグイン(Bio-Formats、TrackMate、Analyze Particles、Weka segmentation)に渡し、結果を pandas DataFrame に戻せます。スクリプトやバッチ処理向けのヘッドレス動作に加え、Fiji の対話的なセッション向けの GUI モードにも対応しています。
使用する場面
- Python から Fiji 専用のプラグインを実行する場合:Bio-Formats による複数形式の I/O、TrackMate による粒子追跡、CLIJ2 による GPU 処理、コミュニティの Fiji アップデートサイトのプラグイン
- Fiji GUI を開かずに ImageJ マクロのパイプラインをヘッドレスで自動化する場合(例:実験全体の一晩かけたバッチ処理)
- ImageJ の型システムをフル活用して、ImageJ Ops フレームワーク(150 以上の画像処理操作)を適用する場合
- 往復処理のために、NumPy 配列(SciPy エコシステム)と ImageJ のハイパースタック(TZCYX のチャンネル順)を相互変換する場合
- ImageJ Results テーブルと ROI Manager の測定結果を解析し、後続の統計分析用に pandas DataFrame にする場合
- 既存の
.ijmマクロファイルを書き換えずに Python ワークフローの一部として実行する場合 - Fiji プラグインを使わない純粋な Python 処理が必要な場合は、代わりに
scikit-imageを使用してください。scikit-image はインストールが速く、JVM のオーバーヘッドもありません - 対話的な多次元画像の可視化や注釈には、代わりに
napariを使用してください。PyImageJ はビューアーの代わりにはなりません
前提条件
- Python パッケージ:
pyimagej、scyjava、numpy、pandas - Java:Java 8 または Java 11(Java 17 はサポートされていません)。Java を確実に管理するには conda を使用してください
- Fiji/ImageJ2:初回の初期化時に自動でダウンロードされます。または、ローカルの Fiji インストールパスを指定してください
- 環境:conda 環境を強く推奨します。pip のみでインストールすると、JVM のパスに関する問題が起きることがよくあります
# Recommended: conda installation
conda create -n pyimagej -c conda-forge pyimagej openjdk=11
conda activate pyimagej
# Install additional dependencies
pip install pandas tifffile
# Verify
python -c "import imagej; ij = imagej.init('sc.fiji:fiji', mode='headless'); print(ij.getVersion())"
クイックスタート
import imagej
import numpy as np
# Initialize Fiji in headless mode (downloads on first run, ~500 MB)
ij = imagej.init("sc.fiji:fiji", mode="headless")
print(f"ImageJ version: {ij.getVersion()}")
# Create a test image, process with Gaussian blur via Ops, convert back
arr = np.random.randint(0, 1000, (256, 256), dtype=np.uint16)
imp = ij.py.to_imageplus(arr)
blurred = ij.op().filter().gauss(imp.getProcessor(), 2.0)
result = ij.py.from_imageplus(imp)
print(f"Processed array shape: {result.shape}, dtype: {result.dtype}")
コア API
モジュール 1:初期化
PyImageJ は、Python のセッションごとに一度初期化する必要があります。mode とエンドポイントによって、使用する ImageJ ディストリビューションと GUI の動作が決まります。
import imagej
# Headless Fiji — most common for scripts and batch jobs
ij = imagej.init("sc.fiji:fiji", mode="headless")
# GUI mode — opens the Fiji window (requires a display)
ij = imagej.init("sc.fiji:fiji", mode="gui")
# Local Fiji installation — faster startup, no download
ij = imagej.init("/path/to/Fiji.app", mode="headless")
# Specific Fiji version
ij = imagej.init("sc.fiji:fiji:2.14.0", mode="headless")
# Bare ImageJ2 without Fiji plugins
ij = imagej.init("net.imagej:imagej", mode="headless")
print(f"ImageJ version: {ij.getVersion()}")
print(f"Headless: {ij.ui().isHeadless()}")
モジュール 2:画像 I/O
ImageJ の I/O レイヤー(独自形式に対応する Bio-Formats を含む)を使用して画像を開いて保存し、ImageJ と NumPy の表現を相互変換します。
import imagej
import numpy as np
ij = imagej.init("sc.fiji:fiji", mode="headless")
# Open any format Bio-Formats supports: CZI, LIF, ND2, ICS, TIFF, etc.
imp = ij.io().open("/data/experiment.czi")
print(f"Dimensions: {imp.getDimensions()}") # [W, H, C, Z, T]
print(f"nSlices: {imp.getNSlices()}, nFrames: {imp.getNFrames()}")
# Save image
ij.io().save(imp, "/data/output.tif")
print("Saved output.tif")
# NumPy ↔ ImageJ conversion
arr = np.zeros((100, 100), dtype=np.uint16)
arr[30:70, 30:70] = 1000 # bright square
# NumPy → ImagePlus
imp = ij.py.to_imageplus(arr)
print(f"ImagePlus: {imp.getWidth()}×{imp.getHeight()}, type={imp.getType()}")
# ImagePlus → NumPy (returns a view where possible)
arr_back = ij.py.from_imageplus(imp)
print(f"NumPy array: shape={arr_back.shape}, dtype={arr_back.dtype}")
# Multi-channel array: shape (C, H, W)
rgb = np.random.randint(0, 255, (3, 256, 256), dtype=np.uint8)
imp_rgb = ij.py.to_imageplus(rgb)
print(f"Channels: {imp_rgb.getNChannels()}")
モジュール 3:マクロの実行
ImageJ マクロ言語(IJM)のコードやマクロファイルを実行します。マクロは ImageJ 環境内で実行され、組み込みの ImageJ コマンドをすべて呼び出せます。
import imagej
ij = imagej.init("sc.fiji:fiji", mode="headless")
# Run an inline macro string
ij.macro.run("print('Hello from ImageJ macro');")
# Run a macro with options string (key=value pairs)
# Options string mirrors the dialog parameters of ImageJ commands
macro_code = """
run("Gaussian Blur...", "sigma=2");
run("Auto Threshold", "method=Otsu white");
"""
ij.macro.run(macro_code)
# Run a macro file from disk
ij.macro.runMacroFile("/scripts/my_analysis.ijm")
# Run macro that returns a value via getResult or output string
result = ij.macro.run("""
x = 42 * 2;
return x;
""")
print(f"Macro returned: {result}")
# Macro with current image: open → process → measure
ij.io().open("/data/cells.tif") # sets current active image
measure_macro = """
run("Set Measurements...", "area mean min integrated redirect=None decimal=3");
run("Analyze Particles...", "size=50-Infinity display clear summarize");
"""
ij.macro.run(measure_macro)
print("Analyze Particles complete; results in Results table")
モジュール 4:ImageJ Ops
ImageJ Ops は、型安全なディスパッチに対応した 150 以上の画像処理操作を備えるフレームワークです。Ops は ImgLib2 の Img オブジェクトに対して動作し、プログラムから画像処理アルゴリズムを呼び出す際に推奨される方法です。
import imagej
import numpy as np
ij = imagej.init("sc.fiji:fiji", mode="headless")
arr = np.random.randint(100, 900, (512, 512), dtype=np.uint16)
img = ij.py.to_java(arr) # converts to ImgLib2 RandomAccessibleInterval
# Gaussian blur
blurred = ij.op().filter().gauss(img, 2.0)
blurred_np = ij.py.from_java(blurred)
print(f"Blurred: {blurred_np.shape}")
# Otsu threshold → binary image
binary = ij.op().threshold().otsu(img)
binary_np = ij.py.from_java(binary)
print(f"Binary unique values: {np.unique(binary_np)}")
# Morphological operations
from jnius import autoclass
BitType = autoclass("net.imglib2.type.logic.BitType")
opened = ij.op().morphology().open(binary, [3, 3])
opened_np = ij.py.from_java(opened)
print(f"After opening: {opened_np.shape}")
# Statistics ops
mean_val = ij.op().stats().mean(img)
std_val = ij.op().stats().stdDev(img)
print(f"Mean intensity: {mean_val:.1f}, StdDev: {std_val:.1f}")
# Math ops: multiply image by scalar
scaled = ij.op().math().multiply(img, ij.py.to_java(2.0))
print(f"Scaled max: {ij.py.from_java(scaled).max()}")
モジュール 5:プラグインとコマンドの呼び出し
SciJava コマンドは、Fiji プラグインをプログラムから呼び出す主要な方法です。コマンドは、プラグインのダイアログに対応する名前付きパラメーターの dict を受け取ります。
import imagej
ij = imagej.init("sc.fiji:fiji", mode="headless")
# Open a file using Bio-Formats opener command
future = ij.command().run(
"loci.plugins.LociImporter",
True,
{"id": "/data/image.lif", "open_files": True, "autoscale": True}
)
module = future.get()
imp = module.getOutput("imp")
print(f"Opened via Bio-Formats: {imp.getDimensions()}")
# Run Analyze Particles as a SciJava command
ij.io().open("/data/binary_mask.tif")
future = ij.command().run(
"ij.plugin.filter.ParticleAnalyzer",
True,
{
"minSize": 50.0,
"maxSize": float("inf"),
"options": 0, # SHOW_NONE
"measurements": 1, # AREA
}
)
future.get()
print("Analyze Particles command complete")
# Alternatively, run via macro string for simpler plugin invocation
ij.macro.run("""
run("Analyze Particles...", "size=50-Infinity display clear summarize");
""")
モジュール 6:Results テーブルと ROI の分析
Analyze Particles やその他の測定コマンドを実行した後、ImageJ の Results テーブルと ROI Manager から測定結果を取得します。
import imagej
import pandas as pd
ij = imagej.init("sc.fiji:fiji", mode="headless")
# After running Analyze Particles, read the Results table
def results_to_dataframe(ij) -> pd.DataFrame:
"""Convert ImageJ Results table to pandas DataFrame."""
rt = ij.ResultsTable.getResultsTable()
if rt is None or rt.size() == 0:
return pd.DataFrame()
headings = list(rt.getHeadings())
data = {col: [rt.getValue(col, i) for i in range(rt.size())]
for col in headings}
return pd.DataFrame(data)
# Run segmentation + measurement macro
ij.io().open("/data/cells.tif")
ij.macro.run("""
run("Gaussian Blur...", "sigma=1.5");
setAutoThreshold("Otsu dark");
run("Convert to Mask");
run("Analyze Particles...", "size=20-Infinity display clear");
""")
df = results_to_dataframe(ij)
print(f"Found {len(df)} objects")
print(df[["Area", "Mean", "IntDen"]].describe())
df.to_csv("particle_measurements.csv", index=False)
print("Saved particle_measurements.csv")
# Access the ROI Manager
def get_roi_manager(ij):
"""Return the ImageJ ROI Manager instance, creating if needed."""
RoiManager = ij.py.jclass("ij.plugin.frame.RoiManager")
rm = RoiManager.getInstance()
if rm is None:
rm = RoiManager(False) # headless=False means no GUI window
return rm
rm = get_roi_manager(ij)
roi_count = rm.getCount()
print(f"ROIs in manager: {roi_count}")
# Extract bounding boxes for all ROIs
rois = []
for i in range(roi_count):
roi = rm.getRoi(i)
bounds = roi.getBounds()
rois.append({"index": i, "x": bounds.x, "y": bounds.y,
"width": bounds.width, "height": bounds.height})
roi_df = pd.DataFrame(rois)
print(roi_df.head())
よくあるワークフロー
ワークフロー 1:蛍光の自動定量
目標:複数チャンネルの TIFF スタックを開き、ガウシアンぼかしを適用し、核チャンネルをしきい値処理して Analyze Particles を実行し、細胞ごとの測定結果を CSV としてエクスポートします。
import imagej
import pandas as pd
import numpy as np
from pathlib import Path
ij = imagej.init("sc.fiji:fiji", mode="headless")
def quantify_nuclei(tiff_path: str, output_csv: str,
channel: int = 1, sigma: float = 1.5,
min_size: int = 50) -> pd.DataFrame:
"""
Segment and measure nuclei in a fluorescence TIFF.
Parameters
----------
tiff_path : path to single- or multi-channel TIFF
output_csv : where to save results
channel : 1-based channel index for nuclear stain (e.g., DAPI)
sigma : Gaussian blur radius in pixels
min_size : minimum nucleus area in pixels
"""
# Step 1: Open image
imp = ij.io().open(tiff_path)
print(f"Loaded: {Path(tiff_path).name} dims={imp.getDimensions()}")
# Step 2: Extract channel if multi-channel
if imp.getNChannels() > 1:
imp.setC(channel)
# Step 3: Apply Gaussian blur and threshold via macro
ij.macro.run(f"""
selectWindow("{imp.getTitle()}");
run("Gaussian Blur...", "sigma={sigma}");
setAutoThreshold("Otsu dark");
run("Convert to Mask");
run("Fill Holes");
run("Watershed");
""")
# Step 4: Measure
ij.macro.run(f"""
run("Set Measurements...", "area mean min centroid integrated shape redirect=None decimal=3");
run("Analyze Particles...", "size={min_size}-Infinity display clear include summarize");
""")
# Step 5: Collect results
rt = ij.ResultsTable.getResultsTable()
if rt is None or rt.size() == 0:
print("No objects detected")
return pd.DataFrame()
headings = list(rt.getHeadings())
df = pd.DataFrame(
{col: [rt.getValue(col, i) for i in range(rt.size())]
for col in headings}
)
df["source_file"] = Path(tiff_path).stem
df.to_csv(output_csv, index=False)
print(f"Saved {len(df)} measurements → {output_csv}")
return df
df = quantify_nuclei(
tiff_path="/data/experiment_dapi.tif",
output_csv="nuclei_measurements.csv",
channel=1,
sigma=1.5,
min_size=50
)
print(df[["Area", "Mean", "Circ."]].describe())
ワークフロー 2:Fiji マクロのバッチ処理
目標:既存の Fiji .ijm マクロファイルを使ってフォルダー内の画像を処理し、各画像の Results テーブルを 1 つの DataFrame にまとめます。
import imagej
import pandas as pd
from pathlib import Path
ij = imagej.init("sc.fiji:fiji", mode="headless")
def run_macro_on_image(ij, image_path: str, macro_file: str) -> pd.DataFrame:
"""Open one image, run a macro file, return its Results table."""
ij.io().open(image_path)
# Clear any previous results before running
ij.macro.run("run(\"Clear Results\");")
# Run macro file (macro must operate on the active image)
ij.macro.runMacroFile(macro_file)
rt = ij.ResultsTable.getResultsTable()
if rt is None or rt.size() == 0:
return pd.DataFrame()
headings = list(rt.getHeadings())
return pd.DataFrame(
{col: [rt.getValue(col, i) for i in range(rt.size())]
for col in headings}
)
input_dir = Path("/data/images")
macro_file = "/scripts/measure_cells.ijm"
output_csv = "batch_results.csv"
all_results = []
image_files = sorted(input_dir.glob("*.tif"))
for img_path in image_files:
print(f"Processing: {img_path.name}")
df = run_macro_on_image(ij, str(img_path), macro_file)
if not df.empty:
df["filename"] = img_path.name
all_results.append(df)
# Close all windows to free memory between images
ij.macro.run("close('*');")
if all_results:
combined = pd.concat(all_results, ignore_index=True)
combined.to_csv(output_csv, index=False)
print(f"Batch complete: {len(image_files)} images, "
f"{len(combined)} total measurements → {output_csv}")
else:
print("No results collected from any image")
主なパラメーター
| パラメーター | モジュール | デフォルト | 範囲/オプション | 効果 |
|---|---|---|---|---|
mode | 初期化 | "headless" | "headless", "gui", "interactive" | Fiji の GUI ウィンドウを開くかどうかを制御します。スクリプトでは "headless" を使用します |
endpoint | 初期化 | "sc.fiji:fiji" | Maven 座標または /path/to/Fiji.app | ImageJ2 ディストリビューションを選択します。sc.fiji:fiji には Fiji プラグインがすべて含まれます |
sigma(ガウシアンぼかし) | マクロ/Ops | 2.0 | 0.5~10.0 | ピクセル単位の空間平滑化半径です。値を大きくするとノイズが減りますが、エッジもぼやけます |
minSize(粒子解析) | プラグイン/マクロ | 0 | ピクセル²または 0~Infinity | 対象に含める最小オブジェクト面積です。ノイズ粒子を除去します |
method(自動しきい値) | マクロ/Ops | "Otsu" | "Otsu", "Triangle", "MaxEntropy", "Huang", "Li" | しきい値アルゴリズムです。二峰性ヒストグラムには Otsu が適しています |
measurements ビットマスク | 結果/マクロ | 変動します | AREA=1、MEAN=2、CENTROID=4 などの OR 結合 | Results テーブルに表示する列を選択します |
| Java ヒープサイズ | 初期化(環境変数) | JVM のデフォルト(RAM の約 25%) | JAVA_TOOL_OPTIONS で設定 | 大きなスタック画像のメモリを制限します。大きな画像には -Xmx8g を設定します |
ベストプラクティス
-
セッションごとに一度初期化し、
ijを再利用します:新しい JVM の起動には時間がかかります(5~15 秒)。モジュールレベルでijを作成するか、パラメーターとして渡し、ループ内でimagej.init()を呼び出さないようにします。# At module top level — initialized once import imagej ij = imagej.init("sc.fiji:fiji", mode="headless") def process(path): imp = ij.io().open(path) # reuse ij ... -
Java の管理には conda を使用します:pip のみでインストールすると、
JAVA_HOMEが設定されていないか、誤った JDK バージョンがPATHに設定されているため、失敗することがよくあります。openjdk=11を含む conda 環境を使用すると、JVM が見つからないエラーの 90% を回避できます。 -
バッチループでは、画像ごとに Results と ROI Manager をクリアします:ImageJ は同一セッション内の呼び出し間で結果を蓄積します。行が混在しないように、各画像の処理前に必ず
run("Clear Results")とrm.reset()を呼び出します。ij.macro.run("run('Clear Results');") rm = get_roi_manager(ij) rm.reset() -
単純なコマンドには
ij.command().run()よりij.macro.run()を優先します:マクロ文字列は短く、読みやすく、Fiji Macro Recorder と同じ構文を使用します。コマンドの出力(モジュールの戻り値)にプログラムからアクセスする必要がある場合にのみ、ij.command().run()を使用します。 -
NumPy への変換はできるだけ後にします:
ij.py.from_imageplus()は JVM から Python にデータをコピーします。ImageJ 内で複数の処理を行う場合は、データを ImagePlus または ImgLib2 形式のまま保持し、メモリコピーのオーバーヘッドを最小限に抑えるため、最後にのみ変換します。 -
ImgLib2 Ops には
ij.py.to_java()/ij.py.from_java()を使用します:to_imageplus()/from_imageplus()のペアは従来の ImageProcessor で動作します。一方、to_java()/from_java()はij.op()が必要とする最新の ImgLib2 型システムを対象とします。 -
再現性を確保するため、初期化時に Fiji の更新サイトプラグインリストを設定します:Fiji で新しいプラグイン更新がリリースされてもパイプラインの動作が変わらないよう、
sc.fiji:fiji(最新版)ではなく、バージョンを固定した Fiji(sc.fiji:fiji:2.14.0)を指定します。
よく使うレシピ
レシピ:TrackMate によるヘッドレススポット検出
使用場面:TrackMate の粒子追跡をプログラムから実行し、TrackMate の GUI を開かずに検出されたスポットを DataFrame として取得します。
import imagej
import pandas as pd
ij = imagej.init("sc.fiji:fiji", mode="headless")
# TrackMate headless via macro (scripting interface)
trackmate_macro = """
run("TrackMate", "");
// For fully scripted TrackMate, use the Scripting Interface
// documented at https://imagej.net/plugins/trackmate/scripting
"""
# Scripted TrackMate via Jython-style Java interop
def run_trackmate_headless(ij, imp, radius=3.0, threshold=100.0):
"""Detect spots with LoG detector; return DataFrame of spot coordinates."""
from jnius import autoclass
# Import TrackMate classes
Model = autoclass("fiji.plugin.trackmate.Model")
Settings = autoclass("fiji.plugin.trackmate.Settings")
TrackMate = autoclass("fiji.plugin.trackmate.TrackMate")
LogDetectorFactory = autoclass(
"fiji.plugin.trackmate.detection.LogDetectorFactory")
model = Model()
settings = Settings(imp)
# Configure LoG spot detector
settings.detectorFactory = LogDetectorFactory()
settings.detectorSettings = {
"DO_SUBPIXEL_LOCALIZATION": True,
"RADIUS": radius,
"TARGET_CHANNEL": 1,
"THRESHOLD": threshold,
"DO_MEDIAN_FILTERING": False,
}
tm = TrackMate(model, settings)
tm.process()
# Extract spot table
spots = model.getSpots()
spots.setVisible(True)
records = []
for spot in spots.iterable(True):
records.append({
"id": spot.ID(),
"x": spot.getDoublePosition(0),
"y": spot.getDoublePosition(1),
"z": spot.getDoublePosition(2),
"frame": spot.getFeature("FRAME"),
"quality": spot.getFeature("QUALITY"),
})
return pd.DataFrame(records)
imp = ij.io().open("/data/timelapse.tif")
df = run_trackmate_headless(ij, imp, radius=3.0, threshold=50.0)
print(f"Detected {len(df)} spots across {df['frame'].nunique()} frames")
df.to_csv("spots.csv", index=False)
print(df.head())
レシピ:ImageJ ハイパースタックを NumPy の 5D 配列(TZCYX)に変換
使用場面:多次元の Fiji ハイパースタックを Python にインポートし、ほとんどの科学画像解析ライブラリで使用される標準的な TZCYX 軸順の NumPy 5D 配列にします。
import imagej
import numpy as np
ij = imagej.init("sc.fiji:fiji", mode="headless")
def hyperstack_to_numpy(ij, imp) -> np.ndarray:
"""
Convert an ImageJ hyperstack to a NumPy array with shape (T, Z, C, Y, X).
ImageJ internal order is C-Z-T (slowest to fastest in stack index).
This function reorders to the TZCYX convention used by tifffile, OME, etc.
"""
nC = imp.getNChannels()
nZ = imp.getNSlices()
nT = imp.getNFrames()
H = imp.getHeight()
W = imp.getWidth()
arr = np.zeros((nT, nZ, nC, H, W), dtype=np.uint16)
for t in range(1, nT + 1):
for z in range(1, nZ + 1):
for c in range(1, nC + 1):
idx = imp.getStackIndex(c, z, t)
imp.setSlice(idx)
arr[t-1, z-1, c-1] = ij.py.from_imageplus(imp)
return arr
imp = ij.io().open("/data/4d_experiment.tif")
print(f"ImageJ dims (W,H,C,Z,T): {imp.getDimensions()}")
stack = hyperstack_to_numpy(ij, imp)
print(f"NumPy TZCYX shape: {stack.shape}") # e.g., (10, 15, 2, 512, 512)
print(f"dtype: {stack.dtype}, max: {stack.max()}")
# Save as OME-TIFF with correct axis metadata
import tifffile
tifffile.imwrite(
"output_TZCYX.ome.tif",
stack,
imagej=True,
metadata={"axes": "TZCYX"},
photometric="minisblack"
)
print("Saved output_TZCYX.ome.tif")
トラブルシューティング
| 問題 | 原因 | 解決策 |
|---|---|---|
初期化時に JVMNotFoundException が発生する | JAVA_HOME が設定されていないか、JDK のバージョンが正しくありません | conda でインストールします:conda install -c conda-forge openjdk=11。Java 17 は避けてください |
RuntimeError: Fiji download failed | インターネットに接続できないか、企業プロキシが原因です | fiji.sc から Fiji を手動でダウンロードし、imagej.init("/path/to/Fiji.app") を使用します |
大きなスタックで java.lang.OutOfMemoryError が発生する | JVM のデフォルトヒープが小さすぎます | imagej をインポートする前に export JAVA_TOOL_OPTIONS="-Xmx8g" を設定します |
マクロの run(...) が何もせずに終了する | マクロが画像を想定しているのに、アクティブな画像がありません | 処理マクロを実行する前に ij.io().open(path) を呼び出します。ij.WindowManager.getImageCount() を確認してください |
| Analyze Particles の実行後、結果テーブルが空になる | しきい値が適用されていないか、マスクがバイナリではありません | マスクが 8 ビットのバイナリ(0/255)であることを imp.getType() == 0 で確認します。Analyze Particles の前に Convert to Mask を実行してください |
ij.ResultsTable.getResultsTable() で AttributeError: 'NoneType' object が発生する | このセッションではまだ測定が実行されていません | Analyze Particles マクロが完了したことを確認します。ij.macro.run("print(nResults);") を実行して件数を確認してください |
プラグインクラスが見つからない(ClassNotFoundException) | この Fiji インストールにプラグインがありません | Fiji のアップデートサイト(例:TrackMate)を追加するか、すべてのデフォルトプラグインが含まれる sc.fiji:fiji エンドポイントを使用します |
gui モードが HeadlessException でクラッシュする | ディスプレイを利用できません(SSH/クラスター) | リモート環境では mode="headless" を使用します。GUI モードには DISPLAY または X11 フォワーディングが必要です |
関連スキル
- scikit-image-processing — JVM を使わない純粋な Python 画像処理です。Fiji プラグインが不要な場合に使用します
- napari-image-viewer — Python 用のインタラクティブな多次元画像ビューアーです。可視化において PyImageJ を補完します
- trackpy-particle-tracking — Python ネイティブの Crocker-Grier SPT です。単純な 2D トラッキングでは TrackMate の代替になります
- cellpose-cell-segmentation — 深層学習による細胞セグメンテーションです。単独で実行することも、Fiji プラグインとして実行することもできます
- omero-integration — OMERO サーバーによる画像管理です。PyImageJ では omero-py 経由で取得した画像を処理できます
参考資料
- PyImageJ のドキュメント — 公式 API リファレンス、初期化ガイド、データ変換
- PyImageJ の GitHub リポジトリ — ソース、課題トラッカー、ノートブック、サンプル
- ImageJ Ops フレームワーク — Ops 名前空間のリファレンスとアルゴリズムカタログ
- TrackMate スクリプトガイド — ヘッドレス TrackMate Java API の使用パターン
- Bio-Formats の対応フォーマット —
ij.io().open()で開ける独自形式の顕微鏡画像の一覧 - ImageJ Macro Language リファレンス —
ij.macro.run()の文字列で使用できる組み込み関数