import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
__author__ = ['Giuseppe Filitto']
__email__ = ['giuseppe.filitto@studio.unibo.it']
[docs]def display(display_list, colormap=False, cmap='gist_heat', norm=True): # pragma: no cover
'''
Display a list of images: 'Input image', 'Ground-truth', 'Predicted'. It is possible to show the predicted image using a matplotlib cmap setting colormap as True.
Parameters
----------
display_list : list
list of input images: ground-truth and predicted image.
colormap : bool, optional
if True show the predicted image using a sequential colormap (i.e. matplotlib 'gist_heat'), by default False.
cmap: str
matplotlib cmap, by default 'gist_heat'.
norm: bool, optional
if normalized the predicted image values are in the range [0.-1.], by deafult True.
'''
plt.style.use('default')
plt.figure(figsize=(12, 8))
title = ['Input image', 'Ground-truth', 'Predicted']
for i, _ in enumerate(display_list):
plt.subplot(1, len(display_list), i + 1)
plt.title(title[i])
if i == 2 and colormap:
ax = plt.gca()
if norm:
im = ax.imshow((display_list[i]),
cmap=cmap, vmin=0.0, vmax=1.0)
else:
im = ax.imshow((display_list[i]),
cmap=cmap)
axins = inset_axes(ax, width="5%", height="100%", loc='lower left',
bbox_to_anchor=(1.02, 0., 1, 1), bbox_transform=ax.transAxes,
borderpad=0)
plt.colorbar(im, cax=axins)
else:
# optional: tf.keras.preprocessing.image.array_to_img, just to rescale from 0.-1. to 0-255
plt.imshow(tf.keras.preprocessing.image.array_to_img(
display_list[i]), cmap='gray')
plt.show()
[docs]def show_dataset(datagen, num=1): # pragma: no cover
'''
Show a given number 'num' of tuples of images created using datagenerator (i.e. create_segmentation_generator).
The first one is the input image, the second ine is the relative ground-truth.
Parameters
----------
datagen : iterator
DirectoryIterator yielding tuples of (x, y) images with shape (batch_size, height, width, channels) where x is the input image and y is the relative ground-truth image.
num : int, optional
number of (x, y) tuples to be shown, by default 1.
'''
plt.style.use('default')
for _ in range(0, num):
image, mask = next(datagen)
display([image[0], mask[0]])
[docs]def plot_history(model_name, history, metrics, loss, save=True, custom_metrics=True, custom_loss=False, **kwargs): # pragma: no cover
'''
Show the model history such as metrics and loss for both training and validation using 'seaborn' style.
Parameters
----------
model_name : str
name of the model. It is the suptitle of the plot.
history : Keras History object
result of model.fit(). It is a record of training loss values and metrics values at successive epochs, as well as validation loss values and validation metrics values.
metrics : list
List of metrics to be evaluated by the model during training and testing. Each of this must be a string (name of a built-in function) or custom function (see 'MRIsegm.metrics').
loss : string or a function
string of name of a built-in function (i.e. 'binary_crossentropy' from tf.keras.metrics) or a custom function (see 'MRIsegm.losses').
save : bool, optional
if saving the plot to the given path which must be given as path='path/to/plot', by default True.
custom_metrics : bool, optional
if 'True' consider metrics as a custom function (see 'MRIsegm.metrics'), by default True.
custom_loss : bool, optional
if 'True' consider loss as a custom function (see 'MRIsegm.losses'), by default False.
'''
plt.style.use('seaborn')
if kwargs.get('figsize'):
figsize = kwargs.get('figsize')
else:
figsize = (18, 7)
plt.figure(figsize=figsize)
plt.suptitle('Model: ' + model_name, fontsize=15)
if kwargs.get('labelsize'):
labelsize = kwargs.get('labelsize')
plt.rc('xtick', labelsize=labelsize)
plt.rc('ytick', labelsize=labelsize)
for i, _ in enumerate(metrics):
plt.subplot(1, len(metrics) + 1, i + 1)
if custom_metrics:
plt.plot(history.history['{}'.format(metrics[i].__name__)])
plt.plot(history.history['val_' + '{}'.format(metrics[i].__name__)])
plt.title('model {}'.format(metrics[i].__name__), fontsize=15)
plt.xlabel('epoch', fontsize=15)
plt.ylabel('{}'.format(metrics[i].__name__), fontsize=15)
plt.legend(['train', 'validation'], loc='best')
else:
plt.plot(history.history[metrics[i]])
plt.plot(history.history['val_' + metrics[i]])
plt.title('model ' + metrics[i], fontsize=15)
plt.xlabel('epoch', fontsize=15)
plt.ylabel(metrics[i], fontsize=15)
plt.legend(['train', 'validation'], loc='best')
if custom_loss:
plt.subplot(1, len(metrics) + 1, len(metrics) + 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model {}'.format(loss.__name__), fontsize=15)
plt.xlabel('epoch', fontsize=15)
plt.ylabel('{}'.format(loss.__name__), fontsize=15)
plt.legend(['train', 'validation'], loc='best')
else:
plt.subplot(1, len(metrics) + 1, len(metrics) + 1)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss', fontsize=15)
plt.xlabel('epoch', fontsize=15)
plt.ylabel(loss, fontsize=15)
plt.legend(['train', 'validation'], loc='best')
if save:
path = kwargs.get('path')
plt.savefig(path)
plt.show()
[docs]def show_prediction(datagen, model, num=1, colormap=True, cmap='gist_heat', norm=True): # pragma: no cover
'''
Show a given number 'num' of a series of image from datagenerator. The first of the series is the input image, the second one is ground-truth and the last one is the predicted image by the given model. The predicted image is shown using a sequential colormap.
Parameters
----------
datagen : iterator
DirectoryIterator yielding tuples of (x, y) with shape (batch_size, height, width, channels) where x is the input image and y is the ground-truth.
model : Keras Model class
model used to make the prediction.
num : int, optional
number of series to be shown, by default 1.
colormap : bool, optional
if True the prediction is shown using a sequential colormap (i.e. matplotlib 'gist_heat'), by default True.
cmap: str
matplotlib cmap, by default 'gist_heat'.
norm: bool, optional
if normalized the predicted values are in the range [0.-1], by deafult True.
'''
plt.style.use('default')
for _ in range(0, num):
image, mask = next(datagen)
pred_mask = model.predict(image)
display([image[0], mask[0], pred_mask[0]], colormap, cmap, norm)
[docs]def display_predictions(display_list, keys, colormap=True, cmap='gist_heat', figsize=(25, 15)): # pragma: no cover
'''
Display the ground-truth image and the predicted images from a list using a matplotlib colormap (setting colormap as True).
Parameters
----------
display_list : list
list of input images: ground-truth and predicted mask.
keys : list
list of models' name used for generating the prediction.
colormap : bool, optional
if True the prediction is shown using a sequential colormap (i.e. matplotlib 'gist_heat'), by default True.
cmap : str, optional
matplotlib cmap, by default 'gist_heat'.
figsize : tuple, optional
figure size, by default (25, 15).
'''
plt.figure(figsize=figsize, constrained_layout=True)
title = ['ground-truth'] + keys
for i in range(len(display_list)):
plt.subplot(1, len(display_list), i + 1)
plt.title(title[i])
if i >= 1 and colormap:
ax = plt.gca()
im = ax.imshow((display_list[i]), cmap=cmap, vmin=0.0, vmax=1.0)
if i == len(display_list) - 1:
axins = inset_axes(ax, width="5%", height="100%", loc='lower left', bbox_to_anchor=(1.02, 0., 1, 1), bbox_transform=ax.transAxes, borderpad=0)
plt.colorbar(im, cax=axins)
else:
plt.imshow(tf.keras.preprocessing.image.array_to_img(display_list[i]), cmap='gray')
# optional: tf.keras.preprocessing.image.array_to_img, just to rescale from 0.-1. to 0-255
plt.show()
[docs]def show_multiple_predictions(datagen, keys, values, num=1, colormap=True, cmap='gist_heat', figsize=(25, 15)): # pragma: no cover
'''
Show a given number 'num' of predicted images by the given models from datagenerator. The first one is the ground-truth.Each predicted image is shown using a matplotlib sequential colormap.
Parameters
----------
datagen : iterator
DirectoryIterator yielding tuples of (x, y) with shape (batch_size, height, width, channels) where x is the input image and y is the ground-truth.
keys : list
list of models' name used for generating the predictions.
values : list
list of loaded models used for generating the predictions.
num : int, optional
number of series to be shown, by default 1.
colormap : bool, optional
if True the prediction is shown using a sequential colormap (i.e. matplotlib 'gist_heat'), by default True.
cmap : str, optional
matplotlib cmap, by default 'gist_heat'.
figsize : tuple, optional
figure size, by default (25, 15).
'''
for _ in range(0, num):
image, mask = next(datagen)
pred_masks = [model.predict(image) for model in values]
disp_list = [mask[0]] + [pred_masks[j][0] for j in range(len(pred_masks))]
display_predictions(disp_list, keys, colormap, cmap, figsize)
plt.show()
[docs]def display_overlap(display_list, keys, colormap=True, cmap='gist_heat', figsize=(25, 15)): # pragma: no cover
'''
Display the ground-truth image and the predicted images from a list using a matplotlib colormap (setting colormap as True), over the original images.
Parameters
----------
display_list : list
list of input images: ground-truth and predicted mask.
keys : list
list of models' name used for generating the prediction.
colormap : bool, optional
if True the predicted mask is shown using a sequential colormap (i.e. matplotlib 'gist_heat'), by default True.
cmap : str, optional
matplotlib cmap, by default 'gist_heat'.
figsize : tuple, optional
figure size, by default (25, 15).
'''
plt.figure(figsize=figsize, constrained_layout=True)
title = ['ground-truth'] + keys
for i in range(1, len(display_list)):
plt.subplot(1, len(display_list), i + 1)
plt.title(title[i - 1])
if i >= 2 and colormap:
ax = plt.gca()
im_0 = ax.imshow(display_list[0], cmap='gray', vmin=0.0, vmax=1.0)
display_list[i][display_list[i] <= 0.05] = np.nan
im = ax.imshow(display_list[i], cmap=cmap, vmin=0.0, vmax=1.0, alpha=0.75)
if i == len(display_list) - 1:
axins = inset_axes(ax, width="5%", height="100%", loc='lower left', bbox_to_anchor=(1.02, 0., 1, 1), bbox_transform=ax.transAxes, borderpad=0)
plt.colorbar(im, cax=axins)
else:
plt.imshow(tf.keras.preprocessing.image.array_to_img(display_list[i] + display_list[0]), cmap='gray')
# optional: tf.keras.preprocessing.image.array_to_img, just to rescale from 0.-1. to 0-255
plt.show()
[docs]def show_multiple_overlap(datagen, keys, values, num=1, colormap=True, cmap='gray', figsize=(25, 15)): # pragma: no cover
'''
Show a given number 'num' of predicted images by the given models from datagenerator, over the original images. The first one is the ground-truth. Each predicted image is shown using a matplotlib sequential colormap(setting colormap as 'True').
Parameters
----------
datagen : iterator
DirectoryIterator yielding tuples of (x, y) with shape (batch_size, height, width, channels) where x is the input image and y is the ground-truth.
keys : list
list of models' name used for generating the prediction.
values : list
list of loaded models used for generating the predictions.
num : int, optional
number of series to be shown, by default 1.
colormap : bool, optional
if True the prediction is shown using a sequential colormap, by default True.
cmap : str, optional
matplotlib cmap, by default 'gray'.
figsize : tuple, optional
figure size, by default (25, 15).
'''
for _ in range(0, num):
image, mask = next(datagen)
pred_masks = [model.predict(image) for model in values]
disp_list = [image[0]] + [mask[0]] + [pred_masks[j][0] for j in range(len(pred_masks))]
display_overlap(disp_list, keys, colormap, cmap, figsize)
plt.show()