一、napari 簡介
napari 是一個基于 Python 的科學圖像和體積數(shù)據(jù)可視化工具,專注于提供交互性和可擴展性。其提供了一個交互式的圖像和數(shù)據(jù)可視化環(huán)境,使用戶能夠探索、分析和處理科學圖像、體積數(shù)據(jù)和其他多維數(shù)據(jù)。
napari支持用戶自定義界面及數(shù)據(jù)交互:由于napari的GUI圖形用戶界面是基于 PyQt 庫創(chuàng)建,故用戶只需要通過PyQt自定義組件后,然后添加到napari圖層就可以實現(xiàn)自定義組件顯示。
napari: a fast, interactive viewer for multi-dimensional images in Python
napari:基于 Python 編寫的快速、交互式多維圖像查看器
??napari 官網(wǎng)首頁:https://napari.org/0.4.18/index.html#
??napari 使用案例:https://napari.org/0.4.18/gallery.html#gallery
二、napari 安裝與更新
- 安裝napari:
pip install napari
- 更新napari:
pip install --upgrade napari
三、napari【巨巨巨大的一個BUG】
【BUG】
:點擊View - Toggle Full Screen將最大化軟件界面,且菜單欄和很多按鈕都將不可用。【影響】
:此時,想要任何操作都無法退出最大化,即使關(guān)閉后重試,卸載后重試都無法達到,沒有試過關(guān)機后重試。【解決方法】
:Window + Tab切換窗口,菜單欄可以短暫有效且可點擊,瞬間點擊View - Toggle Full Screen,可解除BUG。
四、napari 使用指南
4.1、菜單欄(File + View + Plugins + Window + Help)
File(文件) | ||
---|---|---|
1 | Open File | 打開文件 |
2 | Opencv File as Stack | 打開文件(適用于大尺度) |
3 | Open Sample + napari builtins(提供了很多的內(nèi)置樣本) | 初學者可以直接導入后研究 |
4 | Preferences | 設置(主題 + 快捷鍵等等) |
5 | Save Selected Layer(s)(所有幀圖像) | 保存選定的單層或多層(指定后綴,修改圖像格式) |
6 | Save All Layers(所有幀圖像) | 保存所有層(指定后綴,修改圖像格式) |
7 | Save Screenshot(單幀圖像) | 保存當前窗口內(nèi)容(不顯示界面) |
8 | Save Screenshot with Viewer(單幀圖像) | 保存整個視圖內(nèi)容(圖像 + 界面) |
- Plugins(插件):安裝和卸載插件(也可以自定義)
View(視圖) | ||
---|---|---|
1 | Axes | 軸 |
2 | Scale Bar | 刻度條 |
3 | Toggle Full Screen | 切換全屏 |
4 | Toggle Menubar Visibity | 切換菜單可見性 |
5 | Toggle Paly | 切換面板 |
6 | Toggle Layer Tooltips | 切換圖層工具提示 |
7 | Toggle Activity Dock | 切換活動區(qū) |
Window(窗口) | ||
---|---|---|
1 | console | 控制面板(命令行窗口) |
2 | layer controls | 圖層控制(點層、形狀層、標簽層) |
3 | layer list | 圖層列表 |
Help(幫助) | 直接跳轉(zhuǎn)官網(wǎng)頁面 | |
---|---|---|
1 | Getting started | 開始 |
2 | Tutorials | 教程 |
3 | Using Layers Guides | 使用圖層指南 |
4 | Examples Gallery | 示例圖庫 |
5 | Release Notes | 版本說明 |
6 | napari homepage | napari 主頁 |
7 | napari Info | napari 信息 |
4.2、Window:layer list(參數(shù)詳解)
4.3、Window:layer controls(points layer + shapes layer + labels layer)
五、項目實戰(zhàn)
5.0、啟動napari
在Pycharm的Terminal中輸入:napari
。然后將顯示napari的初始化界面,可以直接拖拽一個或多個圖像到界面中進行圖形化顯示。
5.1、查看圖像層:napari.view_image()
在napari查看器中顯示單個或多個圖像,并提供了許多可選參數(shù)來自定義圖像的顯示。
import napari
import tifffile
image_path = 'output_8bit.tif'
marked_image = tifffile.imread(image_path)
viewer = napari.view_image(marked_image, name='image', rgb=False)
napari.run()
# 備注:若不添加napari.run(),將避免程序阻塞問題(一直等待界面關(guān)閉)
"""
#########################################################################################################
# 函數(shù)功能:創(chuàng)建一個 napari 查看器(Viewer),并在查看器中顯示圖像。
# 函數(shù)說明:napari.view_image(data, *, name=None, channel_axis=None, colormap=None, blending=None, interpolation=None, gamma=None, is_pyramid=None, rgb=None, scale=None, translate=None, contrast_limits=None, rendering=None)
# 輸入?yún)?shù):
# - data:要顯示的圖像數(shù)據(jù)??梢允且韵赂袷街唬?# 2D NumPy array:灰度圖像數(shù)據(jù)。
# 3D NumPy array:3D圖像數(shù)據(jù),例如多張2D圖像疊加形成的圖像序列。
# 4D NumPy array:4D圖像數(shù)據(jù),例如多通道彩色圖像。
# List of 2D, 3D, or 4D arrays:多個圖像數(shù)據(jù)列表。
# Dask array:支持分塊加載的大型圖像數(shù)據(jù)。
# ImageData:來自dask_image.imread()等函數(shù)的圖像數(shù)據(jù)對象。
# - name: 圖像的名稱,將在napari查看器中顯示。
# channel_axis: 用于多通道圖像的通道軸的索引。默認值為None,表示使用最后一個軸作為通道軸。
# - colormap: 圖像的顏色映射??梢允亲址硎镜念伾成涿Q,或是colormap函數(shù)。默認值為None,表示使用默認顏色映射。
# blending: 圖像的混合模式。可以是字符串表示的混合模式名稱,例如"translucent"、"additive"等。默認值為None,表示使用默認混合模式。
# interpolation: 圖像的插值方法。可以是字符串表示的插值方法名稱,例如"nearest"、"bilinear"、"bicubic"等。默認值為None,表示使用默認插值方法。
# gamma: 圖像的gamma值,用于對圖像進行伽馬校正。默認值為None,表示不進行伽馬校正。
# is_pyramid: 布爾值,用于指示是否使用金字塔結(jié)構(gòu)顯示圖像。默認值為None,表示不使用金字塔結(jié)構(gòu)。
# rgb: 布爾值,用于指示輸入圖像是否為RGB彩色圖像。默認值為None,表示根據(jù)輸入圖像數(shù)據(jù)自動判斷。
# scale: 圖像的縮放因子。可以是單個值,表示在所有軸上應用相同的縮放,也可以是每個軸的縮放因子列表。默認值為None,表示不進行縮放。
# translate: 圖像的平移量。可以是單個值,表示在所有軸上應用相同的平移,也可以是每個軸的平移量列表。默認值為None,表示不進行平移。
# contrast_limits: 圖像的對比度限制,用于控制圖像顯示的亮度范圍??梢允菃蝹€值,表示在所有軸上應用相同的對比度限制,也可以是每個軸的對比度限制列表。默認值為None,表示不設置對比度限制。
# rendering: 圖像的渲染模式??梢允亲址硎镜匿秩灸J矫Q,例如"mip"、"translucent"、"attenuated_mip"等。默認值為None,表示使用默認渲染模式。
#########################################################################################################
"""
5.2、添加圖像層:viewer.add_image()
將單個或多個圖像添加到napari查看器中,并提供了多個可選參數(shù)來自定義圖像的顯示。
import napari
import tifffile
image_path = '561result-1-part.tif'
marked_image = tifffile.imread(image_path)
viewer = napari.Viewer() # 創(chuàng)建napari視圖
viewer.add_image(marked_image, name="image", colormap='red') # 添加圖像(指定紅色)
################################################################################
# 隱藏面板
# viewer.window.qt_viewer.controls.hide() # 隱藏后不可使用該功能(重新打開也不行)
# viewer.window.qt_viewer.layers.hide()
# viewer.window.qt_viewer.controls.close()
# viewer.window.qt_viewer.layers.close()
################################################################################
napari.run() # 顯示napari圖形界面
# 備注:若不添加napari.run(),將避免程序阻塞問題(一直等待界面關(guān)閉)
"""
#########################################################################################################
# 函數(shù)功能:用于在 napari 視圖中添加圖像圖層,允許您可視化圖像數(shù)據(jù)。
# 函數(shù)說明:viewer.add_image(data, *, name=None, scale=None, translate=None, contrast_limits=None,
# colormap=None, blending=None, visible=True, opacity=1.0, interpolation='bilinear',
# rendering='mip', rgb=None, colormap_range=None)
# 輸入?yún)?shù):
# - data: 必選參數(shù),圖像數(shù)據(jù)。通常是一個 NumPy 數(shù)組,表示圖像的像素值??梢允?2D 圖像、3D 圖像或多通道圖像,具體取決于您的數(shù)據(jù)。
# - name: 可選參數(shù),圖像名稱,將在napari查看器中顯示。
##########################################
# scale: 可選參數(shù),圖像的縮放因子。默認為 None,表示不進行縮放。
# translate: 可選參數(shù),圖像的平移量。默認為 None,表示不進行平移。
# rotate: 可選參數(shù),圖像的旋轉(zhuǎn)角度。默認為 None,表示不進行旋轉(zhuǎn)。
# interpolation: 可選參數(shù),圖像的插值方法。用于在縮放或變換時平滑圖像。
默認為 'linear',表示線性插值。其他可能的值包括 'nearest'(最近鄰插值)等。
##########################################
# rgb: 可選參數(shù),(布爾值)用于指示輸入圖像是否為RGB彩色圖像。
# - colormap: 可選參數(shù),圖像的顏色映射。默認為 'gray',表示灰度圖??梢赃x擇其他顏色映射,如 'viridis'、'cividis' 等。
# colormap_range: 可選參數(shù),顏色映射的范圍??梢允亲址?,例如"auto"或"full",表示自動計算顏色映射范圍或使用完整范圍。
##########################################
# blending: 可選參數(shù),圖像的混合模式。即圖像如何與其他圖層疊加。
# 默認為 'translucent',表示半透明。其他可能的值包括 'opaque'(不透明)和 'additive'(疊加)等。
# visible: 可選參數(shù),圖像是否可見。默認為 True,表示圖像可見。
# opacity: 可選參數(shù),圖像的不透明度。默認為1.0,表示完全不透明。
##########################################
# - contrast_limits: 可選參數(shù),調(diào)整圖像的對比度,默認為 None,表示不進行對比度調(diào)整。
# 通常是一個包含兩個值的元組,表示對比度的最小和最大值。例如 (0, 255),圖像的像素值將線性映射到指定的范圍內(nèi)。
# - gamma: 可選參數(shù),調(diào)整圖像的伽馬校正。默認為 1.0,表示不進行伽馬校正。
# 較低的值可以增加圖像的亮度,較高的值可以增加圖像的對比度。
##########################################
# - rendering: 可選參數(shù),圖像的渲染方法。不同的渲染方法可以影響圖像的可視化效果。
'mip'(默認值): 最大強度渲染。 選擇每個像素沿視線方向上的最大值來渲染圖像。通常用于顯示有深度信息的圖像,如體繪圖。
'minimum': 最小強度渲染。 選擇每個像素沿視線方向上的最小值來渲染圖像。通常用于查看圖像中的最暗特征,如血管。
'attenuated_mip': 衰減最大強度投影。根據(jù)深度進行衰減,距離視線近的像素比遠處的像素更容易看到。適用于可視化深度信息的圖像。
'translucent': 半透明渲染。 根據(jù)像素的亮度來渲染圖像,較暗的像素會顯示為半透明。適用于需要突出細節(jié)的圖像。
'translucent_no_depth':半透明但不考慮深度信息渲染。
'additive': 多通道渲染。 將像素的亮度相加,而不是取最大值。適用于需要將多個圖像疊加在一起的情況,如疊加多通道的彩色圖像。
'iso': 等值面渲染。 將圖像中所有像素值相同的區(qū)域渲染為等值面,適用于可視化等值面數(shù)據(jù)的圖像。
#########################################################################################################
"""
5.3、添加點云層:viewer.add_points() —— 獲取點坐標
將點的坐標和可選的其他屬性添加到napari查看器中,并提供了多個可選參數(shù)來自定義點云的顯示。
點云數(shù)據(jù):由離散點(x, y, z)坐標的集合組成。
import napari
# (1)創(chuàng)建napari Viewer
viewer = napari.Viewer() # 創(chuàng)建napari查看器
points_layer = viewer.add_points(size=5, face_color='red', edge_color='green', name='Points') # 添加點層
viewer.layers['Points'].mode = 'add' # 打開點繪制模式
napari.run() # 運行napari
# (2)打印坐標
points_data = viewer.layers['Points'].data # 獲取繪制的點的圖層
print("繪制的點:\n", points_data) # points_data坐標順序:[y, x]
"""
#########################################################################################################
# 函數(shù)功能:用于在 napari 視圖中添加點圖層,它允許您可視化點數(shù)據(jù)。
# 函數(shù)說明:viewer.add_points(data, *, name=None, face_color='white', edge_color='black', size=10,
# symbol='o', edge_width=1, opacity=1.0, blending='translucent')
#
# 輸入?yún)?shù):
# - data: 點的坐標數(shù)據(jù)。用于指定點的位置坐標,可以接受不同維度的數(shù)據(jù)。
# 對于 2D 數(shù)據(jù),data 可以是一個形狀為 (N, 2) 的數(shù)組,其中 N 表示點的數(shù)量,每行包含點的 X 和 Y 坐標。
# 對于 3D 數(shù)據(jù),data 可以是一個形狀為 (N, 3) 的數(shù)組,其中每行包含點的 X、Y 和 Z 坐標。
# 對于更高維度的數(shù)據(jù),data 的形狀會相應地增加,以包含更多的坐標信息。
# - name: 圖層的名稱,用于標識圖層。默認為 None。
# - face_color: 點的填充顏色。默認為紅色 ('red')。
# edge_color: 點的邊緣顏色。默認為紅色 ('red')。
# - size: 點的大小。默認為 10(單位:像素),表示點的直徑。
# symbol: 點的形狀。默認為圓形點: 'o'
# 's':表示方形點。 '+':表示十字形點。 'x':表示X形點。
# 'd':表示菱形點。 '>':表示朝右箭頭。 '<':表示朝左箭頭。
# '^':表示朝上箭頭。 'v':表示朝下箭頭。 '1':表示下箭頭。
# '2':表示上箭頭。 '3':表示左箭頭。 '4':表示右箭頭。
# - shading: 點的著色方式。用于控制渲染點圖層時的著色方式。指定點的渲染方式,以改變點的外觀。
# 'flat': 默認值。使用平面著色,使點看起來像扁平的二維圖標。這是最常見的著色方式,適用于大多數(shù)情況。
# 'smooth': 使用平滑的漸變著色,使點看起來更加光滑和立體。這種著色方式可以讓點看起來更加圓潤,適用于需要強調(diào)點的立體感的情況。
# 'spherical':使用球形著色,使點看起來像立體的球體。這種著色方式強調(diào)了點的立體感,尤其在 3D 空間中使用時效果明顯。
# edge_width: 點的邊緣寬度。默認為 1(單位:像素)。
# opacity: 點的不透明度。默認為 1.0,表示完全不透明。取值范圍為 0(完全透明)到 1(完全不透明)之間。
# blending: 點的混合模式,控制點的渲染方式??梢允?'translucent'(默認值,半透明)、'opaque'(不透明)和 'additive'(疊加)等。
#########################################################################################################
"""
5.4、添加形狀層:viewer.add_shapes() —— 獲取線條坐標(起點和終點)
- napari會根據(jù)實際繪制線條的方向自動獲取線條的起點和終點,而不是隨機情況。
- 切換到n維顯示模式(
viewer.dims.ndisplay = 3
)將導致無法選定線條繪制,但切換網(wǎng)格模式不會有影響。
注意:shapes層和image_data層是兩個獨立的層,故線的坐標映射到image_data需要進行高度和寬度限制。
import napari
import cv2
# (1)加載圖像
image_path = 'blank.png'
image_data = cv2.imread(image_path)
print("height:", image_data.shape[0], "width:", image_data.shape[1])
# (2)創(chuàng)建napari Viewer
viewer = napari.Viewer() # 創(chuàng)建napari查看器
viewer.add_image(image_data) # 添加圖像
shapes_layer = viewer.add_shapes(data=None, shape_type='line', edge_width=3, edge_color='red') # 添加形狀(線條 + 線寬 + 顏色)
shapes_layer.mode = 'add_line' # 直接開始繪制線條
napari.run() # 運行napari
# 備注:若不添加napari.run(),將避免程序阻塞問題(一直等待界面關(guān)閉)
# (3)打印坐標
# image_shape = image_data.shape # 獲取圖像的形狀
line_layer = viewer.layers['Shapes'] # 獲取繪制的線的圖層
line_coordinates1 = [] # 獲取繪制的所有線的坐標
line_coordinates2 = [] # 獲取繪制的所有線的坐標:刪除超出圖像的線條
if line_layer.data: # 檢查圖層數(shù)據(jù)是否存在
for line in line_layer.data: # 遍歷線的坐標
coordinates1 = [line[0, 0], line[0, 1], line[1, 0], line[1, 1]]
line_coordinates1.append(coordinates1)
for line in line_layer.data: # 遍歷線的坐標
# 【高度限制】:刪除超出圖像的線條
if line[0, 0] < 0:
line[0, 0] = 0
elif line[0, 0] > image_data.shape[0]:
line[0, 0] = image_data.shape[0]
if line[1, 0] < 0:
line[1, 0] = 0
elif line[1, 0] > image_data.shape[0]:
line[1, 0] = image_data.shape[0]
# 【寬度限制】:刪除超出圖像的線條
if line[0, 1] < 0:
line[0, 1] = 0
elif line[0, 1] > image_data.shape[1]:
line[0, 1] = image_data.shape[1]
if line[1, 1] < 0:
line[1, 1] = 0
elif line[1, 1] > image_data.shape[1]:
line[1, 1] = image_data.shape[1]
# 坐標獲取:[y1, x1, y2, x2]
coordinates2 = [line[0, 0], line[0, 1], line[1, 0], line[1, 1]]
line_coordinates2.append(coordinates2)
# 輸出所有坐標(shapes:線坐標)
for idx, coordinates in enumerate(line_coordinates1):
print(f'Line {idx + 1} coordinates1:', coordinates)
print("")
# 輸出所有坐標(image:線坐標映射到圖像的坐標):高度限制+寬度限制
for idx, coordinates in enumerate(line_coordinates2):
print(f'Line {idx + 1} coordinates2:', coordinates)
"""
#########################################################################################################
# 函數(shù)功能:用于在 napari 視圖中添加形狀圖層,允許您可視化和編輯形狀數(shù)據(jù)。
# 函數(shù)說明:viewer.add_shapes(data=None, shape_type='rectangle', edge_color='red', face_color='transparent',
# opacity=1.0, edge_width=1, blending='translucent', name=None)
# 輸入?yún)?shù):
# - data: 包含形狀數(shù)據(jù)的列表。
# (1)列表中可以包含多個形狀字典,每個字典描述一個形狀。
# (2)字典中包含形狀的類型、坐標、邊框顏色、填充顏色等信息。
# data = [{'type': 'rectangle', 'roi': [x1, y1, x2, y2], 'edge_color': 'red', 'face_color': 'transparent'}]
# - name: 形狀圖層的名稱,用于標識圖層。默認為 None。
# - shape_type: 指定要繪制的形狀類型。默認為 'rectangle',表示繪制矩形。其他可能的值包括 'line'(線條)、'ellipse'(橢圓)等。
# edge_color: 形狀的邊框顏色。默認為 'red',表示紅色。
# face_color: 形狀的填充顏色。默認為 'transparent',表示透明填充。
# opacity: 形狀的不透明度,用于控制形狀的透明度。默認為 1.0,表示完全不透明。
# edge_width: 形狀的邊框?qū)挾?,用于指定形狀的邊框線寬。默認為 1。
# blending: 形狀的混合模式,用于指定形狀的繪制方式。默認為 'translucent',表示半透明。其他可能的值包括 'opaque'(不透明)和 'additive'(疊加)等。
#########################################################################################################
"""
六、擴展功能
6.1、在PyQt中,自定義組件,并添加到napari中,且完成數(shù)據(jù)交互
- 備注:napari沒有提供鼠標點擊事件的接口。
- 在napari中自定義組件與PyQt新建組件的方法相同,區(qū)別是需要將組件的主窗口添加到napari界面的控制面板中:
self.viewer.window.add_dock_widget(widget, area='right') # 添加到napari的右側(cè)
,其中:widget是插件的主窗口。
import tifffile
import napari
import numpy as np
import sys
import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, \
QPushButton, QFileDialog, QTextEdit, QSlider, QCheckBox
from PyQt5.QtCore import Qt
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Window")
##########################################################
layout = QVBoxLayout()
button_layout = QHBoxLayout()
self.load_button = QPushButton("Load Image", self)
self.load_button.clicked.connect(self.load_image)
self.image_name_label = QLabel("")
button_layout.addWidget(self.load_button)
button_layout.addWidget(self.image_name_label)
layout.addLayout(button_layout)
##########################################################
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
##########################################################
# 初始化參數(shù)
self.image_path = ""
self.image_name = ""
##########################################################
def load_image(self):
file_dialog = QFileDialog()
image_path, _ = file_dialog.getOpenFileName(self, "Select Image", "", "Image Files (*.tif *.png *.jpg *.jpeg)")
if image_path:
self.image_path = image_path
self.image_name = os.path.basename(image_path)
self.image_name_label.setText(self.image_name)
self.image_slices = tifffile.imread(image_path)
self.napari_gray_view() # 調(diào)用napari_gray_view方法來顯示第一個切片
def napari_gray_view(self):
# (1)napari:創(chuàng)建視圖、添加圖層、顯示視圖
self.viewer = napari.Viewer() # 創(chuàng)建napari視圖
self.viewer.add_image(self.image_slices, name='image') # 添加napari圖層
# napari.run() # 顯示napari圖形界面
# 備注:若不添加napari.run(),將避免程序阻塞問題(一直等待界面關(guān)閉)
#########################################################################
# (2)自定義組件
#########################################################################
# (2.1)創(chuàng)建滑動條
self.slider = QSlider() # 新建滑動條
self.slider.setMinimum(0) # 設置滑動條的最小值
self.slider.setMaximum(np.max(self.image_slices)) # 設置滑動條的最大值
self.slider.setValue(0) # 設置滑動條的初始值
# (2.2)創(chuàng)建標簽
self.slider_label = QLabel(str(self.slider.value()))
# (2.3)復選框
self.checkbox = QCheckBox("checkbox") # 復選框
self.slider.setEnabled(False) # 復選框的初始狀態(tài):False
self.input_box = QLineEdit() # 新建輸入框
self.input_box.setEnabled(True) # 復選框的初始狀態(tài):True
self.input_label = QLabel("range: " + str(np.min(self.image_slices)) + "/" + str(np.max(self.image_slices))) # 輸入框標簽
# (3)創(chuàng)建布局并將滑動條和標簽添加到布局中
layout = QVBoxLayout()
layout.addWidget(self.slider)
layout.addWidget(self.slider_label)
layout.addWidget(self.checkbox)
layout.addWidget(self.input_box)
layout.addWidget(self.input_label)
# (4)創(chuàng)建一個QWidget作為插件的主窗口
widget = QWidget()
widget.setLayout(layout)
# (5)連接復選框的狀態(tài)變化信號與槽函數(shù)
self.checkbox.stateChanged.connect(self.onCheckboxStateChanged)
self.slider.valueChanged.connect(self.napari_update_gray) # 根據(jù)滑動條的值,顯示第一個切片
self.input_box.returnPressed.connect(self.napari_update_gray) # 根據(jù)輸入框的值,顯示第一個切片
# (6)將插件的主窗口添加到napari界面的控制面板中
self.viewer.window.add_dock_widget(widget, area='right') # 添加到napari的右側(cè)
#########################################################################
# (7)napari:顯示視圖
self.viewer.window.show()
def onCheckboxStateChanged(self, state):
if state == Qt.Checked:
self.slider.setEnabled(True)
self.input_box.setEnabled(False)
else:
self.slider.setEnabled(False)
self.input_box.setEnabled(True)
def napari_update_gray(self):
# (1)獲取napari視圖中的圖層對象,并獲取圖像數(shù)據(jù)
napari_image = self.image_slices.data
# (2)獲取當前切片滑動條的值
current_slice = int(self.viewer.dims.current_step[0])
# (3)獲取當前灰度滑動條的值
self.slider_label.setText(str(self.slider.value()))
if self.checkbox.isChecked():
current_gray = self.slider.value()
else:
current_gray = int(self.input_box.text())
print("current_slice:", current_slice, "current_gray:", current_gray)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
6.2、在add_points中,提取圖像中指定像素值并繪制成點
viewer.add_points()用于添加點云數(shù)據(jù),但不能直接顯示。需要先添加viewer.view_image(),然后再顯示點云數(shù)據(jù)。
import napari
import numpy as np
# (1)通過tifffile加載tif圖像
marked_image = np.random.rand(10, 10, 10) # 創(chuàng)建一個三維圖像數(shù)據(jù) (10 slices, 100x100 pixels)
marked_image[2:3, 1:4, 5:6] = 2
marked_image[5:8, 4:7, 5:9] = 2
# (2)提取指定像素的坐標
gray_value = 2 # 指定像素值
indices = np.argwhere(marked_image == gray_value) # 獲取像素值坐標
# (3)繪制點層
viewer = napari.Viewer() # 創(chuàng)建napari查看器
viewer.add_image(marked_image) # 添加圖像到napari視圖
viewer.add_points(indices[:, [0, 1, 2]], size=1, face_color='red', shading='spherical', edge_width=0) # 添加點云
viewer.dims.ndisplay = 3 # 切換到n維顯示模式(此時,系統(tǒng)會將兩張圖像融合在一起)
napari.run() # 顯示napari圖形界面
# 備注:若不添加napari.run(),將避免程序阻塞問題(一直等待界面關(guān)閉)
6.2、在add_points中,保存點層的3D圓(napari不支持,自定義繪制)
import numpy as np
import tifffile
import napari
from napari.layers import Points
# 創(chuàng)建一個新的Napari查看器
viewer = napari.Viewer()
####################################################################################
"""替換坐標即可完成點繪制"""
num_points = 50 # 隨機生成50個3D坐標點
points = np.random.randint(0, 100, size=(num_points, 3)) # 在范圍[0, 100)內(nèi)生成隨機坐標
####################################################################################
# 方法一:添加點層
point_layer = viewer.add_points(points, size=10, shading='spherical', edge_color='red', face_color='blue')
# 方法二:創(chuàng)建一個點層并添加坐標點
# point_layer = Points(points, size=10, shading='spherical', edge_color='red', face_color='blue')
# viewer.add_layer(point_layer)
####################################################################################
# 創(chuàng)建一個空白的3D圖像,你需要指定圖像的大?。╯hape)
image_shape = np.zeros((100, 100, 100), dtype=np.uint8) # 例如,創(chuàng)建一個100x100x100的空白圖像
blank_image = np.zeros((*image_shape.shape, 3), dtype=np.uint8)
# 在空白圖像上繪制3D圓
for point in points:
x, y, z = point
rr, cc, dd = np.meshgrid(range(image_shape.shape[0]), range(image_shape.shape[1]), range(image_shape.shape[2]), indexing='ij')
distance = np.sqrt((rr - x)**2 + (cc - y)**2 + (dd - z)**2)
circle_radius = 5 # 3D圓的半徑
circle_mask = distance <= circle_radius
blank_image[circle_mask, 0] = 255 # 紅色通道設置為255,表示紅色
blank_image[circle_mask, 1] = 0 # 綠色通道設置為0,表示綠色
blank_image[circle_mask, 2] = 0 # 藍色通道設置為0,表示藍色
# 保存繪制后的圖像為TIFF文件
tifffile.imsave('output_image.tif', blank_image)
# 啟動Napari查看器以查看繪制的點和圖像
napari.run()
6.3、在add_image中,添加帶箭頭的線條(napari不支持,自定義繪制)
import napari
import cv2
import numpy as np
# 創(chuàng)建napari Viewer
viewer = napari.Viewer()
# 創(chuàng)建空白圖像
image_shape = (300, 400, 3)
image = np.zeros(image_shape, dtype=np.uint8)
# 在圖像上繪制帶箭頭的線條
start_point = (100, 100)
end_point = (300, 200)
arrow_color = (255, 0, 0) # Red color in BGR
# 使用OpenCV繪制帶箭頭的線條
arrow_image = cv2.arrowedLine(image.copy(), start_point, end_point, arrow_color, thickness=2, tipLength=0.3)
# 將OpenCV圖像添加到napari中
viewer.add_image(arrow_image, name='Arrow Line')
# 運行napari
napari.run()
6.4、在add_image中,添加兩張圖像并進行多通道疊加顯示(rendering=“additive”)
import napari
import tifffile
# 加載兩張圖像
image_path1 = r'D:\BIRDS\_coach_path_561temp_BIRDS\registration\coarse\downSampleImage.tif'
image_path2 = r'D:\BIRDS\_coach_path_561temp_BIRDS\registration\coarse\lineImage.tif'
SampleImage = tifffile.imread(image_path1)
lineImage = tifffile.imread(image_path2)
viewer = napari.Viewer() # 創(chuàng)建napari Viewer
viewer.add_image(SampleImage[500], name='SampleImage') # 添加幀圖像
viewer.add_image(lineImage[500], name='lineImage', colormap='green', rendering="additive") # 添加幀圖像
napari.run() # 顯示napari圖形界面
6.4、在add_image中,添加兩張圖像并自動切換到n維顯示模式(Toggle ndisplay)
import napari
import tifffile
# 加載兩張圖像
image_path1 = r'C:\Users\Administrator\Desktop\py\SampleImage.tif'
image_path2 = r'C:\Users\Administrator\Desktop\py\lineImage.tif'
image_data1 = tifffile.imread(image_path1)
image_data2 = tifffile.imread(image_path2)
viewer = napari.Viewer() # 創(chuàng)建napari Viewer
viewer.add_image(SampleImage[500], name='SampleImage') # 添加幀圖像
viewer.add_image(lineImage[500], name='lineImage', colormap='green') # 添加幀圖像
""""添加圖像:后一個會自動覆蓋在前一個上,故需要注意順序"""
viewer.dims.ndisplay = 3 # 切換到n維顯示模式(此時,系統(tǒng)會將兩張圖像融合在一起)
napari.run() # 顯示napari圖形界面
6.5、在add_image中,添加兩張圖像并自動切換網(wǎng)格模式(Toggle grid mode)
文章來源:http://www.zghlxwxcb.cn/news/detail-650639.html
import napari
import tifffile
# 加載兩張圖像
image_path1 = r'C:\Users\Administrator\Desktop\py\SampleImage.tif'
image_path2 = r'C:\Users\Administrator\Desktop\py\lineImage.tif'
image_data1 = tifffile.imread(image_path1)
image_data2 = tifffile.imread(image_path2)
# 創(chuàng)建napari Viewer
viewer = napari.Viewer()
viewer.add_image(image_data1, name='Image 1', colormap='red')
viewer.add_image(image_data2, name='Image 2', colormap='green')
# 切換網(wǎng)格模式
viewer.grid.enabled = not viewer.grid.enabled
# 顯示napari圖形界面
napari.run()
6.6、在add_image中,獲取圖像層的slice值
(1)在 napari 中,通過訪問 viewer.dims.current_step 屬性可以獲取當前圖像層的屬性。其中:viewer.dims.current_step[0]表示獲取 slice 值。
(2)通過slice滑動條可以更改當前slice,但 viewer.dims.current_step 的值不會自動更新,可以使用回調(diào)函數(shù)來監(jiān)聽 viewer.dims.events 的變化。文章來源地址http://www.zghlxwxcb.cn/news/detail-650639.html
import napari
import numpy as np
viewer = napari.Viewer() # 創(chuàng)建 napari 視圖
image_data = np.random.rand(10, 100, 100) # 創(chuàng)建一個三維圖像數(shù)據(jù) (10 slices, 100x100 pixels)
image_layer = viewer.add_image(image_data, name='My Image') # 添加圖像圖層
"""創(chuàng)建一個回調(diào)函數(shù),獲取更新的切片值"""
def update_current_slice(event):
current_slice = viewer.dims.current_step[0] # 獲取當前 slice 值
print("Current Slice Value:", current_slice)
# 監(jiān)聽 dims 的變化
viewer.dims.events.current_step.connect(update_current_slice)
napari.run() # 運行 napari
6.7、在add_image中,獲取圖像層的參數(shù)contrast_limits + gamma
import napari
import numpy as np
viewer = napari.Viewer() # 創(chuàng)建 napari 視圖
image_data = np.random.rand(10, 100, 100) # 創(chuàng)建一個三維圖像數(shù)據(jù) (10 slices, 100x100 pixels)
image_layer = viewer.add_image(image_data, name='Image', contrast_limits=None, gamma=1) # 添加圖像層
##############################################################################
"""
對比度限制和伽馬校正參數(shù): 不會在圖像圖層的顯示期間自動更新
"""
contrast_limits_value = image_layer.contrast_limits # 獲取圖層的對比度限制參數(shù)
gamma_value = image_layer.gamma # 獲取圖層的伽馬校正參數(shù)
print("初始參數(shù) =", contrast_limits_value, gamma_value)
napari.run() # 運行 napari
contrast_limits_value2 = image_layer.contrast_limits
gamma_value2 = image_layer.gamma
print("參數(shù)1 =", contrast_limits_value2, gamma_value2)
##############################################################################
"""
在圖像層添加后再次運行 napari.run() 來重新啟動 napari 查看器,那么之前的圖像圖層和參數(shù)將會被丟棄,因此 contrast_limits 和 gamma 的值會恢復為默認值。
viewer = napari.Viewer() # 創(chuàng)建 napari 視圖
viewer.layers.clear() # 清空 napari 圖層
viewer.add_image() # 添加 napari 圖層
"""
viewer.layers.clear() # 清空圖層
image_data = np.random.rand(10, 100, 100) # 創(chuàng)建一個三維圖像數(shù)據(jù) (10 slices, 100x100 pixels)
image_layer = viewer.add_image(image_data, name='Image', contrast_limits=contrast_limits_value2, gamma=gamma_value2)
napari.run() # 運行 napari
contrast_limits_value2 = image_layer.contrast_limits
gamma_value2 = image_layer.gamma
print("參數(shù)2 =", contrast_limits_value2, gamma_value2)
到了這里,關(guān)于Python項目實戰(zhàn):基于napari的3D可視化(點云+slice)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!