Python项目实战:基于matplotlib与mayavi的3D可视化(点云+等值面)

一、3D可视化常用方法

3D可视化是一种用于呈现三维数据的方法,它可以帮助我们更好地理解和分析复杂的空间结构和关系。在科学、工程、医学和其他领域,3D可视化常用于展示和研究体数据、空间模型、分子结构等。

以下是一些常见的用于3D可视化的工具和库:

  1. Matplotlib:Matplotlib 是一个常用的Python数据可视化库,其中的 mplot3d 模块提供了3D可视化功能,可以绘制三维图形和表面图。
  2. Mayavi:Mayavi 是一个基于VTK(Visualization Toolkit)的强大的3D科学数据可视化工具,它提供了丰富的功能和交互性,支持绘制体数据、曲面、等值面、轮廓线等。
  3. Plotly:Plotly 是一个交互式的数据可视化库,支持绘制各种类型的3D图形,包括散点图、线图、曲面图等,并提供了丰富的交互功能和布局选项。
  4. VTK(Visualization Toolkit):VTK 是一个强大的开源可视化库,提供了广泛的3D可视化算法和工具,可以用于构建复杂的可视化应用。
  5. ParaView:ParaView 是基于VTK的可视化软件,主要用于科学数据的可视化和分析,支持高效处理大规模数据,并提供了各种可视化技术和交互性。

二、三维图像在numpy、cv2、以及tifffile.imread中通道的区别

  • (1)NumPy:NumPy是一个强大的数值计算库,用于处理多维数组。在NumPy中,三维图像通常表示为形状为 (height, width, channels) 的数组。每个像素的通道值可以通过索引访问,例如 image[y, x, channel]。
  • (2)OpenCV (cv2):OpenCV是一个广泛使用的计算机视觉库,支持图像和视频处理。在OpenCV中,三维图像通常表示为形状为 (height, width, channels) 的NumPy数组。每个像素的通道值可以通过索引访问,例如 image[y, x, channel]。OpenCV还提供了许多图像处理和计算机视觉功能。
  • (3)tifffile.imread:tifffile是一个用于读取TIFF图像文件的库。在使用tifffile.imread加载三维图像时,它会返回一个形状为 (slices, height, width) 的NumPy数组,其中每个像素的值表示灰度强度。tifffile库通常用于处理多在这里插入代码片层的灰度图像。
    • height:表示图像的垂直维度,即行数或高度。
    • width:表示图像的水平维度,即列数或宽度。
    • channels:表示图像的通道数,对于彩色图像通常为3(红、绿、蓝),对于灰度图像通常为1。

三、项目实战

1、基于matplotlib的3D可视化

1.1、ax.plot_surface:绘制3D圆

在这里插入图片描述

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 创建一个空白的3D图像
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# 你的3D坐标点数据
points = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [8, 5, 3]])

# 为每个点绘制3D圆
for point in points:
    x, y, z = point
    radius = 0.5  # 圆的半径
    u = np.linspace(0, 2 * np.pi, 100)
    v = np.linspace(0, np.pi, 100)
    x_circle = radius * np.outer(np.cos(u), np.sin(v)) + x
    y_circle = radius * np.outer(np.sin(u), np.sin(v)) + y
    z_circle = radius * np.outer(np.ones(np.size(u)), np.cos(v)) + z

    # 绘制3D圆
    ax.plot_surface(x_circle, y_circle, z_circle, color='b', alpha=0.5)

# 设置坐标轴标签
ax.set_xlabel('X轴')
ax.set_ylabel('Y轴')
ax.set_zlabel('Z轴')

# 显示图像
plt.show()

1.2、np.meshgrid:绘制点云图(体素体)

200x200x200图像可视化:耗时问题比较严重,且任意视角的拖动都等需要等待较长时间。
在这里插入图片描述

import numpy as np
import matplotlib.pyplot as plt
import tifffile				# pip install tifffile

# 加载 TIFF 图像
image_data = tifffile.imread('marked_image.tif')

