mcpField
N
napari-image-viewer

napari-image-viewer

github.com/jaechang-hitsデータ・データベース38476 回インストール6 日前に更新
リポジトリ

napari-image-viewer について

napari-image-viewer は、napari による多次元科学画像の表示、注釈、可視化を紹介するスキルです。生物画像研究者や Python ユーザー向けで、レイヤー表示や画面のない環境でのスクリーンショット出力を扱います。

主な機能

  1. 01画像・ラベル・ポイント・シェイプレイヤー
  2. 023Dスタックと時系列の操作
  3. 03コントラスト調整付きマルチチャンネル表示
  4. 04オフスクリーン描画とスクリーンショット出力
  5. 05プラグインを使った分析ワークフロー

活用シーン

  1. 01顕微鏡画像とセグメンテーションマスクの確認
  2. 02セグメンテーションモデル用データの注釈
  3. 03複数画像チャンネルの比較
  4. 04画面のない環境での図の出力

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill napari-image-viewer

インストール後、Claude Code で/napari-image-viewerを入力して読み込まれたか確認します。

詳細

napari — 多次元画像ビューアー

概要

napari は、PyQt5 と VisPy を基盤に構築された、高速でインタラクティブな科学データ向け多次元ビューアーです。NumPy 配列や zarr 配列を、レイヤー化されたビジュアライゼーションとして表示します。生データ用の Image レイヤー、セグメンテーションマスク用の Labels レイヤー、細胞重心用の Points レイヤー、ROI アノテーション用の Shapes レイヤーを利用できます。napari はプラグインを介して scikit-image、Cellpose、StarDist と連携し、Python のバイオ画像解析パイプラインにおける標準的な可視化・アノテーションツールとなっています。ヘッドレス環境(HPC、CI)では、napari はオフスクリーンレンダリングと viewer.screenshot() による図の自動生成をサポートしています。

使用する場面

  • 定量解析の前に、顕微鏡画像とセグメンテーションマスクを目視で検査し、品質を確認する
  • ディープラーニングのセグメンテーションモデル(Cellpose、StarDist)用のトレーニングデータにアノテーションを付ける
  • 独立したコントラストとカラーマップの設定で、複数の画像チャンネル(DAPI、GFP、mCherry)を重ね合わせる
  • スライダーで操作しながら、3D Z スタックや 4D タイムラプス実験を確認する
  • GUI からアノテーション付きスクリーンショットやラベルマスクをエクスポートし、論文用の図を作成する
  • プラグインベースの解析(Cellpose napari プラグイン、StarDist プラグイン、n2v ノイズ除去)を対話的に実行する
  • Python への依存を最小限に抑えたマクロ/バッチ処理には、ImageJ/FIJI を使用する
  • 医用画像(DICOM、NIfTI)のセグメンテーションには、代替ツールとして ITK-SNAP を使用する

前提条件

  • Python パッケージ:napari、numpy、scikit-image
  • Qt バックエンド:ディスプレイサーバーが必要です。ヘッドレスで使用する場合は QT_QPA_PLATFORM=offscreen を設定します
  • オプションのプラグイン:napari-cellpose、napari-stardist、napari-animation
# Install with all backends
pip install "napari[all]"

# Or minimal install
pip install napari pyqt5

# Verify
python -c "import napari; print(napari.__version__)"
# 0.5.5

# Install useful plugins
pip install napari-cellpose napari-animation

クイックスタート

import napari
import numpy as np
from skimage import data

# Open viewer with a sample image
viewer = napari.Viewer()
viewer.add_image(data.cells3d()[:, 1, :, :], name="DAPI", colormap="blue")
napari.run()   # blocks until viewer closed (use in scripts)

コア API

モジュール 1:Image レイヤー — 生画像を表示する

複数チャンネルの画像レイヤーを追加して設定します。

import napari
import numpy as np
from skimage import io

viewer = napari.Viewer()

# Add single grayscale image
img = io.imread("cells.tif")  # shape: (H, W)
viewer.add_image(img, name="phase contrast", colormap="gray",
                 contrast_limits=[0, img.max()])

# Add multichannel image (3 channels)
img_mc = io.imread("multichannel.tif")  # shape: (H, W, 3)
viewer.add_image(img_mc[..., 0], name="DAPI", colormap="blue", blending="additive")
viewer.add_image(img_mc[..., 1], name="GFP", colormap="green", blending="additive")
viewer.add_image(img_mc[..., 2], name="mCherry", colormap="red", blending="additive")

print(f"Layers: {[l.name for l in viewer.layers]}")
モジュール 2:Labels レイヤー — セグメンテーションマスクを可視化する

Cellpose、StarDist、または scikit-image で生成した整数ラベルマスクを表示して編集します。

import napari
import numpy as np
from skimage import io

viewer = napari.Viewer()

img = io.imread("cells.tif")
masks = np.load("masks.npy")  # integer label array: 0=background, 1..N=cells

# Add raw image
viewer.add_image(img, name="raw", colormap="gray")

