如何在matplotlib mplot3D中显示3D阵列等值面的三维图?

时间:2011-05-17 11:27:38

标签: python matplotlib scipy visualization volume

我有一个三维的numpy数组。我想(在matplotlib中)显示这个数组的等值面的一个漂亮的3D图(或者更严格地说,显示通过在采样点之间插值定义的3D标量场的等值面)。

matplotlib的mplot3D部分提供了很好的3D绘图支持,但是(据我所知)它的API没有任何东西可以简单地采用标量值的3D数组并显示等值面。但是,它确实支持显示多边形集合,因此我可以实现行进立方体算法来生成这样的多边形。

看起来很可能已经在某处实现了一个友好的行进立方体并且我没有找到它,或者我错过了一些简单的方法。或者,我欢迎任何指向其他工具的指针,以便可视化从Python / numpy / scipy世界轻松使用的3D数组数据。

3 个答案:

答案 0 :(得分:39)

为了详细说明我上面的评论,matplotlib的3D绘图确实不适用于像isosurfaces这样复杂的东西。它旨在为真正简单的3D图形生成漂亮的,出版品质的矢量输出。它无法处理复杂的3D多边形,因此即使实现了行进立方体以创建等值面,也无法正确渲染它。

但是,你可以做的是使用mayavi(它mlab API比直接使用mayavi更方便),它使用VTK来处理和可视化多维数据

作为一个简单的例子(从mayavi画廊的一个例子中修改):

import numpy as np
from enthought.mayavi import mlab

x, y, z = np.ogrid[-10:10:20j, -10:10:20j, -10:10:20j]
s = np.sin(x*y*z)/(x*y*z)

src = mlab.pipeline.scalar_field(s)
mlab.pipeline.iso_surface(src, contours=[s.min()+0.1*s.ptp(), ], opacity=0.3)
mlab.pipeline.iso_surface(src, contours=[s.max()-0.1*s.ptp(), ],)

mlab.show()

enter image description here

答案 1 :(得分:19)

补充@DanHickstein的答案,您还可以使用trisurf可视化在行进立方体阶段获得的多边形。

import numpy as np
from numpy import sin, cos, pi
from skimage import measure
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


def fun(x, y, z):
    return cos(x) + cos(y) + cos(z)

x, y, z = pi*np.mgrid[-1:1:31j, -1:1:31j, -1:1:31j]
vol = fun(x, y, z)
verts, faces = measure.marching_cubes(vol, 0, spacing=(0.1, 0.1, 0.1))

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(verts[:, 0], verts[:,1], faces, verts[:, 2],
                cmap='Spectral', lw=1)
plt.show()

enter image description here

更新:2018年5月11日

如@DrBwts所述,现在marching_cubes返回4个值。以下代码有效。

import numpy as np
from numpy import sin, cos, pi
from skimage import measure
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D


def fun(x, y, z):
    return cos(x) + cos(y) + cos(z)

x, y, z = pi*np.mgrid[-1:1:31j, -1:1:31j, -1:1:31j]
vol = fun(x, y, z)
verts, faces, _, _ = measure.marching_cubes(vol, 0, spacing=(0.1, 0.1, 0.1))

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(verts[:, 0], verts[:,1], faces, verts[:, 2],
                cmap='Spectral', lw=1)
plt.show()

答案 2 :(得分:11)

如果你想将你的情节保存在matplotlib中(在我看来,比mayavi更容易产生出版品质的图像),那么你可以使用marching_cubes function implemented in skimage,然后使用

在matplotlib中绘制结果。
mpl_toolkits.mplot3d.art3d.Poly3DCollection

如上面的链接所示。 Matplotlib在渲染等值面方面做得非常好。这是我用一些真正的层析成像数据做的一个例子:

enter image description here