napari-image-viewer について
napari-image-viewer は、napari による多次元科学画像の表示、注釈、可視化を紹介するスキルです。生物画像研究者や Python ユーザー向けで、レイヤー表示や画面のない環境でのスクリーンショット出力を扱います。
主な機能
- 01画像・ラベル・ポイント・シェイプレイヤー
- 023Dスタックと時系列の操作
- 03コントラスト調整付きマルチチャンネル表示
- 04オフスクリーン描画とスクリーンショット出力
- 05プラグインを使った分析ワークフロー
活用シーン
- 01顕微鏡画像とセグメンテーションマスクの確認
- 02セグメンテーションモデル用データの注釈
- 03複数画像チャンネルの比較
- 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()
主なパラメーター
| パラメーター | モジュール | デフォルト | 効果 |
|---|---|---|---|
colormap | add_image | "gray" | カラーマップ名(matplotlib のカラーマップと napari の組み込みカラーマップ:"green"、"blue"、"cyan") |
contrast_limits | add_image | auto | 表示用の輝度クリッピング範囲 [min, max] |
blending | add_image | "translucent" | 複数チャンネルの重ね合わせには "additive"、不透明表示には "opaque" |
opacity | add_labels | 0.7 | 画像上に重ねるラベルレイヤーの透明度(0~1) |
face_color | add_points | "white" | ポイントの塗りつぶし色(名前、16 進数、または RGBA) |
size | add_points | 10 | データ座標でのポイント半径(ピクセル) |
edge_width | add_shapes | 1 | 図形の輪郭線の幅(ピクセル) |
show | Viewer() | True | ヘッドレス/オフスクリーンモードでは False |
ndisplay | Viewer() | 2 | 3D OpenGL レンダリングモードでは 3 |
canvas_only | screenshot() | 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 スタックの深さを減らします |
参考資料
- napari ドキュメント — 公式 API リファレンスとチュートリアル
- napari GitHub: napari/napari — ソースコードとプラグイン開発ガイド
- Sofroniew N et al. (2022)「napari: a multi-dimensional image viewer for Python」— Zenodo。DOI:10.5281/zenodo.3555620
- napari-hub — 300 以上のコミュニティ製解析プラグインを掲載するプラグインレジストリ