Python项目实战:基于napari的3D可视化(点云+slice)

这篇具有很好参考价值的文章主要介绍了Python项目实战:基于napari的3D可视化(点云+slice)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、napari 简介

napari 是一个基于 Python 的科学图像和体积数据可视化工具,专注于提供交互性和可扩展性。其提供了一个交互式的图像和数据可视化环境,使用户能够探索、分析和处理科学图像、体积数据和其他多维数据。

napari支持用户自定义界面及数据交互:由于napari的GUI图形用户界面是基于 PyQt 库创建,故用户只需要通过PyQt自定义组件后,然后添加到napari图层就可以实现自定义组件显示。

napari: a fast, interactive viewer for multi-dimensional images in Python
napari:基于 Python 编写的快速、交互式多维图像查看器
🥗napari 官网首页: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将最大化软件界面,且菜单栏和很多按钮都将不可用。
  • 【影响】:此时,想要任何操作都无法退出最大化,即使关闭后重试,卸载后重试都无法达到,没有试过关机后重试。
  • 【解决方法】: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(提供了很多的内置样本) 初学者可以直接导入后研究
4 Preferences 设置(主题 + 快捷键等等)
5 Save Selected Layer(s)(所有帧图像) 保存选定的单层或多层(指定后缀,修改图像格式)
6 Save All Layers(所有帧图像) 保存所有层(指定后缀,修改图像格式)
7 Save Screenshot(单帧图像) 保存当前窗口内容(不显示界面)
8 Save Screenshot with Viewer(单帧图像) 保存整个视图内容(图像 + 界面)
  • 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 切换活动区
Window(窗口)
1 console 控制面板(命令行窗口)
2 layer controls 图层控制(点层、形状层、标签层)
3 layer list 图层列表
Help(帮助) 直接跳转官网页面
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(参数详解)

Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

4.3、Window:layer controls(points layer + shapes layer + labels layer)

Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

五、项目实战

5.0、启动napari

在Pycharm的Terminal中输入:napari。然后将显示napari的初始化界面,可以直接拖拽一个或多个图像到界面中进行图形化显示。

5.1、查看图像层:napari.view_image()

在napari查看器中显示单个或多个图像,并提供了许多可选参数来自定义图像的显示。

Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

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(),将避免程序阻塞问题(一直等待界面关闭)

"""
#########################################################################################################
# 函数功能:创建一个 napari 查看器(Viewer),并在查看器中显示图像。
# 函数说明: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)
# 输入参数:
#       - data:要显示的图像数据。可以是以下格式之一:
#                 2D NumPy array:灰度图像数据。
#                 3D NumPy array:3D图像数据,例如多张2D图像叠加形成的图像序列。
#                 4D NumPy array:4D图像数据,例如多通道彩色图像。
#                 List of 2D, 3D, or 4D arrays:多个图像数据列表。
#                 Dask array:支持分块加载的大型图像数据。
#                 ImageData:来自dask_image.imread()等函数的图像数据对象。
#       - name:             图像的名称,将在napari查看器中显示。
#         channel_axis:     用于多通道图像的通道轴的索引。默认值为None,表示使用最后一个轴作为通道轴。
#       - colormap:         图像的颜色映射。可以是字符串表示的颜色映射名称,或是colormap函数。默认值为None,表示使用默认颜色映射。
#         blending:         图像的混合模式。可以是字符串表示的混合模式名称,例如"translucent"、"additive"等。默认值为None,表示使用默认混合模式。
#         interpolation:    图像的插值方法。可以是字符串表示的插值方法名称,例如"nearest"、"bilinear"、"bicubic"等。默认值为None,表示使用默认插值方法。
#         gamma:            图像的gamma值,用于对图像进行伽马校正。默认值为None,表示不进行伽马校正。
#         is_pyramid:       布尔值,用于指示是否使用金字塔结构显示图像。默认值为None,表示不使用金字塔结构。
#         rgb:              布尔值,用于指示输入图像是否为RGB彩色图像。默认值为None,表示根据输入图像数据自动判断。
#         scale:            图像的缩放因子。可以是单个值,表示在所有轴上应用相同的缩放,也可以是每个轴的缩放因子列表。默认值为None,表示不进行缩放。
#         translate:        图像的平移量。可以是单个值,表示在所有轴上应用相同的平移,也可以是每个轴的平移量列表。默认值为None,表示不进行平移。
#         contrast_limits:  图像的对比度限制,用于控制图像显示的亮度范围。可以是单个值,表示在所有轴上应用相同的对比度限制,也可以是每个轴的对比度限制列表。默认值为None,表示不设置对比度限制。
#         rendering:        图像的渲染模式。可以是字符串表示的渲染模式名称,例如"mip"、"translucent"、"attenuated_mip"等。默认值为None,表示使用默认渲染模式。
#########################################################################################################
"""

