Skip to content

Visualizer

visualize_heatmap(image, heatmap, overlay=True, out_path=None, alpha=0.4) ¤

Simple wrapper function to visualize a heatmap encoded as NumPy matrix with a [0-1] range as image/volume via matplotlib.

Reference - Implementation

Author: François Chollet
Date: April 26, 2020
https://keras.io/examples/vision/grad_cam/

Parameters:

Name Type Description Default
image numpy.ndarray

NumPy matrix containing an image or volume.

required
heatmap numpy.ndarray

NumPy matrix containing a XAI heatmap.

required
out_path str

Path in which image is stored (else live output).

None
alpha float

Transparency value for heatmap overlap on image (range: [0-1]).

0.4
Source code in aucmedi/utils/visualizer.py
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def visualize_heatmap(image, heatmap, overlay=True, out_path=None, alpha=0.4):
    """ Simple wrapper function to visualize a heatmap encoded as NumPy matrix with a
        [0-1] range as image/volume via matplotlib.

    ??? abstract "Reference - Implementation"
        Author: François Chollet <br>
        Date: April 26, 2020 <br>
        https://keras.io/examples/vision/grad_cam/ <br>

    Args:
        image (numpy.ndarray):          NumPy matrix containing an image or volume.
        heatmap (numpy.ndarray):        NumPy matrix containing a XAI heatmap.
        out_path (str):                 Path in which image is stored (else live output).
        alpha (float):                  Transparency value for heatmap overlap on image (range: [0-1]).
    """
    # Grayscale normalization if required
    if image.shape[-1] == 1 and (np.min(image) < 0 or np.max(image) > 255):
        image = Standardize(mode="grayscale").transform(image)
    elif image.shape[-1] != 1 and (np.min(image) < 0 or np.max(image) > 255):
        raise ValueError("Visualizer does not support multi-channel " + \
                         "non-RGB formats." + \
                         " Array min: " + str(np.min(image)) + \
                         " Array max: " + str(np.max(image))) 
    # If image is grayscale, convert to RGB
    if image.shape[-1] == 1 : image = np.concatenate((image,)*3, axis=-1)
    # Rescale heatmap to grayscale range
    heatmap = np.uint8(heatmap * 255)
    # Overlay the heatmap on the image 
    if overlay:
        # Use jet colormap to colorize heatmap
        jet = cm.get_cmap("jet")
        # Use RGB values of the colormap
        jet_colors = jet(np.arange(256))[:,:3]
        jet_heatmap = jet_colors[heatmap] * 255
        # Superimpose the heatmap on original image
        final_img = jet_heatmap * alpha + (1-alpha) * image
    # Output just the heatmap
    else : final_img = heatmap
    # Apply corresponding 2D visualizer 
    if len(image.shape) == 3 : visualize_image(final_img, out_path=out_path)
    elif len(image.shape) == 4 : visualize_volume(final_img, out_path=out_path)

visualize_image(array, out_path=None) ¤

Simple wrapper function to visualize a NumPy matrix as image via PIL.

Info

NumPy array shape has to be (x, y, channel) like this: (224, 224, 3)

Parameters:

Name Type Description Default
array numpy.ndarray

NumPy matrix containing an image.

required
out_path str

Path in which image is stored (else live output).

None
Source code in aucmedi/utils/visualizer.py
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
def visualize_image(array, out_path=None):
    """ Simple wrapper function to visualize a NumPy matrix as image via PIL.

    ???+ info
        NumPy array shape has to be (x, y, channel) like this: (224, 224, 3)

    Args:
        array (numpy.ndarray):          NumPy matrix containing an image.
        out_path (str):                 Path in which image is stored (else live output).
    """
    # Ensure integer intensity values
    array = np.uint8(array)
    # Remove channel axis if grayscale
    if array.shape[-1] == 1 : array = np.reshape(array, array.shape[:-1])
    # Convert array to PIL image
    image = Image.fromarray(array)
    # Visualize or store image
    if out_path is None : image.show()
    else : image.save(out_path)

visualize_volume(array, out_path=None, iteration_axis=1) ¤

Simple wrapper function to visualize/store a NumPy matrix as volume.

Info

NumPy array shape has to be (x, y, z, channel) like this: (128, 128, 128, 1)

Parameters:

Name Type Description Default
array numpy.ndarray

NumPy matrix containing an image.

required
out_path str

Path in which volume is stored (else live output).

None
Source code in aucmedi/utils/visualizer.py
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
def visualize_volume(array, out_path=None, iteration_axis=1):
    """ Simple wrapper function to visualize/store a NumPy matrix as volume.

    ???+ info
        NumPy array shape has to be (x, y, z, channel) like this: (128, 128, 128, 1)

    Args:
        array (numpy.ndarray):          NumPy matrix containing an image.
        out_path (str):                 Path in which volume is stored (else live output).
    """
    # Identify output format
    if out_path is None : format = "gif"
    elif out_path.split(".")[-1].lower() in ["gif", "mha", "nii", "gz", "npy"]:
        format = out_path.split(".")[-1]
    else : raise ValueError("Visualizer does not support image format!")

    # Encode as GIF
    if format == "gif":
        # Grayscale normalization if required
        if array.shape[-1] == 1 and (np.min(array) < 0 or np.max(array) > 255):
            array = Standardize(mode="grayscale").transform(array)
        elif array.shape[-1] != 1 and (np.min(array) < 0 or np.max(array) > 255):
            raise ValueError("Visualizer does not support multi-channel " + \
                            "non-RGB formats." + \
                            " Array min: " + str(np.min(array)) + \
                            " Array max: " + str(np.max(array))) 
        # Ensure integer intensity values
        array = np.uint8(array)

        # Create a figure and two axes objects from matplot
        fig = plt.figure()
        img = plt.imshow(np.take(array, 0, axis=iteration_axis),
                        cmap='gray', vmin=0, vmax=255, animated=True)
        # Update function to show the slice for the current frame
        def update(i):
            plt.suptitle("Slice: " + str(i))
            img.set_data(np.take(array, i, axis=iteration_axis))
            return img
        # Compute the animation (gif)
        ani = animation.FuncAnimation(fig, update, 
                                    frames=array.shape[iteration_axis],
                                    interval=5, 
                                    repeat_delay=0, 
                                    blit=False)
        # Visualize or store gif
        if out_path is None : plt.show()
        else : ani.save(out_path, writer='imagemagick', fps=None, dpi=None)
        # Close the matplot
        plt.close()
    # Encode as NumPy file
    elif format == "npy" : np.save(out_path, array)
    # Encode as ITK file
    else:
        array_sitk = sitk.GetImageFromArray(array)
        sitk.WriteImage(array_sitk, out_path)