# Add label mask (each cell gets a unique random color)
label_layer = viewer.add_labels(masks, name="cell_masks", opacity=0.5)

# Access labels for editing
print(f"Unique cells: {len(np.unique(masks)) - 1}")
print(f"Label layer data shape: {label_layer.data.shape}")
モジュール 3:Points レイヤー — 細胞の重心をマークする

重心、ランドマーク、または検出された特徴にポイントマーカーを追加し、スタイルを設定します。

import napari
import numpy as np
import pandas as pd
from skimage.measure import regionprops_table

viewer = napari.Viewer()

# Compute centroids from label mask
masks = np.load("masks.npy")
props = regionprops_table(masks, properties=["centroid", "label"])
centroids = np.column_stack([props["centroid-0"], props["centroid-1"]])

# Add centroids as Points layer
viewer.add_points(
    centroids,
    name=f"centroids ({len(centroids)} cells)",
    size=8,
    face_color="yellow",
    edge_color="black",
    edge_width=0.5,
)
print(f"Cells marked: {len(centroids)}")
モジュール 4:Shapes レイヤー — ROI とアノテーションを描画する

バウンディングボックス、ポリゴン、線のアノテーションを追加します。

import napari
import numpy as np

viewer = napari.Viewer()

# Add rectangles as ROIs (format: [[y1, x1], [y2, x2]])
rois = [
    np.array([[50, 100], [200, 300]]),   # ROI 1
    np.array([[300, 150], [450, 350]]),  # ROI 2
]

shapes_layer = viewer.add_shapes(
    rois,
    shape_type="rectangle",
    name="ROIs",
    edge_color="cyan",
    face_color="transparent",
    edge_width=2,
)

# Retrieve shapes data for analysis
for i, shape in enumerate(shapes_layer.data):
    y_min, x_min = shape.min(axis=0)
    y_max, x_max = shape.max(axis=0)
    print(f"ROI {i+1}: y={y_min:.0f}-{y_max:.0f}, x={x_min:.0f}-{x_max:.0f}")
モジュール 5:3D とタイムラプスの可視化

スライダーを使って Z スタックと時系列データを表示します。

import napari
import numpy as np
from skimage import data

viewer = napari.Viewer()

# 3D z-stack: shape (Z, H, W)
zstack = data.cells3d()[:, 1, :, :]   # nuclei channel
viewer.add_image(zstack, name="z-stack nuclei",
                 colormap="cyan", blending="additive")

# 4D time-lapse: shape (T, H, W) or (T, Z, H, W)
timelapse = np.random.randint(0, 65535, (10, 256, 256), dtype=np.uint16)
viewer.add_image(timelapse, name="timelapse", colormap="gray")

# napari shows axis sliders automatically for ndim > 2
print(f"z-stack shape: {zstack.shape} → slider for Z axis")
print(f"timelapse shape: {timelapse.shape} → sliders for T axis")
モジュール 6:ヘッドレスでのスクリーンショットのエクスポート

ディスプレイなしでスクリーンショットをエクスポートします(HPC および CI 環境向け)。

import os
os.environ["QT_QPA_PLATFORM"] = "offscreen"  # must be set BEFORE importing napari

import napari
import numpy as np
from skimage import io, data
import matplotlib
matplotlib.use("Agg")  # also set matplotlib backend

viewer = napari.Viewer(show=False)

img = data.cells3d()[30, 1, :, :]  # single z-slice
masks = (img > img.mean()).astype(int)  # simple threshold mask

viewer.add_image(img, name="DAPI", colormap="blue", blending="additive")
viewer.add_labels(masks.astype(np.int32), name="masks", opacity=0.5)

# Export screenshot
screenshot = viewer.screenshot(path="napari_export.png", canvas_only=True)
print(f"Screenshot saved: napari_export.png ({screenshot.shape})")
viewer.close()

主なパラメーター

パラメーターモジュールデフォルト効果
colormapadd_image"gray"カラーマップ名(matplotlib のカラーマップと napari の組み込みカラーマップ:"green"、"blue"、"cyan")
contrast_limitsadd_imageauto表示用の輝度クリッピング範囲 [min, max]
blendingadd_image"translucent"複数チャンネルの重ね合わせには "additive"、不透明表示には "opaque"
opacityadd_labels0.7画像上に重ねるラベルレイヤーの透明度(0~1)
face_coloradd_points"white"ポイントの塗りつぶし色(名前、16 進数、または RGBA)
sizeadd_points10データ座標でのポイント半径(ピクセル)
edge_widthadd_shapes1図形の輪郭線の幅(ピクセル)
showViewer()Trueヘッドレス/オフスクリーンモードでは False
ndisplayViewer()23D OpenGL レンダリングモードでは 3
canvas_onlyscreenshot()Falseエクスポート時に napari のツールバーを除外するには True

よくあるワークフロー

ワークフロー 1:Cellpose のセグメンテーション品質を確認する
import os
os.environ["QT_QPA_PLATFORM"] = "offscreen"

import napari
import numpy as np
from cellpose import models
from skimage import io
from skimage.measure import regionprops_table