5.2、添加图像层:viewer.add_image()

将单个或多个图像添加到napari查看器中,并提供了多个可选参数来自定义图像的显示。

Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

import napari
import tifffile

image_path = '561result-1-part.tif'
marked_image = tifffile.imread(image_path)

viewer = napari.Viewer()  # 创建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(),将避免程序阻塞问题(一直等待界面关闭)

"""
#########################################################################################################
# 函数功能:用于在 napari 视图中添加图像图层,允许您可视化图像数据。
# 函数说明: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)
# 输入参数:
#       - data:             必选参数,图像数据。通常是一个 NumPy 数组,表示图像的像素值。可以是 2D 图像、3D 图像或多通道图像,具体取决于您的数据。
#       - name:             可选参数,图像名称,将在napari查看器中显示。
##########################################
#         scale:            可选参数,图像的缩放因子。默认为 None,表示不进行缩放。
#         translate:        可选参数,图像的平移量。默认为 None,表示不进行平移。
#         rotate:           可选参数,图像的旋转角度。默认为 None,表示不进行旋转。
#         interpolation:    可选参数,图像的插值方法。用于在缩放或变换时平滑图像。
                                    默认为 'linear',表示线性插值。其他可能的值包括 'nearest'(最近邻插值)等。
##########################################
#         rgb:              可选参数,(布尔值)用于指示输入图像是否为RGB彩色图像。
#       - colormap:         可选参数,图像的颜色映射。默认为 'gray',表示灰度图。可以选择其他颜色映射,如 'viridis'、'cividis' 等。
#         colormap_range:   可选参数,颜色映射的范围。可以是字符串,例如"auto"或"full",表示自动计算颜色映射范围或使用完整范围。
##########################################
#         blending:         可选参数,图像的混合模式。即图像如何与其他图层叠加。
#                                   默认为 'translucent',表示半透明。其他可能的值包括 'opaque'(不透明)和 'additive'(叠加)等。
#         visible:          可选参数,图像是否可见。默认为 True,表示图像可见。
#         opacity:          可选参数,图像的不透明度。默认为1.0,表示完全不透明。
##########################################
#       - contrast_limits:  可选参数,调整图像的对比度,默认为 None,表示不进行对比度调整。
#                                   通常是一个包含两个值的元组,表示对比度的最小和最大值。例如 (0, 255),图像的像素值将线性映射到指定的范围内。
#       - gamma:            可选参数,调整图像的伽马校正。默认为 1.0,表示不进行伽马校正。
#                                   较低的值可以增加图像的亮度,较高的值可以增加图像的对比度。
##########################################
#       - rendering:        可选参数,图像的渲染方法。不同的渲染方法可以影响图像的可视化效果。
                    'mip'(默认值):     	最大强度渲染。	选择每个像素沿视线方向上的最大值来渲染图像。通常用于显示有深度信息的图像,如体绘图。
                    'minimum':			 	最小强度渲染。	选择每个像素沿视线方向上的最小值来渲染图像。通常用于查看图像中的最暗特征,如血管。
                    'attenuated_mip':   	衰减最大强度投影。根据深度进行衰减,距离视线近的像素比远处的像素更容易看到。适用于可视化深度信息的图像。                    
                    'translucent':      	半透明渲染。		根据像素的亮度来渲染图像,较暗的像素会显示为半透明。适用于需要突出细节的图像。
                    'translucent_no_depth':半透明但不考虑深度信息渲染。
                    'additive':         	多通道渲染。		将像素的亮度相加,而不是取最大值。适用于需要将多个图像叠加在一起的情况,如叠加多通道的彩色图像。
                    'iso':              	等值面渲染。		将图像中所有像素值相同的区域渲染为等值面,适用于可视化等值面数据的图像。
#########################################################################################################
"""