# 创建立体图像的坐标网格
x, y, z = np.meshgrid(np.arange(image_data.shape[1]+1), np.arange(image_data.shape[0]+1), np.arange(image_data.shape[2]+1))

# 创建 3D 图形对象
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# 绘制立体图像
ax.voxels(x, y, z, image_data, cmap='gray')

# 设置坐标轴标签
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

# 显示图像
plt.show()

2、基于mayavi的3D可视化

2.0、mayavi使用指南(鼠标)

(1)鼠标左键:xyz轴旋转;
(2)鼠标右键 / 滑动鼠标滚轮:缩放功能;
(3)按住鼠标滚轮不松并进行拖动:上下左右平移;

2.1、mlab.points3d()参数详解:用于绘制3D点云

mlab.points3d(x, y, z, scalars, color, colormap, scale_factor, scale_mode, mode, resolution, opacity, line_width, reset_zoom, reset_camera, name, **kwargs)
参数详解:

  • (1)x, y, z: 分别表示点云在x、y、z轴坐标。这些参数可以是一维数组,也可以是多维数组。
  • (2)value / scalars: 用于指定点云的标量值(例如像素值、温度等),这些值用于着色点云,value是scalars参数的别名。scalars参数可以是一维数组,长度与点云中的点数相同,也可以是与点云坐标数组相同的形状。
  • (3)scale_factor: 用于指定每个点云的大小
  • (4)mode: 用于指定绘制的点的类型,可选值(字符串类型)包括:
    • 默认是小球体
    • ‘none’: 不绘制任何点。
    • ‘2dvertex’: 绘制2D点,点的大小由scale_factor确定。
    • ‘2dcross’: 绘制2D十字形点,点的大小由scale_factor确定。
    • ‘2dcircle:’ 绘制2D圆形点,点的大小由scale_factor确定。
    • ‘3dvertex’: 绘制3D点,点的大小由scale_factor确定。
    • ‘3dcross’: 绘制3D十字形点,点的大小由scale_factor确定。
    • ‘3dcircle’: 绘制3D圆形点,点的大小由scale_factor确定。
    • 'cube': 绘制3D立方体点,点的大小由scale_factor确定。
  • (5)colormap: 用于指定着色的颜色映射表,可选值包括Mayavi中预定义的颜色映射表,例如’viridis’、‘plasma’、'coolwarm’等。也可以使用自定义的颜色映射表。
  • (6)vmin, vmax: 用于指定着色时的最小值和最大值,用于映射scalars参数的值到颜色映射表。
  • (7)figure: 指定绘制点云的Mayavi figure对象,如果未指定,则使用当前活动的figure。
  • (8)name: 用于指定点云的名称。
  • (9)reset_zoom: 是否在绘制点云时自动调整视图范围以适应整个点云。
  • (10)line_width: 用于指定绘制线条的宽度。
  • (11)opacity: 用于指定点云的不透明度,取值范围为0(完全透明)到1(完全不透明)。
  • (12)mask_points: 是否掩蔽点云,掩蔽后点云将不可见。
  • (13)mask_color: 用于指定掩蔽点云时的颜色。
  • (14)scale_mode: 用于指定缩放模式,可选值(字符串类型)包括:
    • ‘none’: 不缩放。
    • ‘scalar’: 根据scalars参数的值进行缩放。
    • ‘vector’: 根据向量值进行缩放。
  • (15)scale_factor: 用于指定缩放因子,用于调整点的大小。
  • (16)resolution: 用于指定点云的分辨率,即点的密度。
  • (17)其他参数:还可以使用其他参数来调整点云的样式,例如color参数指定点云的颜色,representation参数指定绘制点云的外观,mask_points参数用于掩蔽点云等。

2.1.1、mlab.points3d:绘制小球

在这里插入图片描述

import numpy as np
from mayavi import mlab

x, y, z, value = np.random.random((4, 40))	# 随机生成x,y,z坐标,以及小球的值
mlab.figure(bgcolor=(1, 1, 1))
mlab.points3d(x, y, z, value)		# mode默认是小球体
mlab.show()

