可视化#

Tensorboard 可视化#

monai.visualize.img2tensorboard.add_animated_gif(writer, tag, image_tensor, max_out=3, frame_dim=-3, scale_factor=1.0, global_step=None)[source]#

使用 ‘CHWD’ 格式的图像张量创建动态 GIF,并使用 SummaryWriter 写入。

参数:
  • writer (UnionType[SummaryWriter, SummaryWriter]) – 用于写入的 Tensorboard SummaryWriter

  • tag (str) – 数据标识符

  • image_tensor (UnionType[ndarray, Tensor]) – 要添加的图像张量,期望格式为 CHWD

  • max_out (int) – 动画化时的最大图像通道数

  • frame_dim (int) – 用作 GIF 图像帧的维度,期望输入数据形状为 CHWD,默认为 -3(第一个空间维度)

  • scale_factor (float) – 数值乘数。如果图像数据在 0 到 1 之间,将其设为 255 可将其缩放至可显示范围

  • global_step (Optional[int, None]) – 要记录的全局步数

返回类型:

None

monai.visualize.img2tensorboard.make_animated_gif_summary(tag, image, writer=None, max_out=3, frame_dim=-3, scale_factor=1.0)[source]#

使用 ‘CHWD’ 格式的图像张量创建动态 GIF,并返回 Summary 对象。

参数:
  • tag (str) – 数据标识符

  • image (UnionType[ndarray, Tensor]) – 图像,期望格式为 CHWD

  • writer (Union[SummaryWriter, SummaryWriter, None]) – 用于绘制图像的 tensorboard 写入器

  • max_out (int) – 动画化时的最大图像通道数

  • frame_dim (int) – 用作 GIF 图像帧的维度,期望输入数据形状为 CHWD,默认为 -3(第一个空间维度)

  • scale_factor (float) – 数值乘数。如果图像数据在 0 到 1 之间,将其设为 255 可将其缩放至可显示范围

返回类型:

Summary

monai.visualize.img2tensorboard.plot_2d_or_3d_image(data, step, writer, index=0, max_channels=1, frame_dim=-3, max_frames=24, tag='output')[source]#

在 TensorBoard 上绘制 2D 或 3D 图像,3D 图像将被转换为 GIF 图像。

注意

将 3D 或 2D 图像(具有超过 3 个通道)绘制为独立图像。如果写入器来自 TensorBoardX 且数据有 3 个通道且 max_channels=3,将绘制为 RGB 视频。

参数:
  • data (Union[~NdarrayTensor, list[~NdarrayTensor]]) – 在 TensorBoard 上绘制为图像的目标数据。期望数据具有 ‘NCHW[D]’ 维度,或包含 CHW[D] 维度数据的列表,仅绘制批处理中的第一个。

  • step (int) – 图表中的当前步数。

  • writer (UnionType[SummaryWriter, SummaryWriter]) – 指定用于绘制图像的 TensorBoard 或 TensorBoardX SummaryWriter。

  • index (int) – 绘制输入数据批次中的哪个元素,默认为第一个元素。

  • max_channels (int) – 要绘制的通道数。

  • frame_dim (int) – 若将 3D 图像绘制为 GIF,指定用作帧的维度,期望输入数据形状为 NCHWD,默认为 -3(第一个空间维度)

  • max_frames (int) – 若在 TensorBoardX 中将 3D RGB 图像绘制为视频,将 FPS 设置为 max_frames

  • tag (str) – 在 TensorBoard 上绘制的图像标签。

返回类型:

None

类激活映射#

class monai.visualize.class_activation_maps.CAM(nn_module, target_layers, fc_layers='fc', upsampler=<function default_upsampler>, postprocessing=<function default_normalizer>)[source]#

从空间池化前的最后一个全连接层计算类激活映射。该实现基于

Zhou 等人,Learning Deep Features for Discriminative Localization. CVPR ‘16, https://arxiv.org/abs/1512.04150

示例

import torch

# densenet 2d
from monai.networks.nets import DenseNet121
from monai.visualize import CAM

model_2d = DenseNet121(spatial_dims=2, in_channels=1, out_channels=3)
cam = CAM(nn_module=model_2d, target_layers="class_layers.relu", fc_layers="class_layers.out")
result = cam(x=torch.rand((1, 1, 48, 64)))

