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

tim*_*day 42 python visualization volume matplotlib scipy

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

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

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

Joe*_*ton 40

为了详细说明我上面的评论,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()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 完善!apt-get install mayavi2,运行你的代码...... Just Works.正是我在寻找什么.多年来我一直在想是否不应该以某种方式使用VTK; 这看起来像是从scipy世界进入它的好方法.OMG就像发现一个全新的星球...... (4认同)
  • 取消它,传递特定值的列表似乎在最新版本中完美运行,无论其价值如何。 (4认同)
  • 在 ubuntu 15.04 上,我添加了一点点修改你的如下:`from mayavi import mlab` (2认同)

nic*_*aro 20

补充@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()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

更新: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()
Run Code Online (Sandbox Code Playgroud)


Dan*_*ein 12

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

mpl_toolkits.mplot3d.art3d.Poly3DCollection
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述