2.1.2、mlab.points3d:绘制小立方体

在这里插入图片描述

import numpy as np
from mayavi import mlab

x, y, z, value = np.random.random((4, 40))
mlab.figure(bgcolor=(1, 1, 1))
mlab.points3d(x, y, z, value, mode='cube', scale_factor=1, colormap='binary')
mlab.show()

2.1.3、mlab.points3d:3D灰度/彩色图像的点云图(体素体)

threshold = 1在这里插入图片描述
threshold = 100
在这里插入图片描述

import numpy as np
from mayavi import mlab
import tifffile

# (1)加载3D图像(彩色图像: 10x10x10x3        灰度图像: 10x10x10)
color_image = tifffile.imread('marked_image.tif')
print(len(color_image.shape))

# (2)创建网格点
if len(color_image.shape) == 3:          # 灰度3D图像:10x10x10
    x, y, z = np.mgrid[0:color_image.shape[0], 0:color_image.shape[1], 0:color_image.shape[2]]
elif len(color_image.shape) == 4:        # 彩色3D图像:3x10x10x10
    color_image = np.moveaxis(color_image, -1, 0)    # 调整彩色3D图像的轴顺序与网格点的轴顺序一致
    x, y, z = np.mgrid[0:color_image.shape[1], 0:color_image.shape[2], 0:color_image.shape[3]]
    color_image = color_image[0]
    # Mayavi库的绘制函数通常期望三维数组作为输入,表示空间坐标和相应的数值。对于四维图像数据,您可以选择提取其中的一维作为绘制的数据,或者将四维数据转换为三维数据。
##########################################################################
# (3)显示彩色3D点云图像
fig = mlab.figure(bgcolor=(0, 0, 0), size=(800, 600))  # 新建画布,指定背景为黑色(默认灰色),并设置画布的初始大小
threshold = 1     # 去掉冗余信息(如:100),且可以加速计算
selected_x, selected_y, selected_z = np.where(color_image >= threshold)  # 将color_image中大于阈值的像素点的坐标提取出来,作为点云的坐标
colors = color_image[selected_x, selected_y, selected_z] / 255.0  # 根据像素值设置点云的颜色: 将像素值归一化到[0, 1]范围,作为颜色值
mlab.points3d(selected_x, selected_y, selected_z, colors, mode='cube', scale_factor=2)  # 绘制点云
##########################################################################
# (4)设置立方体8条边线:边线颜色、边线宽度
mlab.outline(color=(0, 0, 0), line_width=3.0)
mlab.axes(xlabel='X', ylabel='Y', zlabel='Z', figure=fig)  # 添加坐标轴标签
# (5)设置Mayavi场景的渲染参数(可以改变 Mayavi 场景的视角和观察者与场景的距离,从而获得所需的视觉效果。)
mlab.view(azimuth=0, elevation=90, distance='auto')
# (6)显示Mayavi场景
mlab.show()
##########################################################################
# mlab.view() 函数用于设置 Mayavi 场景的视角。
#       azimuth: 水平旋转角度,以度数表示。0 表示正对前方,正值表示向右旋转,负值表示向左旋转。
#       elevation: 垂直旋转角度,以度数表示。90 表示从正上方俯视,0 表示水平视角,-90 表示从正下方仰视。
#       distance: 观察者与场景的距离。'auto' 表示自动调整距离以适应场景。
##########################################################################

2.2、mlab.contour3d()参数详解:用于绘制3D等值面

