关于 napari-image-viewer
napari-image-viewer 是一项介绍 napari 的技能,帮助生物图像研究者和 Python 用户查看、标注及可视化多维科学图像。其内容涵盖分层数据视图和无显示环境下的截图导出。
主要功能
- 01图像、标签、点和形状分层显示
- 02浏览 3D 堆栈与时间序列
- 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-stack 和 4D 延时实验
- 从 GUI 导出已注释的屏幕截图或标签掩膜,用于发表论文的图表
- 交互式运行基于插件的分析(Cellpose napari 插件、StarDist 插件、n2v 去噪)
- 使用 ImageJ/FIJI 进行宏/批处理脚本编写,尽量减少对 Python 的依赖
- 使用 ITK-SNAP 作为医学影像(DICOM、NIfTI)分割的替代方案
前置条件
- 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-stack 和时间序列。
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 cmaps + 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" | 点的填充颜色(名称、十六进制值或 RGBA) |
size | add_points | 10 | 点在数据坐标中的半径(像素) |
edge_width | add_shapes | 1 | 形状轮廓宽度(像素) |
show | Viewer() | True | 无头/离屏模式使用 False |
ndisplay | Viewer() | 2 | 使用 3 启用 3D OpenGL 渲染模式 |
canvas_only | screenshot() | False | 使用 True 可在导出时排除 napari 工具栏 |
常见工作流
工作流 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-stack 投影
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 窗口未打开 | 在 SSH 中运行,且未启用 X 转发 | 使用 viewer = napari.Viewer(show=False),并通过 screenshot() 导出 |
| 大型图像渲染缓慢 | 图像对于 GPU 显存来说过大 | 使用 viewer.add_image(img, multiscale=True) 进行金字塔渲染 |
| Labels 图层显示的颜色不正确 | 掩码数据类型溢出 | 确保掩码为 int32 而非 uint8(超过 255 个单元格时会溢出) |
napari.run() 阻塞 Jupyter 笔记本 | Qt 事件循环冲突 | 在 Jupyter 中使用 %gui qt 魔法命令;或使用 viewer.show(),而不调用 napari.run() |
| 截图为黑屏或空白 | 截图前查看器尚未完全渲染 | 在调用 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 等(2022)“napari: a multi-dimensional image viewer for Python” — Zenodo。DOI:10.5281/zenodo.3555620
- napari-hub — 插件注册中心,提供 300 多个社区分析插件
评论
支持 Markdown