注意
转到结尾 下载完整示例代码。
3D 中的 2D 图像#
此示例演示如何在 3D 中绘制 2D 彩色编码图像(类似于 Axes.imshow
)作为平面。
Matplotlib 没有为此提供原生函数。下面我们通过依赖 Axes3D.plot_surface
来构建一个。为简便起见,与 Axes.imshow
有一些区别:此函数不会设置坐标轴的纵横比,因此像素不一定为正方形。此外,像素边缘位于整数处,而不是像素中心。此外,Axes.imshow
的许多可选参数未实现。
默认情况下,多次调用 imshow3d
使用独立的范数,因此具有不同的颜色尺度。如果你想要一个共同的颜色尺度,你需要事先构建一个合适的范数,并将其传递给所有 imshow3d
调用。
3D 绘图引擎的一个基本限制是,无法正确绘制相交的对象。一个对象总是绘制在另一个对象的后面。因此,多个图像平面可以很好地用在本示例中所示的背景中。但是,如果平面相交,则此方法不适合。
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import Normalize
def imshow3d(ax, array, value_direction='z', pos=0, norm=None, cmap=None):
"""
Display a 2D array as a color-coded 2D image embedded in 3d.
The image will be in a plane perpendicular to the coordinate axis *value_direction*.
Parameters
----------
ax : Axes3D
The 3D Axes to plot into.
array : 2D numpy array
The image values.
value_direction : {'x', 'y', 'z'}
The axis normal to the image plane.
pos : float
The numeric value on the *value_direction* axis at which the image plane is
located.
norm : `~matplotlib.colors.Normalize`, default: Normalize
The normalization method used to scale scalar data. See `imshow()`.
cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap`
The Colormap instance or registered colormap name used to map scalar data
to colors.
"""
if norm is None:
norm = Normalize()
colors = plt.get_cmap(cmap)(norm(array))
if value_direction == 'x':
nz, ny = array.shape
zi, yi = np.mgrid[0:nz + 1, 0:ny + 1]
xi = np.full_like(yi, pos)
elif value_direction == 'y':
nx, nz = array.shape
xi, zi = np.mgrid[0:nx + 1, 0:nz + 1]
yi = np.full_like(zi, pos)
elif value_direction == 'z':
ny, nx = array.shape
yi, xi = np.mgrid[0:ny + 1, 0:nx + 1]
zi = np.full_like(xi, pos)
else:
raise ValueError(f"Invalid value_direction: {value_direction!r}")
ax.plot_surface(xi, yi, zi, rstride=1, cstride=1, facecolors=colors, shade=False)
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.set(xlabel="x", ylabel="y", zlabel="z")
nx, ny, nz = 8, 10, 5
data_xy = np.arange(ny * nx).reshape(ny, nx) + 15 * np.random.random((ny, nx))
data_yz = np.arange(nz * ny).reshape(nz, ny) + 10 * np.random.random((nz, ny))
data_zx = np.arange(nx * nz).reshape(nx, nz) + 8 * np.random.random((nx, nz))
imshow3d(ax, data_xy)
imshow3d(ax, data_yz, value_direction='x', cmap='magma')
imshow3d(ax, data_zx, value_direction='y', pos=ny, cmap='plasma')
plt.show()