# resnet 2d
from monai.networks.nets import seresnet50
from monai.visualize import CAM

model_2d = seresnet50(spatial_dims=2, in_channels=3, num_classes=4)
cam = CAM(nn_module=model_2d, target_layers="layer4", fc_layers="last_linear")
result = cam(x=torch.rand((2, 3, 48, 64)))

注意:为了帮助选择目标层,列出所有层可能会很有用

for name, _ in model.named_modules(): print(name)
__init__(nn_module, target_layers, fc_layers='fc', upsampler=<function default_upsampler>, postprocessing=<function default_normalizer>)[source]#
参数:
  • nn_module (Module) – 要可视化的模型

  • target_layers (str) – 用于生成特征图的模型层名称。

  • fc_layers (UnionType[str, Callable]) – 一个字符串或可调用对象,用于获取全连接权重,以便从目标层(不进行池化)计算激活映射,并在每个空间位置进行评估。

  • upsampler (Callable) – 用于对输出图像进行上采样的方法。默认为 N 维线性(双线性、三线性等),具体取决于输入的空间维度数。

  • postprocessing (Callable) – 应用于上采样输出图像的可调用对象。默认是将最小值=1和最大值=0进行归一化(即最大的输入将变为 0,最小的输入将变为 1)。

compute_map(x, class_idx=None, layer_idx=-1, **kwargs)[source]#

计算输入张量 x 的实际特征图。

