Matplotlib渲染所有内部体素(带有Alpha)

发布于 2021-01-29 14:09:40

我想在matplotlib中渲染一个卷。该体积是一个简单的7x7x7多维数据集,并且我希望能够看到所有内部体素(即使我知道它看起来像一团糟)。

在此处输入图片说明我已经能够渲染透明的体素,但是似乎从未绘制过表面上没有的任何体素。

该卷的每个7x7切片应如下所示:
在此处输入图片说明

我汇集了MWE

以下代码使用5x5的红色,绿色,蓝色,黄色和青色层创建5x5x5的体积。每层的Alpha设置为.5,因此整个过程应该是透明的。

然后,我将所有非表面体素的颜色更改为带有alpha 1的黑色,因此如果显示出来,我们应该能够在中心看到一个黑框。

单独渲染它会产生左侧的图形,但是如果我们从青色层中删除填充,我们可以看到黑框确实存在,只是没有显示它,因为即使那些遮盖了体素的遮盖物也被100%遮盖了alpha小于1。

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # NOQA

spatial_axes = [5, 5, 5]
filled = np.ones(spatial_axes, dtype=np.bool)

colors = np.empty(spatial_axes + [4], dtype=np.float32)
alpha = .5
colors[0] = [1, 0, 0, alpha]
colors[1] = [0, 1, 0, alpha]
colors[2] = [0, 0, 1, alpha]
colors[3] = [1, 1, 0, alpha]
colors[4] = [0, 1, 1, alpha]

# set all internal colors to black with alpha=1
colors[1:-1, 1:-1, 1:-1, 0:3] = 0
colors[1:-1, 1:-1, 1:-1, 3] = 1

fig = plt.figure()

ax = fig.add_subplot('111', projection='3d')
ax.voxels(filled, facecolors=colors, edgecolors='k')

fig = plt.figure()
ax = fig.add_subplot('111', projection='3d')
filled[-1] = False
ax.voxels(filled, facecolors=colors, edgecolors='k')

在此处输入图片说明

有什么办法渲染所有被遮挡的体素?