mlab.contour3d(scalar_field, contours=10, transparent=False, colormap=None, vmin=None, vmax=None, opacity=1.0, figure=None, line_width=1.0, extent=None)

  • 输入参数:
  • (1)scalar_field: 三维数据数组,表示要绘制等值面的标量场。该数组的形状应为(N, M, L),其中N,M,L分别是X,Y,Z方向的数据点数
    该参数是mlab.contour3d()函数的唯一必需参数。
  • (2)contours: 可选参数,用于指定要绘制的等值面的数量或位置。可以是一个整数,表示要绘制的等值面数量,或者是一个一维数组,表示要绘制的具体等值面位置。默认值为10,表示绘制10个等值面。
  • (3)transparent: 可选参数,表示等值面是否透明。如果设置为True,则等值面将显示为透明。默认值为False,即不透明。
  • (4)colormap: 可选参数,用于指定等值面的颜色映射。可以是颜色名称字符串,如’red’,‘green’,'blue’等,也可以是一个RGB元组表示的颜色,如(1, 0, 0)表示红色。如果不指定该参数,则默认使用Mayavi的默认颜色映射。
  • (5)vmin和vmax: 可选参数,用于指定绘制等值面的数据范围。vmin表示数据的最小值,vmax表示数据的最大值。超出这个范围的数据将被截断或忽略。如果不指定这两个参数,则默认使用数据数组中的最小值和最大值。
  • (6)opacity: 可选参数,表示等值面的不透明度。取值范围为0到1,其中0表示完全透明,1表示完全不透明。默认值为1.0,即完全不透明。
  • (7)line_width: 可选参数,表示等值面的线宽。默认值为1.0。
  • (8)extent: 可选参数,用于指定等值面在X,Y,Z方向的显示范围。它是一个六元组(xmin, xmax, ymin, ymax, zmin, zmax),分别表示X,Y,Z方向上的最小和最大值。如果不指定该参数,则默认使用数据数组的形状作为显示范围。
  • 返回对象:返回mlab.pipeline.iso_surface对象,通过该对象可以对等值面进行进一步的操作和设置。

2.2.1、mlab.contour3d:3D灰度/彩色图像的等值面图(体素体)

在这里插入图片描述

import numpy as np
from mayavi import mlab
import tifffile

# (1)加载3D图像(彩色图像: 10x10x10x3        灰度图像: 10x10x10)
color_image = tifffile.imread('marked_image.tif')
print(len(color_image.shape))

# (2)创建网格点
if len(color_image.shape) == 3:          # 灰度3D图像:10x10x10
    x, y, z = np.mgrid[0:color_image.shape[0], 0:color_image.shape[1], 0:color_image.shape[2]]
elif len(color_image.shape) == 4:        # 彩色3D图像:3x10x10x10
    color_image = np.moveaxis(color_image, -1, 0)    # 调整彩色3D图像的轴顺序与网格点的轴顺序一致
    x, y, z = np.mgrid[0:color_image.shape[1], 0:color_image.shape[2], 0:color_image.shape[3]]
    color_image = color_image[0]
    # Mayavi库的绘制函数通常期望三维数组作为输入,表示空间坐标和相应的数值。对于四维图像数据,您可以选择提取其中的一维作为绘制的数据,或者将四维数据转换为三维数据。

# (4)显示彩色3D图像
fig = mlab.figure(bgcolor=(0, 0, 0), size=(800, 600))  # 新建画布,指定背景为黑色(默认灰色),并设置画布的初始大小。白色=(1,1,1)
mlab.contour3d(x, y, z, color_image)
##########################################################################

# (5)创建三维体素数据
volume = mlab.pipeline.volume(mlab.pipeline.scalar_field(color_image))
# (6)创建颜色映射,全黑体素置黑色,全白体素置白色
color_map = np.zeros((256, 4))
color_map[0] = (0, 0, 0, 0)  # 全黑体素的颜色为黑色
# color_map[255] = (1, 1, 1, 1)  # 全白体素的颜色为白色
# (7)设置体素数据的颜色映射
volume.module_manager.scalar_lut_manager.lut.table = color_map
##########################################################################

# (8)设置立方体8条边线:边线颜色、边线宽度
mlab.outline(color=(0, 0, 0), line_width=3.0)
mlab.axes(xlabel='X', ylabel='Y', zlabel='Z', figure=fig)  # 添加坐标轴标签
# (9)设置Mayavi场景的渲染参数(可以改变 Mayavi 场景的视角和观察者与场景的距离,从而获得所需的视觉效果。)
mlab.view(azimuth=0, elevation=90, distance='auto')
# (10)显示Mayavi场景
mlab.show()

