文章目录
一、3D可视化常用方法
3D可视化是一种用于呈现三维数据的方法,它可以帮助我们更好地理解和分析复杂的空间结构和关系。在科学、工程、医学和其他领域,3D可视化常用于展示和研究体数据、空间模型、分子结构等。
以下是一些常见的用于3D可视化的工具和库:
Matplotlib
:Matplotlib 是一个常用的Python数据可视化库,其中的 mplot3d 模块提供了3D可视化功能,可以绘制三维图形和表面图。Mayavi
:Mayavi 是一个基于VTK(Visualization Toolkit)的强大的3D科学数据可视化工具,它提供了丰富的功能和交互性,支持绘制体数据、曲面、等值面、轮廓线等。Plotly
:Plotly 是一个交互式的数据可视化库,支持绘制各种类型的3D图形,包括散点图、线图、曲面图等,并提供了丰富的交互功能和布局选项。VTK(Visualization Toolkit)
:VTK 是一个强大的开源可视化库,提供了广泛的3D可视化算法和工具,可以用于构建复杂的可视化应用。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' 表示自动调整距离以适应场景。
##########################################################################