Skip to content

overlay

visualize.overlay

get_empty_layer

get_empty_layer(size: Tuple[int, int], color: Tuple[int, int, int] = (0, 0, 0), opacity: float = 0.0) -> Image

Create empty layer.

Parameters:

  • size (Tuple[int, int]) –

    (width, height) in pixels.

  • color (Tuple[int, int, int], default: (0, 0, 0) ) –

    Layer's base color (Background). Defaults to (0, 0, 0) (black).

  • opacity (float, default: 0.0 ) –

    Opacity value. Defaults to 0..

Returns:

  • Image

    Image.Image: Empty layer.

Source code in SaigeToolkit/visualize/util.py
def get_empty_layer(
    size: Tuple[int, int],
    color: Tuple[int, int, int] = (0, 0, 0),
    opacity: float = 0.0,
) -> Image.Image:
    """Create empty layer.

    Args:
        size (Tuple[int, int]): (width, height) in pixels.
        color (Tuple[int, int, int], optional): Layer's base color (Background).
            Defaults to (0, 0, 0) (black).
        opacity (float, optional): Opacity value. Defaults to 0..

    Returns:
        Image.Image: Empty layer.

    """
    return Image.new(mode="RGBA", size=size, color=(*color, int(opacity * 255)))

blend_layers

blend_layers(layers: List[Image]) -> Image

Blend multiple layers into one layer respect alpha channel.

Parameters:

  • layers (List[Image]) –

    Layers to blend. First element will place to bottom, and last one to top. If layer's mode is not 'RGBA', it will convert to 'RGBA' with opacity 1.0.

Returns:

  • Image

    Image.Image: Blended image.

Source code in SaigeToolkit/visualize/util.py
def blend_layers(
    layers: List[Image.Image],
) -> Image.Image:
    """Blend multiple layers into one layer respect alpha channel.

    Args:
        layers (List[Image.Image]): Layers to blend.
            First element will place to bottom, and last one to top.
            If layer's mode is not 'RGBA', it will convert to 'RGBA' with opacity 1.0.

    Returns:
        Image.Image: Blended image.

    """
    base_layer = get_empty_layer(layers[0].size)

    for layer in layers:
        if layer.mode != "RGBA":
            layer = layer.convert("RGBA")
        base_layer.paste(Image.alpha_composite(base_layer, layer))

    return base_layer

add_opacity_to_color_tuple

add_opacity_to_color_tuple(color: Optional[Tuple[int, int, int]] = None, opacity: float = 1.0) -> Optional[Tuple[int, int, int, int]]

Convert RGB color tuple to RGBA with specific opacity.

Parameters:

  • color (Tuple[int, int, int], default: None ) –

    Tuple of RGB color, each value has the range [0, 255]. Defaults to None.

  • opacity (float, default: 1.0 ) –

    Opacity value. Expected range is [0., 1.]. Defaults to 1..

Returns:

  • Optional[Tuple[int, int, int, int]]

    Tuple[int, int, int, int]: Converted RGBA color tuple.

Note

Since the PIL can handle outliers, this function does not separately check for outliers for RGBA tuple.

It is correct not to consider the case where color is None, (if it is None, should not to call this function), but in this function, It is more efficient to assume that color is None rather than handling all exceptions for None in the Visualize implementation. (By keeping the color Tuple as None, PIL can handle it automatically.)

Source code in SaigeToolkit/visualize/util.py
def add_opacity_to_color_tuple(
    color: Optional[Tuple[int, int, int]] = None,
    opacity: float = 1.0,
) -> Optional[Tuple[int, int, int, int]]:
    """Convert RGB color tuple to RGBA with specific opacity.

    Args:
        color (Tuple[int, int, int], optional): Tuple of RGB color,
            each value has the range [0, 255]. Defaults to None.
        opacity (float, optional): Opacity value.
            Expected range is [0., 1.]. Defaults to 1..

    Returns:
        Tuple[int, int, int, int]: Converted RGBA color tuple.

    Note:
        Since the `PIL` can handle outliers,
        this function does not separately check for outliers for RGBA tuple.

        It is correct not to consider the case where `color` is None,
        (if it is `None`, should not to call this function),
        but in this function, It is more efficient to assume that `color` is `None`
        rather than handling all exceptions for `None` in the `Visualize` implementation.
        (By keeping the `color` Tuple as None, `PIL` can handle it automatically.)

    """
    if color is None:
        return None

    return (*color, int(opacity * 255))

