Define the tissue mask¶
When extracting the tile dataset from the WSI collection, we may want to consider only a portion of the tissue, rather than the whole slide. For example, a single WSI can include multiple individual slices of tissue, or we may have pathologist annotations with the regions of interest (ROIs) we need to consider.
In this tutorial, we will see how to define different tissue masks in order to refine the tile extraction procedure.
First, we need to load some modules and an example Slide; here we will consider the Kidney WSI available in the data module.
from histolab.slide import Slide
from histolab.data import ihc_kidney
import os
BASE_PATH = os.getcwd()
PROCESS_PATH = os.path.join(BASE_PATH, 'kidney', 'processed')
ihc_kidney_svs, ihc_kidney_path = ihc_kidney_svs()
ihc_kidney_slide = Slide(ihc_kidney_path, processed_path=PROCESS_PATH)
ihc_kidney_slide.thumbnail

From our Slide object we can now retrieve a binary mask considering specific regions of the tissue. Notice that available masks are defined in the masks module.
As a diagnostic check to visualize the mask, we can call the locate mask method on the Slide, which outlines the boundaries of the selected mask on the slide’s thumbnail.
TissueMask¶
If we want to account for all the tissue detected on the slide, the TissueMask is what we need:
from histolab.masks import TissueMask
all_tissue_mask = TissueMask()
ihc_kidney_slide.locate_mask(all_tissue_mask)

BiggestTissueBoxMask¶
The BiggestTissueBoxMask keeps only the largest connected component of the tissue, and returns the bounding box including that region:
from histolab.masks import BiggestTissueBoxMask
largest_area_mask = BiggestTissueBoxMask()
ihc_kidney_slide.locate_mask(largest_area_mask)

Use TissueMark or BiggestTissueBoxMask with a custom set of filters¶
It is also possible to supply a custom set of filters to the TissueMask
or BiggestTissueBoxMask
classes, in order to provide more flexibility and address specific analysis requirements.
For example, in order to extract the tile dataset from the WSI collection, we may want to consider only the tissue that is not covered by the pathologist annotations.
from histolab.data import breast_tissue_diagnostic_green_pen
from histolab.filters.image_filters import (
ApplyMaskImage,
GreenPenFilter,
Invert,
OtsuThreshold,
RgbToGrayscale,
)
from histolab.filters.morphological_filters import RemoveSmallHoles, RemoveSmallObjects
from histolab.masks import TissueMask
from histolab.slide import Slide
_, slide_path = breast_tissue_diagnostic_green_pen()
breast_slide = Slide(slide_path, "")
mask = TissueMask(
RgbToGrayscale(),
OtsuThreshold(),
ApplyMaskImage(breast_slide.thumbnail),
GreenPenFilter(),
RgbToGrayscale(),
Invert(),
OtsuThreshold(),
RemoveSmallHoles(),
RemoveSmallObjects(),
)
breast_slide.locate_mask(mask, scale_factor=64)

Custom Mask¶
It is also possible to define a custom binary mask by subclassing the BinaryMask object. For example, we can limit a rectangular region with upper-left coordinates (400, 280) and bottom-right coordinates (300, 320):
from histolab.masks import BinaryMask
from histolab.util import rectangle_to_mask
from histolab.types import CP
class MyCustomMask(BinaryMask):
def _mask(self, slide):
thumb = slide.thumbnail
my_mask = rectangle_to_mask(thumb.size, CP(400, 280, 300, 320))
return my_mask
custom_mask = MyCustomMask()
ihc_kidney_slide.locate_mask(custom_mask)

Tile extraction within the mask¶
We can finally pass our mask to the extract method of our Tiler object, and visualize the location of the extracted tiles:
from histolab.tiler import RandomTiler
rtiler = RandomTiler(
tile_size=(128, 128),
n_tiles=50,
level=0,
tissue_percent=90,
seed=0,
)
rtiler.extract(ihc_kidney_slide, all_tissue_mask)
rtiler.locate_tiles(
slide=ihc_kidney_slide,
extraction_mask=all_tissue_mask,
)

Note
The BiggestTissueBoxMask is considered as default binary mask.