Repository: roboflow/supervision
File: supervision/detection/utils.py (Python)

Code before:

    Note the axis orders:

    - `masks`: array of shape `(n, y, x)`
    - `offset`: array of ints: `(x, y)`
    - `desired_shape`: array of ints, shaped `(y, x, ...)`

    Args:
        masks (np.ndarray): array of bools
        offset (np.ndarray): An array of shape `(2,)` containing non-negative int values
            `[dx, dy]`.
        desired_shape (np.ndarray, optional): Final shape of the mask in the format
            `(height, width, ...)`. If provided, the masks will be padded to match this
            shape. Note the axis order (y,x)!

    Returns:
        (np.ndarray) repositioned masks, optionally padded to the specified shape.
    """
    if offset[0] < 0 or offset[1] < 0:
        raise ValueError(f"Offset values must be non-negative integers. Got: {offset}")

    size_x, size_y = masks.shape[1:] + offset[::-1]
    if desired_shape is not None:
        size_y, size_x = desired_shape[:2]

    mask_arr = np.full((masks.shape[0], size_y, size_x), False)
    mask_arr[
        :,
        offset[1] : masks.shape[1] + offset[1],
        offset[0] : masks.shape[2] + offset[0],
    ] = masks

    return mask_arr


def scale_boxes(xyxy: np.ndarray, factor: float) -> np.ndarray:
    """
    Scale the dimensions of bounding boxes.

    Parameters:
        xyxy (np.ndarray): An array of shape `(n, 4)` containing the bounding boxes
            coordinates in format `[x1, y1, x2, y2]`
        factor (float): A float value representing the factor by which the box
            dimensions are scaled. A factor greater than 1 enlarges the boxes, while a
            factor less than 1 shrinks them.

    Returns:
        np.ndarray: Scaled bounding boxes.

    Example:
        ```python

Review comment (suggestion):
Please don't use abbreviations, especially when word `array` is only two characters longer than `arr` :) 

Code after:
        offset (np.array): An array of shape `(2,)` containing offset values in format
            is `[dx, dy]`.

    Returns:
        np.ndarray: Repositioned bounding boxes.

    Example:
        ```python
        import numpy as np
        import supervision as sv

        boxes = np.array([[10, 10, 20, 20], [30, 30, 40, 40]])
        offset = np.array([5, 5])
        moved_box = sv.move_boxes(boxes, offset)
        print(moved_box)
        # np.array([
        #    [15, 15, 25, 25],
        #     [35, 35, 45, 45]
        # ])
        ```
    """
    return xyxy + np.hstack([offset, offset])


def move_masks(
    masks: np.ndarray,
    offset: np.ndarray,
    resolution_wh: Tuple[int, int] = None,
) -> np.ndarray:
    """
    Offset the masks in an array by the specified (x, y) amount.

    Args:
        masks (np.ndarray): A 3D array of binary masks corresponding to the predictions.
            Shape: `(N, H, W)`, where N is the number of predictions, and H, W are the
            dimensions of each mask.
        offset (np.ndarray): An array of shape `(2,)` containing non-negative int values
            `[dx, dy]`.
        resolution_wh (Tuple[int, int]): The width and height of the desired mask
            resolution.

    Returns:
        (np.ndarray) repositioned masks, optionally padded to the specified shape.
    """

    if offset[0] < 0 or offset[1] < 0:
        raise ValueError(f"Offset values must be non-negative integers. Got: {offset}")

    mask_array = np.full((masks.shape[0], resolution_wh[1], resolution_wh[0]), False)
    mask_array[
        :,