Diff of /pathaia/patches/visu.py [000000] .. [7823dd]

Switch to unified view

a b/pathaia/patches/visu.py
1
# coding: utf8
2
"""Useful functions for visualizing patches in WSIs."""
3
4
import numpy
5
from skimage.morphology import binary_dilation, disk
6
import openslide
7
from typing import Sequence, Tuple, Optional
8
from ..util.types import NDByteImage, Patch, Coord
9
10
11
def preview_from_queries(
12
    slide: openslide.OpenSlide,
13
    queries: Sequence[Patch],
14
    min_res: int = 512,
15
    color: Tuple[int, int, int] = (255, 255, 0),
16
    thickness: int = 2,
17
    cell_size: int = 20,
18
    size_0: Optional[Coord] = None,
19
) -> NDByteImage:
20
    """
21
    Give thumbnail with patches displayed.
22
23
    Args:
24
        slide: openslide object
25
        queries: patch objects to preview from
26
        min_res: minimum size for the smallest side of the thumbnail (usually the width)
27
        color: rgb color for patch boundaries
28
        thickness: thickness of patch boundaries
29
        cell_size: size of a cell representing a patch in the grid
30
        psize: size of a patch at level 0
31
32
    Returns:
33
        Thumbnail image with patches displayed.
34
35
    """
36
    # get thumbnail first
37
    slide_size = Coord(slide.dimensions)
38
    if size_0 is None:
39
        size_0 = Coord(queries[0].size_0) if len(queries) != 0 else Coord(min_res)
40
    thickness = 2 * (thickness // 2) + 1
41
    res = slide_size / size_0 * (thickness + cell_size) + thickness
42
    thumb_w = max(min_res, res.x)
43
    thumb_h = max(min_res, res.y)
44
    image = slide.get_thumbnail((thumb_w, thumb_h))
45
    thumb_size = Coord(image.size)
46
    dsr_x = slide_size[0] / thumb_size[0]
47
    dsr_y = slide_size[1] / thumb_size[1]
48
    image = numpy.array(image)[:, :, 0:3]
49
    # get grid
50
    grid = numpy.zeros((thumb_size.y, thumb_size.x), numpy.uint8)
51
    for query in queries:
52
        # position in queries are absolute
53
        x, y = round(query.position[0] / dsr_x), round(query.position[1] / dsr_y)
54
        dx, dy = round(query.size_0[0] / dsr_x), round(query.size_0[1] / dsr_y)
55
        #? startx = numpy.clip(x, 0, thumb_size.x - 1)
56
        startx = min(x, thumb_size.x - 1)
57
        starty = min(y, thumb_size.y - 1)
58
        endx = min(x + dx, thumb_size.x - 1)
59
        endy = min(y + dy, thumb_size.y - 1)
60
        # horizontal segments
61
        grid[starty, startx:endx] = 1
62
        grid[endy - 1, startx:endx] = 1
63
        # vertical segments
64
        grid[starty:endy, startx] = 1
65
        grid[starty:endy, endx - 1] = 1
66
    d = disk(thickness//2)
67
    grid = binary_dilation(grid, d)
68
    image[grid] = color
69
    return image