Source code for cv2ext.image._augment

# Copyright (c) 2024 Justin Davis (davisjustin302@gmail.com)
#
# MIT License
# ruff: noqa: RUF046
from __future__ import annotations

import cv2
import numpy as np


[docs] def letterbox( image: np.ndarray, new_shape: tuple[int, int] = (640, 640), stride: int = 32, color: tuple[int, int, int] = (114, 114, 114), *, auto: bool | None = None, scale_fill: bool | None = None, scaleup: bool | None = None, ) -> tuple[np.ndarray, tuple[float, float], tuple[float, float]]: """ Resize an image using the letterbox method. This method resizes an image to a new shape while maintaining the aspect ratio of the original image. The new image is padded with a specified color to fill the remaining space. The padding can be adjusted to be divisible by a specified stride. Parameters ---------- image : np.ndarray The image to resize new_shape : tuple[int, int] The new shape to resize the image to. In form (width, height) stride : int The stride to use for padding color : tuple[int, int, int] The color to use for padding auto : bool, optional Whether or not to automatically adjust the padding to be divisible by the stride scale_fill : bool, optional Whether or not to scale the image to fill the new shape scaleup : bool, optional Whether or not to scale the image up if the new shape is larger than the original image Returns ------- tuple[np.ndarray, tuple[float, float], tuple[float, float]] The resized image, the ratio of the new shape to the old shape, and the padding values used. """ if auto is None: auto = False if scale_fill is None: scale_fill = False if scaleup is None: scaleup = True shape = image.shape[:2] # Scale ratio (new / old) r = min(new_shape[1] / shape[0], new_shape[0] / shape[1]) if not scaleup: r = min(r, 1.0) ratio = (r, r) new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r)) dw: float = new_shape[0] - new_unpad[0] dh: float = new_shape[1] - new_unpad[1] if auto: dw, dh = np.mod(dw, stride), np.mod(dh, stride) elif scale_fill: dw, dh = 0.0, 0.0 new_unpad = (new_shape[0], new_shape[1]) ratio = ( new_shape[0] / shape[1], new_shape[1] / shape[0], ) dw /= 2 dh /= 2 if shape[::-1] != new_unpad: image = cv2.resize(image, new_unpad, interpolation=cv2.INTER_LINEAR) top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1)) left, right = int(round(dw - 0.1)), int(round(dw + 0.1)) image = cv2.copyMakeBorder( image, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color, ) return image, ratio, (dw, dh)
[docs] def resize_linear( image: np.ndarray, new_shape: tuple[int, int], ) -> tuple[np.ndarray, tuple[float, float]]: """ Resize an image using linear scaling. Parameters ---------- image : np.ndarray The image to resize. new_shape : tuple[int, int] The shape to resize the image to. In form (width, height) Returns ------- tuple[np.ndarray, tuple[float, float]] The resized image and the scaling factors from resizing """ tensor = cv2.resize(image, new_shape, interpolation=cv2.INTER_LINEAR) h, w = image.shape[:2] ratios = (new_shape[1] / w, new_shape[0] / h) return tensor, ratios