参数:
  • xnn_module 的输入。

  • class_idx – 要可视化的类索引。默认为 None(从 argmax 计算 class_idx

  • layer_idx – 如果存在多个目标层,则为目标层的索引。默认为 -1。

返回:

激活映射(未经过上采样/后处理的原始输出。)

class monai.visualize.class_activation_maps.GradCAM(nn_module, target_layers, upsampler=<function default_upsampler>, postprocessing=<function default_normalizer>, register_backward=True)[source]#

计算梯度加权类激活映射 (Grad-CAM)。该实现基于

Selvaraju 等人,Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization, https://arxiv.org/abs/1610.02391

示例

import torch

# densenet 2d
from monai.networks.nets import DenseNet121
from monai.visualize import GradCAM

model_2d = DenseNet121(spatial_dims=2, in_channels=1, out_channels=3)
cam = GradCAM(nn_module=model_2d, target_layers="class_layers.relu")
result = cam(x=torch.rand((1, 1, 48, 64)))

# resnet 2d
from monai.networks.nets import seresnet50
from monai.visualize import GradCAM

model_2d = seresnet50(spatial_dims=2, in_channels=3, num_classes=4)
cam = GradCAM(nn_module=model_2d, target_layers="layer4")
result = cam(x=torch.rand((2, 3, 48, 64)))

注意:为了帮助选择目标层,列出所有层可能会很有用

for name, _ in model.named_modules(): print(name)
compute_map(x, class_idx=None, retain_graph=False, layer_idx=-1, **kwargs)[source]#

计算输入张量 x 的实际特征图。

参数:
  • xnn_module 的输入。

  • class_idx – 要可视化的类索引。默认为 None(从 argmax 计算 class_idx

  • layer_idx – 如果存在多个目标层,则为目标层的索引。默认为 -1。

返回:

激活映射(未经过上采样/后处理的原始输出。)

class monai.visualize.class_activation_maps.GradCAMpp(nn_module, target_layers, upsampler=<function default_upsampler>, postprocessing=<function default_normalizer>, register_backward=True)[source]#

计算梯度加权类激活映射 (Grad-CAM++)。该实现基于

Chattopadhyay 等人,Grad-CAM++: Improved Visual Explanations for Deep Convolutional Networks, https://arxiv.org/abs/1710.11063

compute_map(x, class_idx=None, retain_graph=False, layer_idx=-1, **kwargs)[source]#

计算输入张量 x 的实际特征图。

参数:
  • xnn_module 的输入。

  • class_idx – 要可视化的类索引。默认为 None(从 argmax 计算 class_idx

  • layer_idx – 如果存在多个目标层,则为目标层的索引。默认为 -1。

返回:

激活映射(未经过上采样/后处理的原始输出。)

class monai.visualize.class_activation_maps.ModelWithHooks(nn_module, target_layer_names, register_forward=False, register_backward=False)[source]#

一个模型包装器,用于运行模型的前向/反向步骤并存储中间特征/梯度信息。

__init__(nn_module, target_layer_names, register_forward=False, register_backward=False)[source]#
参数:
  • nn_module (Module) – 要包装的模型。

  • target_layer_names (UnionType[str, Sequence[str]]) – 要缓存的层名称。

  • register_forward (bool) – 是否缓存与 target_layer_names 对应的前向传播输出。

  • register_backward (bool) – 是否缓存与 target_layer_names 对应的反向传播输出。

get_layer(layer_id)[source]#
参数:

layer_id (UnionType[str, Callable[Module, Module]]) – 层名称字符串或可调用对象。如果它是可调用对象(例如 lambda m: m.fc),该方法将返回模块 self.model.fc

返回类型:

Module

返回:

来自 self.model 的子模块。

monai.visualize.class_activation_maps.default_normalizer(x)[source]#

通过将 (min, max) 映射到 (1, 0) 进行线性强度缩放。如果输入数据是 PyTorch 张量,则输出数据将是同一设备上的张量,否则输出数据将是 numpy 数组。

注意:这将翻转量级(即最小值将变为最大值,反之亦然)。

返回类型:

~NdarrayTensor

遮挡敏感度#

class monai.visualize.occlusion_sensitivity.OcclusionSensitivity(nn_module, mask_size=16, n_batch=16, verbose=True, mode='gaussian', overlap=0.6, activate=True)[source]#

此类用于计算给定图像的模型预测的遮挡敏感度。遮挡敏感度是指随着图像的遮挡部分发生变化,给定预测的概率如何变化。这对于理解网络为何做出某些决策非常有用。

当图像的重要部分被遮挡时,正确分类图像的概率会降低。因此,更负的值意味着相应的遮挡体积在决策过程中更重要。

__call__ 方法将返回两个 torch.Tensor:遮挡图和最可能类别的图像。如果使用了边界框,两张图像都会被裁剪,但体素大小始终与输入保持一致。

遮挡图显示了当图像的相应部分被遮挡时的推断概率。因此,更负的值意味着该区域在决策过程中很重要。该图的形状将为 BCHW(D)N,其中 N 是网络要推断的类别数。因此,类别 i 的遮挡可以通过 map[...,i] 查看。

最可能的类别是当图像的相应部分被遮挡时可能类别的图像(等同于 occ_map.argmax(dim=-1))。

参见:R. R. Selvaraju 等人 Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization. https://doi.org/10.1109/ICCV.2017.74

示例

# densenet 2d
from monai.networks.nets import DenseNet121
from monai.visualize import OcclusionSensitivity
import torch

model_2d = DenseNet121(spatial_dims=2, in_channels=1, out_channels=3)
occ_sens = OcclusionSensitivity(nn_module=model_2d)
occ_map, most_probable_class = occ_sens(x=torch.rand((1, 1, 48, 64)), b_box=[2, 40, 1, 62])

# densenet 3d
from monai.networks.nets import DenseNet
from monai.visualize import OcclusionSensitivity

model_3d = DenseNet(spatial_dims=3, in_channels=1, out_channels=3, init_features=2, growth_rate=2, block_config=(6,))
occ_sens = OcclusionSensitivity(nn_module=model_3d, n_batch=10)
occ_map, most_probable_class = occ_sens(torch.rand(1, 1, 6, 6, 6), b_box=[1, 3, -1, -1, -1, -1])

另请参阅

  • monai.visualize.occlusion_sensitivity.OcclusionSensitivity。

__init__(nn_module, mask_size=16, n_batch=16, verbose=True, mode='gaussian', overlap=0.6, activate=True)[source]#

遮挡敏感度构造函数。

参数:
  • nn_module (Module) – 用于推断的分类模型

  • mask_size (UnionType[int, Sequence]) – 要遮挡的框的大小,以中心体素为中心。如果给定一个数字,则将其用于所有维度。如果给定一个序列,则分别将其用于每个维度。

  • n_batch (int) – 推断批次中的图像数量。

  • verbose (bool) – 使用进度条(如果 tqdm 可用)。

  • mode (UnionType[str, float, Callable]) –

    应使用什么替换遮挡区域?如果给定一个浮点数,该值将在整个遮挡过程中使用。否则,可以提供 gaussianmean_imgmean_patch

    • gaussian:遮挡区域乘以 1 - 高斯核。通过这种方式,遮挡在中心处为 0,向边缘处保持不变,并在两者之间平滑变化。当使用高斯遮挡时,将使用加权平均值来组合重叠区域。这将在使用高斯(而不是 1-高斯)时完成,因为遮挡区域的权重更高。

    • mean_patch:遮挡区域将被替换为该遮挡区域的平均值。

    • mean_img:遮挡区域将被替换为整张图像的平均值。

  • overlap (float) – 推断区域之间的重叠。应在范围 0<=x<1 内。

  • activate (UnionType[bool, Callable]) – 如果 True,若 num_channels > 1 则进行 softmax 激活,否则进行 sigmoid 激活。如果 False,则不进行任何激活。如果为 callable,则对推断输出使用可调用对象。

static constant_occlusion(x, val, mask_size)[source]#

用恒定值进行遮挡。乘法遮挡为零,加法遮挡为恒定值。

返回类型:

tuple[float, Tensor]

static crop_meshgrid(grid, b_box, mask_size)[source]#

裁剪网格,以便我们仅对图像的子部分执行遮挡敏感度分析。

返回类型:

tuple[MetaTensor, SpatialCrop, Sequence]

static gaussian_occlusion(x, mask_size, sigma=0.25)[source]#

对于高斯遮挡,乘法遮挡为 1-高斯,加法遮挡为零。经验表明,0.25 的默认 sigma 值可以提供合理的内核,详情请见:Project-MONAI/MONAI#5230

返回类型:

tuple[Tensor, float]

static predictor(cropped_grid, nn_module, x, mul, add, mask_size, occ_mode, activate, module_kwargs)[source]#

传递给滑动窗口推断器的预测函数。采用裁剪后的网格,引用输入图像中的坐标。我们结合 mask_size 使用左上角的索引来确定图像的哪个区域被遮挡。遮挡是在原始图像 x 上执行的,使用 cropped_region * mul + addmuladd 有时是预先计算的(例如恒定的高斯模糊),有时是动态计算的(例如遮挡补丁的平均值)。因此提供了 occ_mode。最后,activate 用于在每次调用模型后进行激活。

参数:
  • cropped_grid (Tensor) – 网格的子部分,每个体素引用输入图像的坐标。网格由 OcclusionSensitivity 类创建,子集的生成由 sliding_window_inference 决定。

  • nn_module (Module) – 在数据上调用的模块。

  • x (Tensor) – 最初传递给 OcclusionSensitivity.__call__ 的图像。

  • mul (UnionType[Tensor, float]) – 遮挡区域将乘以该值。可以是 torch.Tensorfloat

  • add (UnionType[Tensor, float]) – 乘法后,将其添加到遮挡区域。可以是 torch.Tensorfloat

  • mask_size (Sequence) – 要遮挡的框的大小,以中心体素为中心。应为一个序列,每个空间维度一个值。

  • occ_mode (str) – 可能用于动态计算 muladd

  • activate (UnionType[bool, Callable]) – 如果 True,若 num_channels > 1 则进行 softmax 激活,否则进行 sigmoid 激活。如果 False,则不进行任何激活。如果为 callable,则对推断输出使用可调用对象。

  • module_kwargs (Mapping[str, Any]) – 推断时要传递给模块的关键字参数

返回类型:

Tensor

基于梯度的显著性图#
class monai.visualize.gradient_based.GuidedBackpropGrad(model)[source]#

基于 Springenberg 和 Dosovitskiy 等人的研究 https://arxiv.org/abs/1412.6806,通过反向传播正梯度和输入(参见 _AutoGradReLU)来计算基于梯度的显著性图。

另请参阅

class monai.visualize.gradient_based.GuidedBackpropSmoothGrad(model, stdev_spread=0.15, n_samples=25, magnitude=True, verbose=True)[source]#

基于 GuidedBackpropGradSmoothGrad 计算基于梯度的显著性图。

class monai.visualize.gradient_based.SmoothGrad(model, stdev_spread=0.15, n_samples=25, magnitude=True, verbose=True)[source]#

基于输入图像 xn_samples(高斯加性)噪声版本的平均灵敏度图。

另请参阅

class monai.visualize.gradient_based.VanillaGrad(model)[source]#

给定输入图像 x,调用此类将执行前向传播,然后将除一个(由 index 定义)之外的所有激活设置为零,并反向传播到图像以获得基于梯度的显著性图。

如果 index 为 None,将使用输出 logits 的 argmax。

另请参阅

工具#
monai.visualize.utils.blend_images(image, label, alpha=0.5, cmap='hsv', rescale_arrays=True, transparent_background=True)[source]#

混合图像和标签。两者都应具有形状 CHW[D]。图像可以有 C==1 或 3 个通道(灰度或 RGB)。标签期望有 C==1。

参数:
  • image (UnionType[ndarray, Tensor]) – 要与标签数据混合的输入图像。

  • label (UnionType[ndarray, Tensor]) – 要与图像数据混合的输入标签。

  • alpha (UnionType[float, ndarray, Tensor]) – 指定分配给标签的权重,0 表示完全透明,1 表示完全不透明。这可以作为单个值或与输入图像大小相同的数组/张量给出。

  • cmap (str) – 在 matplotlib 中指定色图,默认为 hsv,有关更多详细信息,请参阅:https://matplotlib.net.cn/2.0.2/users/colormaps.html

  • rescale_arrays (bool) – 是否先将数组缩放到 [0, 1],默认为 True

  • transparent_background (bool) – 如果为 true,标签字段中的任何零将不会被着色。

_images/blend_images.png
返回类型:

UnionType[ndarray, Tensor]

monai.visualize.utils.matshow3d(volume, fig=None, title=None, figsize=(10, 10), frames_per_row=None, frame_dim=-3, channel_dim=None, vmin=None, vmax=None, every_n=1, interpolation='none', show=False, fill_value=nan, margin=1, dtype=<class 'numpy.float32'>, **kwargs)[source]#

将 3D 体积图形创建为图像网格。

参数:
  • volume (UnionType[ndarray, Tensor]) – 要显示的 3D 体积。数据形状可以是 BCHWDCHWDHWD。更高维度的数组将被重塑为 (-1, H, W, [C]),C 取决于 channel_dim 参数。也可以传入一个通道优先 (C, H[, W, D]) 的数组列表,在这种情况下,它们将被显示为填充和堆叠的体积。

  • fig (Optional[Any, None]) – 要使用的 matplotlib 图形或坐标轴。如果为 None,将创建一个新图形。

  • title (Optional[str, None]) – 图形的标题。

  • figsize (tuple[int, int]) – 图形的大小。

  • frames_per_row (Optional[int, None]) – 每行显示的帧数。如果为 None,将使用 sqrt(firstdim)。

  • frame_dim (int) – 对于更高维度的数组,从 (-1, -2, -3) 中移至 -3 维度的哪个维度。维度和重塑为 (-1, H, W) 形状以构建帧,默认为 -3

  • channel_dim (Optional[int, None]) – 如果不为 None,明确指定要转置到最后一个维度的通道维度,形状为 (-1, H, W, C)。这可用于绘制 RGB 彩色图像。如果为 None,通道维度将与 frame_dimbatch_dim 一起平展,形状为 (-1, H, W)。注意它只能支持 3D 输入图像。默认为 None。

  • vmin (Optional[float, None]) – matplotlib imshowvmin

  • vmax (Optional[float, None]) – matplotlib imshowvmax

  • every_n (int) – 对帧进行子采样的因子,以便仅显示每第 n 帧。

  • interpolation (str) – 用于 matplotlib matshow 的插值方法。

  • show (bool) – 如果为 True,则显示该图形。

  • fill_value (Any) – 用于网格空白部分的填充值。

  • margin (int) – 用于网格的边距。

  • dtype (UnionType[dtype, type, str, None]) – 输出堆叠帧的数据类型。

  • kwargs (Any) – 传递给 matplotlib matshowimshow 的附加关键字参数。

示例

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from monai.visualize import matshow3d
# create a figure of a 3D volume
>>> volume = np.random.rand(10, 10, 10)
>>> fig = plt.figure()
>>> matshow3d(volume, fig=fig, title="3D Volume")
>>> plt.show()
# create a figure of a list of channel-first 3D volumes
>>> volumes = [np.random.rand(1, 10, 10, 10), np.random.rand(1, 10, 10, 10)]
>>> fig = plt.figure()
>>> matshow3d(volumes, fig=fig, title="List of Volumes")
>>> plt.show()
返回类型:

tuple[Any, ndarray]