##########################################################################
# mlab.view() 函数用于设置 Mayavi 场景的视角。
#       azimuth: 水平旋转角度,以度数表示。0 表示正对前方,正值表示向右旋转,负值表示向左旋转。
#       elevation: 垂直旋转角度,以度数表示。90 表示从正上方俯视,0 表示水平视角,-90 表示从正下方仰视。
#       distance: 观察者与场景的距离。'auto' 表示自动调整距离以适应场景。
##########################################################################

2.2.2、mlab.contour3d:3D灰度/彩色图像的等值面图(体素体)—— 在同一个视图中,选择指定像素值绘制指定颜色

在这里插入图片描述

import numpy as np
from mayavi import mlab
import tifffile

# (1)加载3D图像(彩色图像: 10x10x10x3        灰度图像: 10x10x10)
color_image = tifffile.imread('marked_image.tif')
print(len(color_image.shape))

# (2)创建网格点
if len(color_image.shape) == 3:          # 灰度3D图像:10x10x10
    x, y, z = np.mgrid[0:color_image.shape[0], 0:color_image.shape[1], 0:color_image.shape[2]]
elif len(color_image.shape) == 4:        # 彩色3D图像:3x10x10x10
    color_image = np.moveaxis(color_image, -1, 0)    # 调整彩色3D图像的轴顺序与网格点的轴顺序一致
    x, y, z = np.mgrid[0:color_image.shape[1], 0:color_image.shape[2], 0:color_image.shape[3]]
    color_image = color_image[0]
    # Mayavi库的绘制函数通常期望三维数组作为输入,表示空间坐标和相应的数值。对于四维图像数据,您可以选择提取其中的一维作为绘制的数据,或者将四维数据转换为三维数据。

# (3.0)新建画布,指定背景为黑色(默认灰色),并设置画布的初始大小。白色=(1,1,1)
fig = mlab.figure(bgcolor=(0, 0, 0), size=(800, 600))

##########################################################################
# (4.1)一次绘制:对原图进行彩色显示
# mlab.contour3d(x, y, z, color_image)
#####################################
# (4.2)二次绘制:对指定像素值,绘制指定颜色
threshold_value = 255  # 指定像素值
color_value = (1, 0, 0)  # 指定颜色(红色)
mlab.contour3d(color_image, contours=[threshold_value], color=color_value)
#####################################
# (4.3)二次绘制:对指定范围像素值,绘制指定颜色
min_value = 100  # 指定最小像素值
max_value = 250  # 指定最大像素值
color_value = (0.5, 0.5, 0.5)  # 指定颜色(红色)
# 绘制指定范围内的等值面,并设置颜色
volume = mlab.pipeline.volume(mlab.pipeline.scalar_field(color_image))
iso_surface = mlab.pipeline.iso_surface(volume, contours=[min_value, max_value], color=color_value)
iso_surface.actor.property.opacity = 1  # 设置等值面的透明度
##########################################################################
# (5)设置立方体8条边线:边线颜色、边线宽度
mlab.outline(color=(0, 0, 0), line_width=3.0)
mlab.axes(xlabel='X', ylabel='Y', zlabel='Z', figure=fig)  # 添加坐标轴标签
# (6)设置Mayavi场景的渲染参数(可以改变 Mayavi 场景的视角和观察者与场景的距离,从而获得所需的视觉效果。)
mlab.view(azimuth=0, elevation=90, distance='auto')
# (7)显示Mayavi场景
mlab.show()

##########################################################################
# mlab.view() 函数用于设置 Mayavi 场景的视角。
#       azimuth: 水平旋转角度,以度数表示。0 表示正对前方,正值表示向右旋转,负值表示向左旋转。
#       elevation: 垂直旋转角度,以度数表示。90 表示从正上方俯视,0 表示水平视角,-90 表示从正下方仰视。
#       distance: 观察者与场景的距离。'auto' 表示自动调整距离以适应场景。
##########################################################################

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖墩会武术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值