5.3、添加点云层:viewer.add_points() —— 获取点坐标

将点的坐标和可选的其他属性添加到napari查看器中,并提供了多个可选参数来自定义点云的显示。

点云数据:由离散点(x, y, z)坐标的集合组成。
Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python
Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

import napari

# (1)创建napari Viewer
viewer = napari.Viewer()  # 创建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]

"""
#########################################################################################################
# 函数功能:用于在 napari 视图中添加点图层,它允许您可视化点数据。
# 函数说明:viewer.add_points(data, *, name=None, face_color='white', edge_color='black', size=10, 
#                            symbol='o', edge_width=1, opacity=1.0, blending='translucent')
# 
# 输入参数:
#       - data:       点的坐标数据。用于指定点的位置坐标,可以接受不同维度的数据。
#                             对于 2D 数据,data 可以是一个形状为 (N, 2) 的数组,其中 N 表示点的数量,每行包含点的 X 和 Y 坐标。
#                             对于 3D 数据,data 可以是一个形状为 (N, 3) 的数组,其中每行包含点的 X、Y 和 Z 坐标。
#                             对于更高维度的数据,data 的形状会相应地增加,以包含更多的坐标信息。
#       - name:       图层的名称,用于标识图层。默认为 None。
#       - face_color: 点的填充颜色。默认为红色 ('red')。
#         edge_color: 点的边缘颜色。默认为红色 ('red')。
#       - size:       点的大小。默认为 10(单位:像素),表示点的直径。
#         symbol:     点的形状。默认为圆形点: 'o'
#                             's':表示方形点。      '+':表示十字形点。     'x':表示X形点。
#                             'd':表示菱形点。      '>':表示朝右箭头。     '<':表示朝左箭头。
#                             '^':表示朝上箭头。     'v':表示朝下箭头。     '1':表示下箭头。
#                             '2':表示上箭头。      '3':表示左箭头。      '4':表示右箭头。
#       - shading:    点的着色方式。用于控制渲染点图层时的着色方式。指定点的渲染方式,以改变点的外观。
#                             'flat':     默认值。使用平面着色,使点看起来像扁平的二维图标。这是最常见的着色方式,适用于大多数情况。
#                             'smooth':   使用平滑的渐变着色,使点看起来更加光滑和立体。这种着色方式可以让点看起来更加圆润,适用于需要强调点的立体感的情况。
#                             'spherical':使用球形着色,使点看起来像立体的球体。这种着色方式强调了点的立体感,尤其在 3D 空间中使用时效果明显。
#         edge_width: 点的边缘宽度。默认为 1(单位:像素)。
#         opacity:    点的不透明度。默认为 1.0,表示完全不透明。取值范围为 0(完全透明)到 1(完全不透明)之间。
#         blending:   点的混合模式,控制点的渲染方式。可以是 'translucent'(默认值,半透明)、'opaque'(不透明)和 'additive'(叠加)等。
#########################################################################################################
"""

5.4、添加形状层:viewer.add_shapes() —— 获取线条坐标(起点和终点)

  • napari会根据实际绘制线条的方向自动获取线条的起点和终点,而不是随机情况
  • 切换到n维显示模式(viewer.dims.ndisplay = 3)将导致无法选定线条绘制,但切换网格模式不会有影响。

注意:shapes层和image_data层是两个独立的层,故线的坐标映射到image_data需要进行高度和宽度限制。
Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python
Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

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)创建napari Viewer
viewer = napari.Viewer()  # 创建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(),将避免程序阻塞问题(一直等待界面关闭)

