VisPy 中体素的透明度

Transparency with voxels in VisPy

我正在尝试使用 python 和 VisPy 来显示 numpy 数组中的 3D 数据。我查阅了示例 here,它非常有用。我已经得到要显示的数据——但它看起来不像我想要的那样。

我的数据现在显示的方式我真的看不到每个体素。我可以看到形状的侧面,但老实说,它看起来就像一个挖空的立方体。 It looks like this。我认为这可能是由于许多值都是负数或大多数值相对较小且有一些较大的异常值。

无论哪种方式,我都希望能够单独设置值的透明度——例如,正值的透明度为 70%,而小于 -2 但大于 -5 的值仅为 30 % 透明和绿色阴影。我希望这能让我看到一个真实的 "volume" 而不是我现在所拥有的。

这是我现在所拥有的内容的一瞥,以防有人想看(注意,从我链接的示例 vispy 代码中大量复制和粘贴):

# Creating volume data (returns a 100x100x100 numpy array)
volume_data = func()

# Prepare canvas
canvas = scene.SceneCanvas(keys='interactive', size=(800, 600), show=True)

# Set up a viewbox to display the image with interactive pan/zoom
view = canvas.central_widget.add_view()

# Creating and assigning camera
camera = scene.cameras.ArcballCamera(parent=view.scene, fov=60)
view.camera = camera  

# Create the volume
volume = scene.visuals.Volume(volume_data, clim=(0, 1), parent=view.scene, 
threshold=0.225,emulate_texture=False)

volume.cmap = 'blues'

if __name__ == '__main__':
    print(__doc__)
    app.run()

也许您可以尝试标准化 (0., 1.) 之间的体积并定义具有多个透明度级别的颜色图。举个例子:

import numpy as np
from vispy import scene, app, io
from vispy.color import BaseColormap

class MultiLevels(BaseColormap):
    """Mix of green and red."""

    glsl_map = """
    vec4 translucent_fire(float t) {
        if (t > .5 && t < .6) {
            return vec4(1, 0., 0., .3);
        }
        else if (t >= .6) {
            return vec4(0, 1., 0., 1.);
        }
        else {
            return vec4(0., 0., 0., 0.);
        }
    }
    """

class Greens(BaseColormap):
    """Transparent green."""

    glsl_map = """
    vec4 translucent_fire(float t) {
        float alpha;
        if (t < .4) {
            alpha = 0.;
        }
        else if (t >= .4 && t < .5) {
            alpha = .1;
        }
        else {
            alpha = 1.;
        }
        return vec4(t, pow(t, 0.5), t*t, alpha);
    }
    """

# Creating volume data (returns a 100x100x100 numpy array)
volume_data = np.load(io.load_data_file('volume/stent.npz'))['arr_0'].astype(float)
volume_data /= volume_data.max()  # normalize the volume between (0., 1.)

# Prepare canvas
canvas = scene.SceneCanvas(keys='interactive', size=(800, 600), show=True)

# Set up a viewbox to display the image with interactive pan/zoom
view = canvas.central_widget.add_view()

# Creating and assigning camera
camera = scene.cameras.ArcballCamera(parent=view.scene, fov=60)
view.camera = camera

# Create the volume
method = 'translucent'  # 'mip'
volume = scene.visuals.Volume(volume_data, parent=view.scene, method=method)
volume.cmap = Greens()  # MultiLevels()

if __name__ == '__main__':
    app.run()