# Segment with Cellpose
img = io.imread("cells.tif")
model = models.Cellpose(model_type="cyto3", gpu=False)
masks, _, _, diams = model.eval(img, diameter=0, channels=[0, 0])

# Visualize in napari (headless for export)
viewer = napari.Viewer(show=False)
viewer.add_image(img, name="raw", colormap="gray")
viewer.add_labels(masks, name=f"masks ({masks.max()} cells)", opacity=0.6)

# Add centroids
props = regionprops_table(masks, properties=["centroid"])
centroids = np.column_stack([props["centroid-0"], props["centroid-1"]])
viewer.add_points(centroids, name="centroids", size=6, face_color="yellow")

viewer.screenshot(path="segmentation_review.png", canvas_only=True)
viewer.close()
print(f"QC export: segmentation_review.png — {masks.max()} cells detected")
ワークフロー 2:マルチチャンネル FISH 画像を解析する
import napari
import numpy as np
from skimage import io

# Load 4-channel FISH image: DAPI + 3 RNA probes
img = io.imread("fish_4channel.tif")  # shape: (H, W, 4)

viewer = napari.Viewer()
channels = [
    ("DAPI", "blue", img[..., 0]),
    ("probe_A_cy3", "yellow", img[..., 1]),
    ("probe_B_cy5", "red", img[..., 2]),
    ("probe_C_gfp", "green", img[..., 3]),
]

for name, colormap, channel in channels:
    viewer.add_image(channel, name=name, colormap=colormap,
                     blending="additive",
                     contrast_limits=[channel.min(), np.percentile(channel, 99.5)])

napari.run()

よく使うレシピ

レシピ 1:すべてのレイヤーをアノテーション付きの図としてエクスポートする
import os
os.environ["QT_QPA_PLATFORM"] = "offscreen"

import napari
import numpy as np
from skimage import io
import matplotlib.pyplot as plt

viewer = napari.Viewer(show=False)

img = io.imread("cells.tif")
masks = np.load("masks.npy")

viewer.add_image(img, name="raw", colormap="gray")
viewer.add_labels(masks, name="segmentation", opacity=0.5)

# Set camera zoom and position
viewer.camera.zoom = 1.5
viewer.camera.center = (img.shape[0] // 2, img.shape[1] // 2)

screenshot = viewer.screenshot(path="figure_panel.png", canvas_only=True)
viewer.close()

# Add scalebar with matplotlib
fig, ax = plt.subplots(figsize=(6, 6))
ax.imshow(screenshot)
ax.axis("off")
plt.tight_layout()
plt.savefig("figure_final.pdf", dpi=300, bbox_inches="tight")
print("Exported: figure_final.pdf")
レシピ 2:Z スタックの投影画像を一括エクスポートする
import os
os.environ["QT_QPA_PLATFORM"] = "offscreen"

import napari
import numpy as np
from skimage import io
from pathlib import Path

output_dir = Path("projections")
output_dir.mkdir(exist_ok=True)

for img_path in sorted(Path("zstacks").glob("*.tif")):
    zstack = io.imread(img_path)  # shape: (Z, H, W)
    max_proj = zstack.max(axis=0)
    
    viewer = napari.Viewer(show=False)
    viewer.add_image(max_proj, name="max_projection", colormap="gray")
    viewer.screenshot(path=str(output_dir / f"{img_path.stem}_maxproj.png"), canvas_only=True)
    viewer.close()
    print(f"Exported: {img_path.stem}_maxproj.png")

print("All z-stack projections exported.")

トラブルシューティング

問題原因解決策
qt.qpa.plugin: Could not load the Qt platform plugin "xcb"ディスプレイまたは Qt プラットフォームプラグインが不足していますnapari をインポートする前に QT_QPA_PLATFORM=offscreen を設定し、libxcb-util-dev をインストールします
napari のウィンドウが開かないX フォワーディングなしで SSH を実行していますviewer = napari.Viewer(show=False) を使用し、screenshot() でエクスポートします
大きな画像のレンダリングが遅い画像が GPU の VRAM に対して大きすぎますピラミッド型レンダリングには viewer.add_image(img, multiscale=True) を使用します
ラベルレイヤーの色が正しく表示されないマスクのデータ型がオーバーフローしていますマスクが uint8 ではなく int32 であることを確認します(255 セルでオーバーフローします)
napari.run() が Jupyter ノートブックをブロックするQt のイベントループが競合していますJupyter では %gui qt マジックを使用するか、napari.run() を使わずに viewer.show() を使用します
スクリーンショットが黒い、または空になるスクリーンショットの撮影前にビューアーのレンダリングが完了していませんscreenshot() の前に viewer.update() を呼び出すか、少し待機します
プラグインがメニューに表示されないプラグインがインストールされていないか、napari のバージョンが適合していませんpip install napari-<plugin> を実行し、napari-hub で napari のバージョンとの互換性を確認します
3D レンダリングが遅いジオメトリが複雑、またはボリュームが大きいviewer.dims.ndisplay = 2 に切り替え、Z スタックの深さを減らします

参考資料

コメント