# (3)打印坐标
# image_shape = image_data.shape  # 获取图像的形状
line_layer = viewer.layers['Shapes']  # 获取绘制的线的图层
line_coordinates1 = []  # 获取绘制的所有线的坐标
line_coordinates2 = []  # 获取绘制的所有线的坐标:删除超出图像的线条
if line_layer.data:  # 检查图层数据是否存在
    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)

"""
#########################################################################################################
# 函数功能:用于在 napari 视图中添加形状图层,允许您可视化和编辑形状数据。
# 函数说明:viewer.add_shapes(data=None, shape_type='rectangle', edge_color='red', face_color='transparent',
#                           opacity=1.0, edge_width=1, blending='translucent', name=None)
# 输入参数:
#       - data:       包含形状数据的列表。
#                         (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: 形状的边框宽度,用于指定形状的边框线宽。默认为 1。
#         blending:   形状的混合模式,用于指定形状的绘制方式。默认为 'translucent',表示半透明。其他可能的值包括 'opaque'(不透明)和 'additive'(叠加)等。
#########################################################################################################
"""

六、扩展功能

6.1、在PyQt中,自定义组件,并添加到napari中,且完成数据交互

  • 备注:napari没有提供鼠标点击事件的接口。
  • 在napari中自定义组件与PyQt新建组件的方法相同,区别是需要将组件的主窗口添加到napari界面的控制面板中:self.viewer.window.add_dock_widget(widget, area='right') # 添加到napari的右侧,其中:widget是插件的主窗口。

Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python
Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python
Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

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)
        ##########################################################
        # 初始化参数
        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()  # 调用napari_gray_view方法来显示第一个切片

    def napari_gray_view(self):
        # (1)napari:创建视图、添加图层、显示视图
        self.viewer = napari.Viewer()  # 创建napari视图
        self.viewer.add_image(self.image_slices, name='image')  # 添加napari图层
	    # napari.run()  # 显示napari图形界面
	    # 备注:若不添加napari.run(),将避免程序阻塞问题(一直等待界面关闭)
        #########################################################################
        # (2)自定义组件
        #########################################################################
        # (2.1)创建滑动条
        self.slider = QSlider()  # 新建滑动条
        self.slider.setMinimum(0)  # 设置滑动条的最小值
        self.slider.setMaximum(np.max(self.image_slices))  # 设置滑动条的最大值
        self.slider.setValue(0)  # 设置滑动条的初始值
        # (2.2)创建标签
        self.slider_label = QLabel(str(self.slider.value()))
        # (2.3)复选框
        self.checkbox = QCheckBox("checkbox")  # 复选框
        self.slider.setEnabled(False)  # 复选框的初始状态:False
        self.input_box = QLineEdit()  # 新建输入框
        self.input_box.setEnabled(True)  # 复选框的初始状态:True
        self.input_label = QLabel("range: " + str(np.min(self.image_slices)) + "/" + str(np.max(self.image_slices)))  # 输入框标签

        # (3)创建布局并将滑动条和标签添加到布局中
        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)创建一个QWidget作为插件的主窗口
        widget = QWidget()
        widget.setLayout(layout)
        # (5)连接复选框的状态变化信号与槽函数
        self.checkbox.stateChanged.connect(self.onCheckboxStateChanged)
        self.slider.valueChanged.connect(self.napari_update_gray)  # 根据滑动条的值,显示第一个切片
        self.input_box.returnPressed.connect(self.napari_update_gray)  # 根据输入框的值,显示第一个切片

        # (6)将插件的主窗口添加到napari界面的控制面板中
        self.viewer.window.add_dock_widget(widget, area='right')  # 添加到napari的右侧
        #########################################################################
        # (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视图中的图层对象,并获取图像数据
        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()用于添加点云数据,但不能直接显示。需要先添加viewer.view_image(),然后再显示点云数据。

Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

import napari
import numpy as np

# (1)通过tifffile加载tif图像
marked_image = np.random.rand(10, 10, 10)  # 创建一个三维图像数据 (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()  # 创建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维显示模式(此时,系统会将两张图像融合在一起)
napari.run()  # 显示napari图形界面
# 备注:若不添加napari.run(),将避免程序阻塞问题(一直等待界面关闭)