get_draw

get_draw(canvas: Image) -> ImageDraw

Function to force PIL.ImageDraw.Draw to RGBA mode

Source code in SaigeToolkit/visualize/draw.py
def get_draw(canvas: Image.Image) -> ImageDraw.ImageDraw:
    """Function to force `PIL.ImageDraw.Draw` to RGBA mode"""
    if canvas.mode != "RGBA":
        canvas = canvas.convert("RGBA")

    return ImageDraw.Draw(canvas)

overlay_solid_color

overlay_solid_color(image: Image, color: Tuple[int, int, int] = (0, 0, 0), opacity: float = 1.0) -> Image

Overlay solid color to image respect opacity.

Parameters:

  • image (Image) –

    Base image to be overlaid on.

  • color (Tuple[int, int, int], default: (0, 0, 0) ) –

    Tuple contain solid color's RGB value. Defaults to (0, 0, 0) (black).

  • opacity (float, default: 1.0 ) –

    Opacity value. Defaults to 1..

Returns:

  • Image

    Image.Image: Overlaid image.

Source code in SaigeToolkit/visualize/overlay.py
def overlay_solid_color(
    image: Image.Image, color: Tuple[int, int, int] = (0, 0, 0), opacity: float = 1.0
) -> Image.Image:
    """Overlay solid color to image respect opacity.

    Args:
        image (Image.Image): Base image to be overlaid on.
        color (Tuple[int, int, int], optional): Tuple contain solid color's RGB value.
            Defaults to (0, 0, 0) (black).
        opacity (float, optional): Opacity value. Defaults to 1..

    Returns:
        Image.Image: Overlaid image.

    """
    overlay = get_empty_layer(size=image.size, color=color, opacity=opacity)

    return blend_layers([image, overlay])

overlay_binary_mask

overlay_binary_mask(image: Image, mask: Image, fill: Tuple[int, int, int] = (255, 0, 0), opacity: float = 1.0) -> Image

Overlay binary mask to image respect opacity.

Parameters:

  • image (Image) –

    Base image to be overlaid on.

  • mask (Image) –

    Binary mask equal to the size of the image (one channel). All element should be 0 or 1.

  • fill (Tuple[int, int, int], default: (255, 0, 0) ) –

    Tuple contain solid color's RGB value. Defaults to (255, 0, 0) (red).

  • opacity (float, default: 1.0 ) –

    Opacity value. Defaults to 1..

Returns:

  • Image

    Image.Image: Mask overlaid image.

Source code in SaigeToolkit/visualize/overlay.py
def overlay_binary_mask(
    image: Image.Image, mask: Image.Image, fill: Tuple[int, int, int] = (255, 0, 0), opacity: float = 1.0
) -> Image.Image:
    """Overlay binary mask to image respect opacity.

    Args:
        image (Image.Image): Base image to be overlaid on.
        mask (Image.Image): Binary mask equal to the size of the image (one channel).
            All element should be 0 or 1.
        fill (Tuple[int, int, int], optional): Tuple contain solid color's RGB value.
            Defaults to (255, 0, 0) (red).
        opacity (float, optional): Opacity value. Defaults to 1..

    Returns:
        Image.Image: Mask overlaid image.

    """
    draw = get_draw(image)
    fill = add_opacity_to_color_tuple(fill, opacity)
    mask = Image.fromarray((mask * (opacity * 255))).convert("L")

    assert image.size == mask.size, (
        "Canvas and overraying mask should have same size!\n"
        + f"canvas: {image.size}, mask: {mask.size}"
    )
    draw.bitmap(xy=(0, 0), bitmap=mask, fill=fill)

    return image