Source code for show

# -*- coding: utf-8 -*-

"""
Show images, such as thumbnails or regions extracted from whole-slide images
(WSI; also known as virtual slides).

"""

import numpy as np
from matplotlib import pyplot as plt
import matplotlib.patches as mpatch


[docs]class Figure(object): """An open *annotated* WSI. Parameters ---------- image: PIL Image Image to display; a thumbnail or region read from WSI. annotation: Numpy 2D array Annotation labels for each pixel in the input ``image``. color_map: dict {label int: RGB color list} Mapping of RGB color values to class labels. Colors are triplet lists of the R, G, and B values. Attributes ---------- image: PIL Image The input ``image``. annotation: Numpy 2D array The input ``annotation``. color_map: dict {label: color} Mapping between each label and the color for visualization. Examples -------- >>> from wsipre import show >>> colors = {0: (0, 0, 0), 2: (1, 0, 0)} >>> fig = show.Figure(image=image, annotation=mask, color_map=colors) >>> fig.color_map {0: (0, 0, 0), 2: (1, 0, 0)} >>> fig.show_label_colors(height=5) >>> fig.show_image_with_annotation() """ def __init__(self, image, annotation, color_map={0: (0., 0., 0.), 1: (0., .8, 1.), 2: (1., .8, 0.), 3: (1., .4, 0.)}): self.image = image self.annotation = annotation.astype(np.float32) # In case it's boolean self.color_map = color_map # RGBA values should be within 0-1 range if all([0 <= channel <= 255 for color in self.color_map.values() for channel in color]): if any([channel > 1 for color in self.color_map.values() for channel in color]): self.color_map = {key: [channel / 255.0 for channel in color] for (key, color) in self.color_map.items()} else: raise ValueError( 'Please make sure color triplets values in "color_map" are ' + 'either between 0-1 or 0-255 range.') # Are there enough colors? labels = np.unique(self.annotation) labels_not_in_map = [label not in color_map.keys() for label in labels] if any(labels_not_in_map): raise ValueError( 'No color provided in "color_map" for label(s) ' + f' {list(labels[labels_not_in_map])}.')
[docs] def show_label_colors(self, width=20, height=6, font_color='w', font_size=14): """Display a color bar with the colors and overlayed labels. Parameters ---------- width: int Width of each class rectangle in plot. height: int Height of each class rectangle in plot. font_size: int Size of the font used to display class labels. Returns ------- Matplotlib image illustrating mapping between class label and color. """ rectangles = [mpatch.Rectangle((0 + width * i, 0), width, height, color=list(self.color_map.values())[i]) for i in range(len(self.color_map.keys()))] rectangles = {list(self.color_map.keys())[i]: rect for i, rect in enumerate(rectangles)} fig, ax = plt.subplots() for r in rectangles: ax.add_artist(rectangles[r]) rx, ry = rectangles[r].get_xy() cx = rx + rectangles[r].get_width() / 2.0 cy = ry + rectangles[r].get_height() / 2.0 ax.annotate(r, (cx, cy), color=font_color, weight='bold', fontsize=font_size, ha='center', va='center') ax.set_xlim((0, width * len(rectangles))) ax.set_ylim((0, height)) ax.set_aspect('equal') ax.axis('off') plt.show()
[docs] def show_image(self): """Show loaded image. Display the loaded WSI thumbnail or region. Returns ------- Matplotlib image. """ plt.imshow(self.image) plt.show()
def _paint_annotation_mask(self): """Convert 2D mask to 3D format (RGB image).""" red = self.annotation.copy() green = self.annotation.copy() blue = self.annotation.copy() for label, color in self.color_map.items(): idx = self.annotation == label red[idx], green[idx], blue[idx] = color rgb = np.stack([red, green, blue], axis=2) return rgb
[docs] def show_annotation(self): """Show loaded image annotation. Display the loaded WSI thumbnail or region annotation, corresponding to a mask of pixel-wise labels. Returns ------- Matplotlib image. """ rgb_mask = self._paint_annotation_mask() plt.imshow(rgb_mask) plt.show()
[docs] def show_image_with_annotation(self, split=True): """Show loaded image and annotation. Parameters ---------- split: bool Whether to display the split image and annotation side-by-side or a combined visualization of the annotation on the image. Returns ------- Matplotlib image. """ if split: rgb_mask = self._paint_annotation_mask() f, (ax1, ax2) = plt.subplots(1, 2, sharey=True) ax1.imshow(np.array(self.image)) ax2.imshow(rgb_mask) plt.show() else: image = np.array(self.image)[:, :, :3] if np.max(image) > 1: image = image / 255. for label, color in self.color_map.items(): if label == 0: continue idx = self.annotation == label image[idx] = color plt.imshow(image) plt.show()