Tissue masks are binary representations that identify tissue regions within whole slide images. They are essential for filtering out background, artifacts, and non-tissue areas during tile extraction. Histolab provides several mask classes to accommodate different tissue segmentation needs.
Purpose: Generic base class for creating custom binary masks.
from histolab.masks import BinaryMask
class CustomMask(BinaryMask):
def _mask(self, obj):
# Implement custom masking logic
# Return binary numpy array
pass
Use cases: - Custom tissue segmentation algorithms - Region-specific analysis (e.g., excluding annotations) - Integration with external segmentation models
Purpose: Segments all tissue regions in the slide using automated filters.
from histolab.masks import TissueMask
# Create tissue mask
tissue_mask = TissueMask()
# Apply to slide
mask_array = tissue_mask(slide)
How it works: 1. Converts image to grayscale 2. Applies Otsu thresholding to separate tissue from background 3. Performs binary dilation to connect nearby tissue regions 4. Removes small holes within tissue regions 5. Filters out small objects (artifacts)
Returns: Binary NumPy array where:
- True (or 1): Tissue pixels
- False (or 0): Background pixels
Best for: - Slides with multiple separate tissue sections - Comprehensive tissue analysis - When all tissue regions are important
Purpose: Identifies and returns the bounding box of the largest connected tissue region.
from histolab.masks import BiggestTissueBoxMask
# Create mask for largest tissue region
biggest_mask = BiggestTissueBoxMask()
# Apply to slide
mask_array = biggest_mask(slide)
How it works: 1. Applies same filtering pipeline as TissueMask 2. Identifies all connected tissue components 3. Selects the largest connected component 4. Returns bounding box encompassing that region
Best for: - Slides with a single primary tissue section - Excluding small artifacts or tissue fragments - Focusing on main tissue area (default for most tilers)
Masks accept custom filter chains for specialized tissue detection:
from histolab.masks import TissueMask
from histolab.filters.image_filters import RgbToGrayscale, OtsuThreshold
from histolab.filters.morphological_filters import BinaryDilation, RemoveSmallHoles
# Define custom filter composition
custom_mask = TissueMask(
filters=[
RgbToGrayscale(),
OtsuThreshold(),
BinaryDilation(disk_size=5),
RemoveSmallHoles(area_threshold=500)
]
)
from histolab.slide import Slide
from histolab.masks import TissueMask
slide = Slide("slide.svs", processed_path="output/")
mask = TissueMask()
# Visualize mask boundaries on thumbnail
slide.locate_mask(mask)
This displays the slide thumbnail with mask boundaries overlaid in a contrasting color.
import matplotlib.pyplot as plt
from histolab.masks import TissueMask
slide = Slide("slide.svs", processed_path="output/")
tissue_mask = TissueMask()
# Generate mask
mask_array = tissue_mask(slide)
# Plot side by side
fig, axes = plt.subplots(1, 2, figsize=(15, 7))
axes[0].imshow(slide.thumbnail)
axes[0].set_title("Original Slide")
axes[0].axis('off')
axes[1].imshow(mask_array, cmap='gray')
axes[1].set_title("Tissue Mask")
axes[1].axis('off')
plt.show()
Define specific regions of interest:
from histolab.masks import BinaryMask
import numpy as np
class RectangularMask(BinaryMask):
def __init__(self, x_start, y_start, width, height):
self.x_start = x_start
self.y_start = y_start
self.width = width
self.height = height
def _mask(self, obj):
# Create mask with specified rectangular region
thumb = obj.thumbnail
mask = np.zeros(thumb.shape[:2], dtype=bool)
mask[self.y_start:self.y_start+self.height,
self.x_start:self.x_start+self.width] = True
return mask
# Use custom mask
roi_mask = RectangularMask(x_start=1000, y_start=500, width=2000, height=1500)
Pathology slides often contain pen markings or digital annotations. Exclude them using custom masks:
from histolab.masks import TissueMask
from histolab.filters.image_filters import RgbToGrayscale, OtsuThreshold
from histolab.filters.morphological_filters import BinaryDilation
class AnnotationExclusionMask(BinaryMask):
def _mask(self, obj):
thumb = obj.thumbnail
# Convert to HSV to detect pen marks (often blue/green)
hsv = cv2.cvtColor(np.array(thumb), cv2.COLOR_RGB2HSV)
# Define color ranges for pen marks
lower_blue = np.array([100, 50, 50])
upper_blue = np.array([130, 255, 255])
# Create mask excluding pen marks
pen_mask = cv2.inRange(hsv, lower_blue, upper_blue)
# Apply standard tissue detection
tissue_mask = TissueMask()(obj)
# Combine: keep tissue, exclude pen marks
final_mask = tissue_mask & ~pen_mask.astype(bool)
return final_mask
Masks integrate seamlessly with tilers through the extraction_mask parameter:
from histolab.tiler import RandomTiler
from histolab.masks import TissueMask, BiggestTissueBoxMask
# Use TissueMask to extract from all tissue
random_tiler = RandomTiler(
tile_size=(512, 512),
n_tiles=100,
level=0,
extraction_mask=TissueMask() # Extract from all tissue regions
)
# Or use default BiggestTissueBoxMask
random_tiler = RandomTiler(
tile_size=(512, 512),
n_tiles=100,
level=0,
extraction_mask=BiggestTissueBoxMask() # Default behavior
)
locate_mask() or manual visualization to verify mask qualityTissueMask for multiple tissue sections, BiggestTissueBoxMask for single main sectionsTissueMask is more comprehensive but computationally intensive than BiggestTissueBoxMaskSolution: Adjust Otsu threshold or increase small object removal threshold
Solution: Reduce small object removal threshold or modify dilation parameters
Solution: Switch from BiggestTissueBoxMask to TissueMask
Solution: Implement custom annotation exclusion mask (see example above)