Shortcuts

slideflow.slide.qc

This module contains functions for slide-level quality control, including Otsu’s thresholding and Gaussian blur filtering. Quality control methods are used by passing a list of callables to the qc argument of .extract_tiles(). They can also be directly applied to a slide with slideflow.WSI.qc().

import slideflow as sf
from slideflow.slide import qc

# Define custom QC options
qc = [
  qc.Otsu(),
  qc.Gaussian(sigma=2)
]

# Use this QC during tile extraction
P.extract_tiles(qc=qc)

# Alternatively, you can use the same QC directly on a WSI object
wsi = sf.WSI(...)
wsi.qc(qc).show()
class Otsu(slide_level: int | None = None)[source]

Prepare Otsu’s thresholding algorithm for filtering a slide.

This method is used to detect areas of tissue and remove background.

This QC method works by obtaining a thumbnail of a slide, and converting the image into the HSV color space. The HSV image undergoes a median blur using OpenCV with a kernel size of 7, and the image is thresholded using cv2.THRESH_OTSU. This results in a binary mask, which is then applied to the slide for filtering.

Original paper: https://ieeexplore.ieee.org/document/4310076

Warning

Otsu’s thresholding may give unexpected results with slides that have many large pen marks, erroneously identifying pen marks as tissue and removing the actual tissue as background. This behavior can be circumvented by applying a Gaussian filter before Otsu’s thresholding.

import slideflow as sf
from slideflow.slide import qc

wsi = sf.WSI(...)
gaussian = qc.GaussianV2()
otsu = qc.Otsu()
wsi.qc([gaussian, otsu])
Examples

Apply Otsu’s thresholding to a slide.

import slideflow as sf
from slideflow.slide import qc

wsi = sf.WSI(...)
otsu = qc.Otsu()
wsi.qc(otsu)
Parameters:

level (int) – Slide pyramid level at which to perform filtering. Defaults to second-lowest available level.

class Gaussian(mpp: float | None = None, sigma: int = 3, threshold: float = 0.02)[source]

Prepare Gaussian filtering algorithm for filtering a slide.

This method is used to remove out-of-focus areas and pen marks.

This QC method works by obtaining a thumbnail of a slide, and converting the image into grayspace. A gaussian filter with a given sigma (default=3) is calculated using scikit-image. Areas with blur below the given threshold (default=0.02) are filtered out.

Examples

Apply Gaussian filtering to a slide.

import slideflow as sf
from slideflow.slide import qc

wsi = sf.WSI(...)
gaussian = qc.Gaussian()
wsi.qc(gaussian)
Parameters:
  • mpp (float) – Microns-per-pixel at which to perform filtering. Defaults to 4 times the tile extraction MPP (e.g. for a tile_px/tile_um combination at 10X effective magnification, where tile_px=tile_um, the default blur_mpp would be 4, or effective magnification 2.5x).

  • sigma (int) – Sigma (radius) for Gaussian filter. Defaults to 3.

  • threshold (float) – Gaussian threshold. Defaults to 0.02.

class Save(dest: str | None = None)[source]

QC function which saves the mask to a numpy file.

When this QC method is applied to a slide, the current QC masks (e.g., as applied by the Otsu or Gaussian filtering methods) are saved to a numpy file. These saved masks can be loaded in the future using slideflow.slide.qc.Load. Saving/loading masks saves time by allowing to avoid regenerating masks repeatedly.

By default, masks are saved in the same folder as whole-slide images.

from slideflow.slide import qc

# Define a QC approach that auto-saves masks
qc = [
    qc.Otsu(),
    qc.Save()
]
P.extract_tiles(qc=qc)

...
# Auto-load previously saved masks
qc = [
    qc.Load()
]
P.extract_tiles(qc=qc)
Parameters:

dest (str, optional) – Path in which to save the qc mask. If None, will save in the same directory as the slide. Defaults to None.

class Load(source: str | None = None)[source]

QC function which loads a saved numpy mask.

Loads and applies a QC mask which was saved by slideflow.slide.qc.Save

Parameters:

source (str, optional) – Path to search for qc mask. If None, will search in the same directory as the slide. Defaults to None.

class StridedDL(model: Callable, pred_idx: int, tile_px: int, tile_um: str | int, *, buffer: int = 8, verbose: bool = False, pred_threshold: float = 0.5, **wsi_kwargs)[source]

QC function which uses a deep learning model to generate a QC mask.

When this QC method is applied to a slide, the given deep learning model generates predictions across the whole-slide image (using the class index specified by pred_idx). Areas with a prediction above pred_threshold are masked, to be discarded.

Examples

Create a DeepFocus module that filters out-of-focus tiles.

import slideflow as sf
from slideflow.slide.qc import strided_dl
from deepfocus import deepfocus_v3

deepfocus = strided_dl.StridedDL(
    model=deepfocus_v3(),
    pred_idx=1,
    tile_px=64,
    tile_um='40x'
)
wsi = sf.WSI(...)
wsi.qc(deepfocus)

Do the same, but using class inheritance.

import slideflow as sf
from slideflow.slide.qc import strided_dl
from deepfocus import deepfocus_v3

class DeepFocus(strided_dl.StridedDL):

    def __init__(self):
        model = deepfocus_v3()
        checkpoint = '/path/to/checkpoint-ver5'
        load_checkpoint(model, checkpoint)
        super().__init__(
            model=model,
            pred_idx=1,
            tile_px=64,
            tile_um='40x'
        )

wsi = sf.WSI(...)
deepfocus = DeepFocus()
wsi.qc(deepfocus)
Parameters:
  • model (callable) – Deep learning model.

  • pred_idx (int) – Index of the model output to interpret as the final prediction.

  • tile_px (int) – Tile size.

  • tile_um (str or float) – Tile size, in microns (int) or magnification (str).

Keyword Arguments:
  • verbose (bool) – Show a progress bar during calculation.

  • buffer (int) – Number of tiles (width and height) to extract and process simultaneously. Extracted tile size (width/height) will be tile_px * buffer. Defaults to 8.

  • grayspace_fraction (float) – Grayspace fraction when extracting tiles from slides. Defaults to 1 (disables).

  • pred_threshold (float) – Predictions below this value are masked.

  • kwargs (Any) – All remaining keyword arguments are passed to slideflow.WSI.build_generator().