OpenSlide Python

repository·main·Indexed 19 days ago

https://github.com/openslide/openslide-python

A Python interface to the OpenSlide C library for reading massive, multi-resolution whole-slide images used in digital pathology. It supports numerous formats including Aperio (.svs), Hamamatsu (.ndpi), Leica (.scn), and Zeiss (.czi), allowing users to read specific image regions at various zoom levels without loading the entire file into RAM. Features include metadata access, ICC color profile management, tile caching via OpenSlideCache, and a DeepZoomGenerator for web-based slide viewing.

Tokens
3.4K
Snippets
9
Records
15
Agent score
16%

What's inside openslide-python

  1. Overview of OpenSlide Python

    main

    OpenSlide Python is a Python interface to the OpenSlide C library. It is designed for reading whole-slide images (virtual slides) used in digital pathology. Because these images can be tens of gigabytes in size, OpenSlide provides a way to read specific amounts of image data at desired zoom levels (resolutions) without needing to uncompress the entire file into RAM.

    Supported formats include:

    • Aperio (.svs)
    • ARGOS (.avs)
    • DICOM (.dcm)
    • Hamamatsu (.ndpi, .vms, .vmu)
    • Huron (.tif)
    • Leica (.scn)
    • MIRAX (.mrxs)
    • Philips (.tiff)
    • Sakura (.svslide)
    • Trestle (.tif)
    • Ventana (.bif, .tif)
    • Zeiss (.czi)
    • Generic tiled TIFF (.tif)
  2. Install OpenSlide Python

    main

    OpenSlide Python is a wrapper around the OpenSlide C library. Because it depends on a C library, you must ensure the OpenSlide binaries are available on your system.

    Option 1: Using openslide-bin (Easiest)

    If you only need OpenSlide for Python, the simplest method is to install the openslide-bin package via pip, which includes the necessary binaries.

    pip install openslide-bin

    Option 2: Linux and macOS

    You can use system package managers (like Anaconda, DNF, Apt, or MacPorts) to install both the OpenSlide C library and the Python bindings.

    Warning: Do not mix package managers for the C library and the Python bindings (e.g., installing OpenSlide via MacPorts but openslide-python via Anaconda), as this causes library conflicts.

    Option 3: Windows

    1. Download the OpenSlide Windows binaries and extract them to a directory.
    2. Use os.add_dll_directory() to point Python to the bin folder of the extracted binaries before importing openslide.
  3. Configure OpenSlide binaries on Windows

    main

    On Windows, if you are using downloaded binaries instead of a package manager, you must explicitly add the path to the OpenSlide bin directory to the DLL search path using os.add_dll_directory() before importing the openslide module.

    # The path can also be read from a config file, etc.
    OPENSLIDE_PATH = r'c:\path\to\openslide-win64\bin'
    
    import os
    if hasattr(os, 'add_dll_directory'):
        # Windows
        with os.add_dll_directory(OPENSLIDE_PATH):
            import openslide
    else:
        import openslide
  4. Manage color profiles and ICC profiles

    main

    OpenSlide Python includes ICC color profiles in the Image.info['icc_profile'] dictionary of the returned PIL images whenever available.

    Saving images with profiles

    To preserve the color profile when saving to disk:

    image.save(filename, icc_profile=image.info.get('icc_profile'))

    Performing color conversions

    You can use PIL.ImageCms to transform images using the slide's profile. For efficiency, build a transform once and reuse it for multiple regions:

    from PIL import ImageCms
    
    # Build a transform from slide profile to sRGB
    to_profile = ImageCms.createProfile('sRGB')
    intent = ImageCms.getDefaultIntent(slide.color_profile)
    transform = ImageCms.buildTransform(
        slide.color_profile, to_profile, 'RGBA', 'RGBA', intent, 0
    )
    
    # Apply to region images
    for image in region_images:
        ImageCms.applyTransform(image, transform, True)
    from io import BytesIO
    from PIL import ImageCms
    
    # Example: Manual conversion
    fromProfile = ImageCms.getOpenProfile(BytesIO(image.info['icc_profile']))
    toProfile = ImageCms.createProfile('sRGB')
    intent = ImageCms.getDefaultIntent(fromProfile)
    ImageCms.profileToProfile(
        image, fromProfile, toProfile, intent, 'RGBA', True, 0
    )
  5. Deep Zoom example programs

    main

    The OpenSlide Python repository includes several example scripts for working with Deep Zoom:

    • deepzoom_server.py: A basic server for a single slide. It serves a web page with a zoomable slide viewer, slide properties, and associated images.
    • deepzoom_multiserver.py: A basic server for a directory tree of slides, providing an index page to link to various zoomable viewers.
    • deepzoom_tile.py: A program to generate and store a complete Deep Zoom directory tree for a slide, optionally including an HTML viewer.

    Note: deepzoom_tile.py is intended as an example. For production applications requiring Deep Zoom tree generation, consider using VIPS instead.

  6. Access slide metadata and properties

    main

    OpenSlide objects provide several attributes for slide metadata:

    • level_count: Number of levels (0 to level_count - 1).
    • dimensions: (width, height) tuple for level 0.
    • level_dimensions: A tuple of (width, height) tuples for every level.
    • level_downsamples: A tuple of downsample factors for each level.
    • properties: A mapping of property names to values. Use the constants in the openslide module to access standard properties (e.g., openslide.PROPERTY_NAME_VENDOR).
    • associated_images: A mapping of image names to RGBA PIL.Image.Image objects (e.g., labels or macro images).
  7. Wrap a Pillow Image with ImageSlide

    main

    If you have a standard PIL.Image.Image object but need it to behave like an OpenSlide object (providing an OpenSlide-compatible API), use ImageSlide.

    You can also use the helper function open_slide(filename) which automatically returns an OpenSlide object for whole-slide images or an ImageSlide object for other image types.

    import openslide
    from PIL import Image
    
    # Wrap an existing PIL image
    img = Image.open("regular_image.png")
    slide = openslide.ImageSlide(img)
    
    # Or use the helper to get the correct type automatically
    slide = openslide.open_slide("path/to/file")
  8. Use the OpenSlide class to open whole-slide images

    main

    The OpenSlide class is used to open whole-slide images. It supports context manager usage (the with statement) to ensure the object is closed automatically.

    Important: Latching Error Semantics If any operation on an OpenSlide object fails and raises an OpenSlideError, all subsequent operations on that same object (except for .close()) will also raise OpenSlideError.

    import openslide
    
    # Using as a context manager (recommended)
    with openslide.OpenSlide("path/to/slide.svs") as slide:
        # perform operations
        pass
    
    # Manual management
    slide = openslide.OpenSlide("path/to/slide.svs")
    # ... operations ...
    slide.close()
  9. Configure tile caching with OpenSlideCache

    main

    You can use OpenSlideCache to store recently decoded tiles in memory to improve performance. Attach a cache to an OpenSlide object using set_cache(cache).

    Note: This requires OpenSlide version 4.0.0 or newer.

    import openslide
    
    cache = openslide.OpenSlideCache(capacity=1024 * 1024 * 100) # 100MB
    slide = openslide.OpenSlide("slide.svs")
    slide.set_cache(cache)
  10. Read regions and thumbnails from an OpenSlide object

    main

    Once an OpenSlide object is opened, you can extract specific image data:

    • read_region(location, level, size): Returns an RGBA PIL.Image.Image of the specified region. location is a (x, y) tuple in the level 0 reference frame. size is a (width, height) tuple.
    • get_thumbnail(size): Returns an RGB PIL.Image.Image thumbnail of the slide with the specified maximum (width, height).
    • get_best_level_for_downsample(downsample): Returns the integer level index that best matches the requested downsample factor.
    import openslide
    
    with openslide.OpenSlide("slide.svs") as slide:
        # Read a 512x512 region at level 0 starting at (100, 100)
        region = slide.read_region((100, 100), 0, (512, 512))
        
        # Get a thumbnail
        thumbnail = slide.get_thumbnail((256, 256))
        
        # Find best level for a 4x downsample
        level = slide.get_best_level_for_downsample(4.0)
  11. Generate Deep Zoom tiles with DeepZoomGenerator

    main

    OpenSlide Python provides the openslide.deepzoom.DeepZoomGenerator class to generate individual Deep Zoom tiles from slide objects. This allows for displaying whole-slide images in web browsers without converting the entire slide to a Deep Zoom format beforehand.

    Class: DeepZoomGenerator

    Constructor: DeepZoomGenerator(osr: AbstractSlide, tile_size: int = 254, overlap: int = 1, limit_bounds: bool = False)

    • osr: The slide object (an OpenSlide, ImageSlide, or any AbstractSlide instance).
    • tile_size: The width and height of a single tile. For optimal viewer performance, tile_size + 2 * overlap should be a power of two.
    • overlap: The number of extra pixels added to each interior edge of a tile.
    • limit_bounds: If True, only the non-empty slide region is rendered.

    Key Attributes

    • level_count: Total number of Deep Zoom levels.
    • tile_count: Total number of Deep Zoom tiles in the image.
    • level_tiles: A tuple of (tiles_x, tiles_y) tuples for each level.
    • level_dimensions: A tuple of (pixels_x, pixels_y) tuples for each level.

    Key Methods

    • get_dzi(format: str) -> str: Returns the XML metadata string for the .dzi file. Supported formats: "png" or "jpeg".
    • get_tile(level: int, address: tuple[int, int]) -> PIL.Image.Image: Returns an RGB Pillow image for the specified tile at the given (column, row) address.
    • get_tile_coordinates(level: int, address: tuple[int, int]) -> tuple[tuple[int, int], int, tuple[int, int]]: Returns the arguments required for OpenSlide.read_region() to fetch the specified tile. Most applications should use get_tile instead.
    • get_tile_dimensions(level: int, address: tuple[int, int]) -> tuple[int, int]: Returns the (pixels_x, pixels_y) dimensions of the specified tile.
    from openslide import DeepZoomGenerator
    
    # Assuming 'slide' is an OpenSlide object
    generator = DeepZoomGenerator(slide, tile_size=254, overlap=1)
    
    # Get the DZI XML metadata
    dzi_xml = generator.get_dzi('png')
    
    # Get a specific tile as a PIL Image
    tile_image = generator.get_tile(level=0, address=(10, 5))
  12. Detect the format vendor of a file

    main

    Use OpenSlide.detect_format(filename) to return a string describing the format vendor of a specified file. If the file is not recognized, it returns None. This is useful for pre-checking compatibility before attempting to open a slide.

    import openslide
    
    vendor = openslide.OpenSlide.detect_format("path/to/slide.svs")
    if vendor:
        print(f"Format vendor: {vendor}")
    else:
        print("Unknown format")