关注者
0
被浏览
541
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    要将以上我的评论变成答案:

    尽管存在一些小问题,但您仍可以在代码中插入pull请求的当前状态:

    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D, art3d  # NOQA
    from matplotlib.cbook import _backports
    from collections import defaultdict
    import types
    
    def voxels(self, *args, **kwargs):
    
        if len(args) >= 3:
            # underscores indicate position only
            def voxels(__x, __y, __z, filled, **kwargs):
                return (__x, __y, __z), filled, kwargs
        else:
            def voxels(filled, **kwargs):
                return None, filled, kwargs
    
        xyz, filled, kwargs = voxels(*args, **kwargs)
    
        # check dimensions
        if filled.ndim != 3:
            raise ValueError("Argument filled must be 3-dimensional")
        size = np.array(filled.shape, dtype=np.intp)
    
        # check xyz coordinates, which are one larger than the filled shape
        coord_shape = tuple(size + 1)
        if xyz is None:
            x, y, z = np.indices(coord_shape)
        else:
            x, y, z = (_backports.broadcast_to(c, coord_shape) for c in xyz)
    
        def _broadcast_color_arg(color, name):
            if np.ndim(color) in (0, 1):
                # single color, like "red" or [1, 0, 0]
                return _backports.broadcast_to(
                    color, filled.shape + np.shape(color))
            elif np.ndim(color) in (3, 4):
                # 3D array of strings, or 4D array with last axis rgb
                if np.shape(color)[:3] != filled.shape:
                    raise ValueError(
                        "When multidimensional, {} must match the shape of "
                        "filled".format(name))
                return color
            else:
                raise ValueError("Invalid {} argument".format(name))
    
        # intercept the facecolors, handling defaults and broacasting
        facecolors = kwargs.pop('facecolors', None)
        if facecolors is None:
            facecolors = self._get_patches_for_fill.get_next_color()
        facecolors = _broadcast_color_arg(facecolors, 'facecolors')
    
        # broadcast but no default on edgecolors
        edgecolors = kwargs.pop('edgecolors', None)
        edgecolors = _broadcast_color_arg(edgecolors, 'edgecolors')
    
        # include possibly occluded internal faces or not
        internal_faces = kwargs.pop('internal_faces', False)
    
        # always scale to the full array, even if the data is only in the center
        self.auto_scale_xyz(x, y, z)
    
        # points lying on corners of a square
        square = np.array([
            [0, 0, 0],
            [0, 1, 0],
            [1, 1, 0],
            [1, 0, 0]
        ], dtype=np.intp)
    
        voxel_faces = defaultdict(list)
    
        def permutation_matrices(n):
            """ Generator of cyclic permutation matices """
            mat = np.eye(n, dtype=np.intp)
            for i in range(n):
                yield mat
                mat = np.roll(mat, 1, axis=0)
    
        for permute in permutation_matrices(3):
            pc, qc, rc = permute.T.dot(size)
            pinds = np.arange(pc)
            qinds = np.arange(qc)
            rinds = np.arange(rc)
    
            square_rot = square.dot(permute.T)
    
            for p in pinds:
                for q in qinds:
                    p0 = permute.dot([p, q, 0])
                    i0 = tuple(p0)
                    if filled[i0]:
                        voxel_faces[i0].append(p0 + square_rot)
    
                    # draw middle faces
                    for r1, r2 in zip(rinds[:-1], rinds[1:]):
                        p1 = permute.dot([p, q, r1])
                        p2 = permute.dot([p, q, r2])
                        i1 = tuple(p1)
                        i2 = tuple(p2)
                        if filled[i1] and (internal_faces or not filled[i2]):
                            voxel_faces[i1].append(p2 + square_rot)
                        elif (internal_faces or not filled[i1]) and filled[i2]:
                            voxel_faces[i2].append(p2 + square_rot)
    
                    # draw upper faces
                    pk = permute.dot([p, q, rc-1])
                    pk2 = permute.dot([p, q, rc])
                    ik = tuple(pk)
                    if filled[ik]:
                        voxel_faces[ik].append(pk2 + square_rot)
    
        # iterate over the faces, and generate a Poly3DCollection for each voxel
        polygons = {}
        for coord, faces_inds in voxel_faces.items():
            # convert indices into 3D positions
            if xyz is None:
                faces = faces_inds
            else:
                faces = []
                for face_inds in faces_inds:
                    ind = face_inds[:, 0], face_inds[:, 1], face_inds[:, 2]
                    face = np.empty(face_inds.shape)
                    face[:, 0] = x[ind]
                    face[:, 1] = y[ind]
                    face[:, 2] = z[ind]
                    faces.append(face)
    
            poly = art3d.Poly3DCollection(faces,
                facecolors=facecolors[coord],
                edgecolors=edgecolors[coord],
                **kwargs
            )
            self.add_collection3d(poly)
            polygons[coord] = poly
    
        return polygons
    
    
    
    spatial_axes = [5, 5, 5]
    filled = np.ones(spatial_axes, dtype=np.bool)
    
    colors = np.empty(spatial_axes + [4], dtype=np.float32)
    alpha = .5
    colors[0] = [1, 0, 0, alpha]
    colors[1] = [0, 1, 0, alpha]
    colors[2] = [0, 0, 1, alpha]
    colors[3] = [1, 1, 0, alpha]
    colors[4] = [0, 1, 1, alpha]
    
    # set all internal colors to black with alpha=1
    colors[1:-1, 1:-1, 1:-1, 0:3] = 0
    colors[1:-1, 1:-1, 1:-1, 3] = 1
    
    fig = plt.figure()
    
    ax = fig.add_subplot('111', projection='3d')
    ax.voxels = types.MethodType(voxels, ax)
    ax.voxels(filled, facecolors=colors, edgecolors='k',internal_faces=True)
    
    fig = plt.figure()
    ax = fig.add_subplot('111', projection='3d')
    ax.voxels = types.MethodType(voxels, ax)
    filled[-1] = False
    ax.voxels(filled, facecolors=colors, edgecolors='k',internal_faces=True)
    
    plt.show()
    

    在此处输入图片说明



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看