Search code examples
pythonmatplotlibspectral

Spectral (SPy) label legend


I would like to put a legend below the image drawn by the spectral module. I wonder if there is an builtin way to do this? I haven't found anything about making legends in the spectral API.

Here is an example

img = np.array([111, 112, 113, 121, 122, 123, 131, 132, 133, 
                211, 212, 213, 221, 222, 223, 231, 232, 233, 
                311, 312, 313, 321, 322, 323, 331, 332, 333]).reshape((3,3,3))
labels = np.array([0, 1, 1, 2, 2, 2, 3, 3, 3]).reshape((3,3))

I can draw img with labels this like this:

from spectral import imshow as spyShow
imageView = spyShow(data=img, bands=(0,1,2), classes=labels, fignum=1, interpolation='none')
imageView.set_display_mode('overlay')

enter image description here

Now I would like to place a legend below the image.

labelDictionary={0:'Unknown', 1:'Gravel', 2:'Aslphalt', 3:'Glass'}

From the source code I see that the label colors are taken from:

spectral.spy_colors

Further they are drawn with the following code:

import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap, NoNorm
cm = ListedColormap(np.array(spectral.spy_colors) / 255.)
plt.imshow(a, cmap=cm, vmin = 0, interpolation='none', norm=NoNorm())

I think I could extract those colors and map them to the labels and label names using a custom made function. Is this the correct way to make the legend, or is there a ready-made way, for the sake of not reinventing the wheel...


Solution

  • I added the legend like this:

    from matplotlib import patches
    from spectral import spy_colors
    labelPatches = [ patches.Patch(color=spy_colors[x]/255.,
                     label=labelDictionary[x]) for x in np.unique(labels) ]
    

    Once you have the label patches the legend is easy to add:

    plt.legend(handles=labelPatches, ncol=2, fontsize='medium', 
               loc='upper center', bbox_to_anchor=(0.5, -0.05));
    

    enter image description here