File: instances.py

package info (click to toggle)
python-imgviz 1.2.4%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 9,268 kB
  • sloc: python: 3,032; makefile: 15
file content (160 lines) | stat: -rw-r--r-- 4,144 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import numpy as np

from . import draw as draw_module
from . import label as label_module


def mask_to_bbox(masks):
    bboxes = np.zeros((len(masks), 4), dtype=float)
    for i, mask in enumerate(masks):
        if mask.sum() == 0:
            continue
        where = np.argwhere(mask)
        (y1, x1), (y2, x2) = where.min(0), where.max(0) + 1
        bbox = y1, x1, y2, x2
        bboxes[i] = bbox
    return bboxes


def instances2rgb(
    image,
    labels,
    bboxes=None,
    masks=None,
    captions=None,
    font_size=25,
    line_width=5,
    boundary_width=1,
    alpha=0.7,
    colormap=None,
    font_path=None,
):
    """Convert instances to rgb.

    Parameters
    ----------
    image: numpy.ndarray, (H, W, 3), numpy.uint8
        RGB image.
    labels: list of int, (N,)
        Labels.
    bboxes: list of numpy.ndarray, (N, 4), float
        Bounding boxes.
    masks: numpy.ndarray, (N, H, W), bool
        Masks.
    captions: list of str
        Captions.
    font_size: int
        Font size.
    line_width: int
        Line width.
    alpha: float
        Alpha of RGB.
    colormap: numpy.ndarray, (M, 3), numpy.uint8
        Label id to RGB color.

    Returns
    -------
    dst: numpy.ndarray, (H, W, 3), numpy.uint8
        Visualized image.

    """
    assert isinstance(image, np.ndarray)
    assert image.dtype == np.uint8
    assert image.ndim == 3

    assert all(label_i >= 0 for label_i in labels)

    n_instance = len(labels)

    if masks is None:
        assert bboxes is not None
        masks = [None] * n_instance
    if bboxes is None:
        assert masks is not None
        bboxes = mask_to_bbox(masks)
    if captions is None:
        captions = [None] * n_instance

    assert len(masks) == len(bboxes) == len(captions) == n_instance

    if colormap is None:
        colormap = label_module.label_colormap()

    dst = image

    for instance_id in range(n_instance):
        mask = masks[instance_id]

        if mask is None or mask.sum() == 0:
            continue

        color_ins = colormap[1:][instance_id % len(colormap[1:])]

        maskviz = mask[:, :, None] * color_ins.astype(float)
        dst = dst.copy()
        dst[mask] = (1 - alpha) * image[mask].astype(float) + alpha * maskviz[
            mask
        ]

        try:
            import skimage.segmentation

            boundary = skimage.segmentation.find_boundaries(
                mask, connectivity=2
            )
            for _ in range(boundary_width - 1):
                boundary = skimage.morphology.binary_dilation(boundary)
            dst[boundary] = (200, 200, 200)
        except ImportError:
            pass

    for instance_id in range(n_instance):
        bbox = bboxes[instance_id]
        label = labels[instance_id]
        caption = captions[instance_id]

        color_cls = colormap[label % len(colormap)]

        y1, x1, y2, x2 = bbox
        if (y2 - y1) * (x2 - x1) == 0:
            continue

        aabb1 = np.array([y1, x1], dtype=int)
        aabb2 = np.array([y2, x2], dtype=int)
        dst = draw_module.rectangle(
            dst,
            aabb1,
            aabb2,
            outline=color_cls,
            width=line_width,
        )

        if caption is not None:
            for loc in ["lt+", "lt"]:
                y1, x1, y2, x2 = draw_module.text_in_rectangle_aabb(
                    src=dst,
                    loc=loc,
                    text=caption,
                    size=font_size,
                    aabb1=aabb1,
                    aabb2=aabb2,
                    font_path=font_path,
                )
                if (
                    y1 >= 0
                    and x1 >= 0
                    and y2 < dst.shape[0]
                    and x2 < dst.shape[1]
                ):
                    break
            dst = draw_module.text_in_rectangle(
                src=dst,
                loc=loc,
                text=caption,
                size=font_size,
                background=color_cls,
                aabb1=aabb1,
                aabb2=aabb2,
                font_path=font_path,
            )
    return dst