6.2、在add_points中,保存点层的3D圆(napari不支持,自定义绘制)

Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python
Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

import numpy as np
import tifffile
import napari
from napari.layers import Points

# 创建一个新的Napari查看器
viewer = napari.Viewer()
####################################################################################
"""替换坐标即可完成点绘制"""
num_points = 50  # 随机生成50个3D坐标点
points = np.random.randint(0, 100, size=(num_points, 3))  # 在范围[0, 100)内生成随机坐标
####################################################################################
# 方法一:添加点层
point_layer = viewer.add_points(points, size=10, shading='spherical', edge_color='red', face_color='blue')

# 方法二:创建一个点层并添加坐标点
# point_layer = Points(points, size=10, shading='spherical', edge_color='red', face_color='blue')
# viewer.add_layer(point_layer)
####################################################################################
# 创建一个空白的3D图像,你需要指定图像的大小(shape)
image_shape = np.zeros((100, 100, 100), dtype=np.uint8)  # 例如,创建一个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不支持,自定义绘制)

Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

import napari
import cv2
import numpy as np

# 创建napari Viewer
viewer = napari.Viewer()

# 创建空白图像
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”)

Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

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()  # 创建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)

Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

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()  # 创建napari Viewer
viewer.add_image(SampleImage[500], name='SampleImage')  # 添加帧图像
viewer.add_image(lineImage[500], name='lineImage', colormap='green')  # 添加帧图像
""""添加图像:后一个会自动覆盖在前一个上,故需要注意顺序"""

viewer.dims.ndisplay = 3  # 切换到n维显示模式(此时,系统会将两张图像融合在一起)
napari.run()  # 显示napari图形界面

6.5、在add_image中,添加两张图像并自动切换网格模式(Toggle grid mode)

Python项目实战:基于napari的3D可视化(点云+slice),深度学习,3D可视化,napari,图像处理,可视化,python

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)

# 创建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')
# 切换网格模式
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 的值不会自动更新,可以使用回调函数来监听 viewer.dims.events 的变化。文章来源地址https://www.toymoban.com/news/detail-650639.html

import napari
import numpy as np

viewer = napari.Viewer()  # 创建 napari 视图
image_data = np.random.rand(10, 100, 100)  # 创建一个三维图像数据 (10 slices, 100x100 pixels)
image_layer = viewer.add_image(image_data, name='My Image')  # 添加图像图层

"""创建一个回调函数,获取更新的切片值"""
def update_current_slice(event):
    current_slice = viewer.dims.current_step[0]  # 获取当前 slice 值
    print("Current Slice Value:", current_slice)


# 监听 dims 的变化
viewer.dims.events.current_step.connect(update_current_slice)
napari.run()  # 运行 napari

6.7、在add_image中,获取图像层的参数contrast_limits + gamma

import napari
import numpy as np

viewer = napari.Viewer()  # 创建 napari 视图
image_data = np.random.rand(10, 100, 100)  # 创建一个三维图像数据 (10 slices, 100x100 pixels)
image_layer = viewer.add_image(image_data, name='Image', contrast_limits=None, gamma=1)  # 添加图像层
##############################################################################
"""
    对比度限制和伽马校正参数: 不会在图像图层的显示期间自动更新
"""
contrast_limits_value = image_layer.contrast_limits  # 获取图层的对比度限制参数
gamma_value = image_layer.gamma  # 获取图层的伽马校正参数
print("初始参数 =", contrast_limits_value, gamma_value)

napari.run()  # 运行 napari

contrast_limits_value2 = image_layer.contrast_limits
gamma_value2 = image_layer.gamma
print("参数1 =", contrast_limits_value2, gamma_value2)
##############################################################################
"""
    在图像层添加后再次运行 napari.run() 来重新启动 napari 查看器,那么之前的图像图层和参数将会被丢弃,因此 contrast_limits 和 gamma 的值会恢复为默认值。
        viewer = napari.Viewer()    # 创建 napari 视图
        viewer.layers.clear()       # 清空 napari 图层
        viewer.add_image()          # 添加 napari 图层
"""

viewer.layers.clear()  # 清空图层
image_data = np.random.rand(10, 100, 100)  # 创建一个三维图像数据 (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("参数2 =", contrast_limits_value2, gamma_value2)


到了这里,关于Python项目实战:基于napari的3D可视化(点云+slice)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 大数据可视化项目—基于Python豆瓣电影数据可视化分析系统的设计与实现

    本项目旨在通过对豆瓣电影数据进行综合分析与可视化展示,构建一个基于Python的大数据可视化系统。通过数据爬取收集、清洗、分析豆瓣电影数据,我们提供了一个全面的电影信息平台,为用户提供深入了解电影产业趋势、影片评价与演员表现的工具。项目的关键步骤包括

    2024年02月04日
    浏览(40)
  • Python项目开发:Flask基于Python的天气数据可视化平台

    目录 步骤一:数据获取 步骤二:设置Flask应用程序 步骤三:处理用户输入和数据可视化 步骤四:渲染HTML模板 总结 在这个数字化时代,数据可视化已经成为我们理解和解释信息的重要手段。在这个项目中,我们将使用Python语言来开发一个基于Flask框架的天气数据可视化平台

    2024年02月09日
    浏览(48)
  • 大数据毕设项目 - 基于大数据的抖音短视频数据分析与可视化 - python 大数据 可视化

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月01日
    浏览(38)
  • 大数据毕设项目 基于大数据的抖音短视频数据分析与可视化 - python 大数据 可视化

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月04日
    浏览(35)
  • 【项目实战】基于Hadoop大数据电商平台用户行为分析与可视化系统Hive、Spark计算机程序开发

    注意:该项目只展示部分功能,如需了解,评论区咨询即可。 在当今数字化时代,电商行业成为全球商业生态系统的关键组成部分,电商平台已经深入各行各业,影响了人们的购物方式和消费习惯。随着互联网技术的不断发展,电商平台产生了大量的用户数据,包括点击、购

    2024年02月04日
    浏览(92)
  • Python 3D可视化(一)

    本篇目录: 一、写在前面的话 二、简介 三、环境安装 四、python 3D实例集锦 (1)、圆柱体 (2)、箭头 (3)、球形 (4)、平面 (5)、线型 (6)、立方体 (7)、圆锥体 (8)、六边形 (9)、空心六边形 (10)、茶壶 (11)、兔子 (12)、飞机 五、总结   作者:北宋苏

    2023年04月12日
    浏览(44)
  • 基于Web的智慧交通3D可视化系统

    城市交通是城市社会活动、经济活动的纽带和动脉,智慧交通系统对城市经济发展和人民生活水平起着极其重要的作用。 随着我国城市化进程不断加快,现代城市交通问题日益受到人们的关注。特别是汽车数量的与日俱增,给城市带来了大量的污染,极大地影响了城市的发展

    2024年02月12日
    浏览(39)
  • python可视化——3D柱形图

       

    2024年02月06日
    浏览(35)
  • 【Python设计】基于Python Flask的全国气象数据采集及可视化系统-附下载方式以及项目参考论文,项目其他均为抄袭

    本项目是一个基于Web技术的实时气象数据可视化系统。通过爬取中国天气网的各个城市气象数据,并将其保存到自己的数据库中,我们利用Python、Flask、ECharts和MySQL等技术,实现了数据的分析和可视化呈现。这是一个采用B/S架构的现代化气象数据管理系统,用户只需通过浏览

    2024年02月11日
    浏览(44)
  • Three.js学习项目--3D抗美援朝数据可视化

    部分场景 体验地址 https://kmyc.hongbin.xyz/ 操作说明 视频 操作说明 我做了哪些(功能) draco解析glb模型 同时处理部分纹理请求 减轻一次加载纹理压力 手动控制轨道控制器镜头动画 多音频拼接 控制 封装动画播放器 控制进度切换 动画进度控制器 同步音频 模拟视频体验 useCon

    2024年02月11日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包