Skip to content

Référence pour ultralytics/utils/ops.py

Note

Ce fichier est disponible à l'adresse https://github.com/ultralytics/ ultralytics/blob/main/ ultralytics/utils/ops .py. Si tu repères un problème, aide à le corriger en contribuant à une Pull Request 🛠️. Merci 🙏 !



ultralytics.utils.ops.Profile

Bases : ContextDecorator

YOLOv8 Classe de profil. Utilise-la comme décorateur avec @Profile() ou comme gestionnaire de contexte avec 'with Profile():'.

Exemple
from ultralytics.utils.ops import Profile

with Profile(device=device) as dt:
    pass  # slow operation here

print(dt)  # prints "Elapsed time is 9.5367431640625e-07 s"
Code source dans ultralytics/utils/ops.py
class Profile(contextlib.ContextDecorator):
    """
    YOLOv8 Profile class. Use as a decorator with @Profile() or as a context manager with 'with Profile():'.

    Example:
        ```python
        from ultralytics.utils.ops import Profile

        with Profile(device=device) as dt:
            pass  # slow operation here

        print(dt)  # prints "Elapsed time is 9.5367431640625e-07 s"
        ```
    """

    def __init__(self, t=0.0, device: torch.device = None):
        """
        Initialize the Profile class.

        Args:
            t (float): Initial time. Defaults to 0.0.
            device (torch.device): Devices used for model inference. Defaults to None (cpu).
        """
        self.t = t
        self.device = device
        self.cuda = bool(device and str(device).startswith("cuda"))

    def __enter__(self):
        """Start timing."""
        self.start = self.time()
        return self

    def __exit__(self, type, value, traceback):  # noqa
        """Stop timing."""
        self.dt = self.time() - self.start  # delta-time
        self.t += self.dt  # accumulate dt

    def __str__(self):
        """Returns a human-readable string representing the accumulated elapsed time in the profiler."""
        return f"Elapsed time is {self.t} s"

    def time(self):
        """Get current time."""
        if self.cuda:
            torch.cuda.synchronize(self.device)
        return time.time()

__enter__()

Début de l'horaire.

Code source dans ultralytics/utils/ops.py
def __enter__(self):
    """Start timing."""
    self.start = self.time()
    return self

__exit__(type, value, traceback)

Arrête le chronométrage.

Code source dans ultralytics/utils/ops.py
def __exit__(self, type, value, traceback):  # noqa
    """Stop timing."""
    self.dt = self.time() - self.start  # delta-time
    self.t += self.dt  # accumulate dt

__init__(t=0.0, device=None)

Initialise la classe Profil.

Paramètres :

Nom Type Description Défaut
t float

Temps initial. La valeur par défaut est 0,0.

0.0
device device

Périphériques utilisés pour l'inférence du modèle. La valeur par défaut est Aucun (cpu).

None
Code source dans ultralytics/utils/ops.py
def __init__(self, t=0.0, device: torch.device = None):
    """
    Initialize the Profile class.

    Args:
        t (float): Initial time. Defaults to 0.0.
        device (torch.device): Devices used for model inference. Defaults to None (cpu).
    """
    self.t = t
    self.device = device
    self.cuda = bool(device and str(device).startswith("cuda"))

__str__()

Renvoie une chaîne lisible par l'homme représentant le temps écoulé accumulé dans le profileur.

Code source dans ultralytics/utils/ops.py
def __str__(self):
    """Returns a human-readable string representing the accumulated elapsed time in the profiler."""
    return f"Elapsed time is {self.t} s"

time()

Obtenir l'heure actuelle.

Code source dans ultralytics/utils/ops.py
def time(self):
    """Get current time."""
    if self.cuda:
        torch.cuda.synchronize(self.device)
    return time.time()



ultralytics.utils.ops.segment2box(segment, width=640, height=640)

Convertit 1 étiquette de segment en 1 étiquette de boîte, en appliquant la contrainte de l'image intérieure, c'est-à-dire que (xy1, xy2, ...) devient (xyxy).

Paramètres :

Nom Type Description Défaut
segment Tensor

l'étiquette du segment

requis
width int

la largeur de l'image. La valeur par défaut est 640

640
height int

La hauteur de l'image. La valeur par défaut est 640

640

Retourne :

Type Description
ndarray

les valeurs x et y minimales et maximales du segment.

Code source dans ultralytics/utils/ops.py
def segment2box(segment, width=640, height=640):
    """
    Convert 1 segment label to 1 box label, applying inside-image constraint, i.e. (xy1, xy2, ...) to (xyxy).

    Args:
        segment (torch.Tensor): the segment label
        width (int): the width of the image. Defaults to 640
        height (int): The height of the image. Defaults to 640

    Returns:
        (np.ndarray): the minimum and maximum x and y values of the segment.
    """
    x, y = segment.T  # segment xy
    inside = (x >= 0) & (y >= 0) & (x <= width) & (y <= height)
    x = x[inside]
    y = y[inside]
    return (
        np.array([x.min(), y.min(), x.max(), y.max()], dtype=segment.dtype)
        if any(x)
        else np.zeros(4, dtype=segment.dtype)
    )  # xyxy



ultralytics.utils.ops.scale_boxes(img1_shape, boxes, img0_shape, ratio_pad=None, padding=True, xywh=False)

Redimensionne les boîtes de délimitation (au format xyxy par défaut) de la forme de l'image dans laquelle elles ont été spécifiées à l'origine (img1_shape) à la forme d'une image différente (img0_shape).

Paramètres :

Nom Type Description Défaut
img1_shape tuple

La forme de l'image à laquelle correspondent les boîtes de délimitation, au format (hauteur, largeur).

requis
boxes Tensor

les boîtes de délimitation des objets de l'image, au format (x1, y1, x2, y2)

requis
img0_shape tuple

la forme de l'image cible, au format (hauteur, largeur).

requis
ratio_pad tuple

un tuple de (ratio, pad) pour la mise à l'échelle des boîtes. S'ils ne sont pas fournis, le ratio et le tampon seront calculés en fonction de la différence de taille entre les deux images.

None
padding bool

Si c'est vrai, on suppose que les boîtes sont basées sur l'image augmentée par le style yolo . Si False, on procède à un redimensionnement.

True
xywh bool

Le format de la boîte est xywh ou non, par défaut=False.

False

Retourne :

Nom Type Description
boxes Tensor

Les boîtes de délimitation mises à l'échelle, au format (x1, y1, x2, y2).

Code source dans ultralytics/utils/ops.py
def scale_boxes(img1_shape, boxes, img0_shape, ratio_pad=None, padding=True, xywh=False):
    """
    Rescales bounding boxes (in the format of xyxy by default) from the shape of the image they were originally
    specified in (img1_shape) to the shape of a different image (img0_shape).

    Args:
        img1_shape (tuple): The shape of the image that the bounding boxes are for, in the format of (height, width).
        boxes (torch.Tensor): the bounding boxes of the objects in the image, in the format of (x1, y1, x2, y2)
        img0_shape (tuple): the shape of the target image, in the format of (height, width).
        ratio_pad (tuple): a tuple of (ratio, pad) for scaling the boxes. If not provided, the ratio and pad will be
            calculated based on the size difference between the two images.
        padding (bool): If True, assuming the boxes is based on image augmented by yolo style. If False then do regular
            rescaling.
        xywh (bool): The box format is xywh or not, default=False.

    Returns:
        boxes (torch.Tensor): The scaled bounding boxes, in the format of (x1, y1, x2, y2)
    """
    if ratio_pad is None:  # calculate from img0_shape
        gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1])  # gain  = old / new
        pad = (
            round((img1_shape[1] - img0_shape[1] * gain) / 2 - 0.1),
            round((img1_shape[0] - img0_shape[0] * gain) / 2 - 0.1),
        )  # wh padding
    else:
        gain = ratio_pad[0][0]
        pad = ratio_pad[1]

    if padding:
        boxes[..., 0] -= pad[0]  # x padding
        boxes[..., 1] -= pad[1]  # y padding
        if not xywh:
            boxes[..., 2] -= pad[0]  # x padding
            boxes[..., 3] -= pad[1]  # y padding
    boxes[..., :4] /= gain
    return clip_boxes(boxes, img0_shape)



ultralytics.utils.ops.make_divisible(x, divisor)

Renvoie le nombre le plus proche qui est divisible par le diviseur donné.

Paramètres :

Nom Type Description Défaut
x int

Le nombre à rendre divisible.

requis
divisor int | Tensor

Le diviseur.

requis

Retourne :

Type Description
int

Le nombre le plus proche divisible par le diviseur.

Code source dans ultralytics/utils/ops.py
def make_divisible(x, divisor):
    """
    Returns the nearest number that is divisible by the given divisor.

    Args:
        x (int): The number to make divisible.
        divisor (int | torch.Tensor): The divisor.

    Returns:
        (int): The nearest number divisible by the divisor.
    """
    if isinstance(divisor, torch.Tensor):
        divisor = int(divisor.max())  # to int
    return math.ceil(x / divisor) * divisor



ultralytics.utils.ops.nms_rotated(boxes, scores, threshold=0.45)

NMS pour obbs, alimenté par probiou et fast-nms.

Paramètres :

Nom Type Description Défaut
boxes Tensor

(N, 5), xywhr.

requis
scores Tensor

(N, ).

requis
threshold float

Seuil de référence.

0.45

Retourne :

Code source dans ultralytics/utils/ops.py
def nms_rotated(boxes, scores, threshold=0.45):
    """
    NMS for obbs, powered by probiou and fast-nms.

    Args:
        boxes (torch.Tensor): (N, 5), xywhr.
        scores (torch.Tensor): (N, ).
        threshold (float): IoU threshold.

    Returns:
    """
    if len(boxes) == 0:
        return np.empty((0,), dtype=np.int8)
    sorted_idx = torch.argsort(scores, descending=True)
    boxes = boxes[sorted_idx]
    ious = batch_probiou(boxes, boxes).triu_(diagonal=1)
    pick = torch.nonzero(ious.max(dim=0)[0] < threshold).squeeze_(-1)
    return sorted_idx[pick]



ultralytics.utils.ops.non_max_suppression(prediction, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic=False, multi_label=False, labels=(), max_det=300, nc=0, max_time_img=0.05, max_nms=30000, max_wh=7680, in_place=True, rotated=False)

Effectue une suppression non maximale (NMS) sur un ensemble de boîtes, avec prise en charge des masques et des étiquettes multiples par boîte.

Paramètres :

Nom Type Description Défaut
prediction Tensor

Une tensor de forme (batch_size, num_classes + 4 + num_masks, num_boxes) contenant les boîtes, les classes et les masques prédits. Le site tensor doit être au format produit par un modèle, tel que YOLO.

requis
conf_thres float

Le seuil de confiance en dessous duquel les boîtes seront filtrées. Les valeurs valides sont comprises entre 0,0 et 1,0.

0.25
iou_thres float

Seuil de l'IoU en dessous duquel les boîtes seront filtrées pendant le NMS. Les valeurs valides sont comprises entre 0,0 et 1,0.

0.45
classes List[int]

Une liste d'indices de classe à prendre en compte. Si Aucun, toutes les classes seront prises en compte.

None
agnostic bool

Si True, le modèle est indifférent au nombre de classes, et toutes les classes seront considérées comme une seule. seront considérées comme une seule classe.

False
multi_label bool

Si c'est le cas, chaque boîte peut avoir plusieurs étiquettes.

False
labels List[List[Union[int, float, Tensor]]]

Une liste de listes, où chaque liste interne contient les étiquettes apriori pour une image donnée. La liste doit être au format produit par un chargeur de données, chaque étiquette étant un tuple de (class_index, x1, y1, x2, y2).

()
max_det int

Le nombre maximum de boîtes à conserver après le NMS.

300
nc int

Le nombre de classes produites par le modèle. Tout indice postérieur à cette valeur sera considéré comme un masque.

0
max_time_img float

Le temps maximum (secondes) pour le traitement d'une image.

0.05
max_nms int

Le nombre maximum de cases dans torchvision.ops.nms().

30000
max_wh int

La largeur et la hauteur maximales de la boîte en pixels.

7680
in_place bool

Si True, la prédiction d'entrée tensor sera modifiée sur place.

True

Retourne :

Type Description
List[Tensor]

Une liste de longueur batch_size, où chaque élément est un tensor de forme (num_boxes, 6 + num_masks) contenant des boîtes conservées. forme (num_boxes, 6 + num_masks) contenant les boîtes conservées, avec des colonnes (x1, y1, x2, y2, confidence, class, mask1, mask2, ...).

Code source dans ultralytics/utils/ops.py
def non_max_suppression(
    prediction,
    conf_thres=0.25,
    iou_thres=0.45,
    classes=None,
    agnostic=False,
    multi_label=False,
    labels=(),
    max_det=300,
    nc=0,  # number of classes (optional)
    max_time_img=0.05,
    max_nms=30000,
    max_wh=7680,
    in_place=True,
    rotated=False,
):
    """
    Perform non-maximum suppression (NMS) on a set of boxes, with support for masks and multiple labels per box.

    Args:
        prediction (torch.Tensor): A tensor of shape (batch_size, num_classes + 4 + num_masks, num_boxes)
            containing the predicted boxes, classes, and masks. The tensor should be in the format
            output by a model, such as YOLO.
        conf_thres (float): The confidence threshold below which boxes will be filtered out.
            Valid values are between 0.0 and 1.0.
        iou_thres (float): The IoU threshold below which boxes will be filtered out during NMS.
            Valid values are between 0.0 and 1.0.
        classes (List[int]): A list of class indices to consider. If None, all classes will be considered.
        agnostic (bool): If True, the model is agnostic to the number of classes, and all
            classes will be considered as one.
        multi_label (bool): If True, each box may have multiple labels.
        labels (List[List[Union[int, float, torch.Tensor]]]): A list of lists, where each inner
            list contains the apriori labels for a given image. The list should be in the format
            output by a dataloader, with each label being a tuple of (class_index, x1, y1, x2, y2).
        max_det (int): The maximum number of boxes to keep after NMS.
        nc (int, optional): The number of classes output by the model. Any indices after this will be considered masks.
        max_time_img (float): The maximum time (seconds) for processing one image.
        max_nms (int): The maximum number of boxes into torchvision.ops.nms().
        max_wh (int): The maximum box width and height in pixels.
        in_place (bool): If True, the input prediction tensor will be modified in place.

    Returns:
        (List[torch.Tensor]): A list of length batch_size, where each element is a tensor of
            shape (num_boxes, 6 + num_masks) containing the kept boxes, with columns
            (x1, y1, x2, y2, confidence, class, mask1, mask2, ...).
    """
    import torchvision  # scope for faster 'import ultralytics'

    # Checks
    assert 0 <= conf_thres <= 1, f"Invalid Confidence threshold {conf_thres}, valid values are between 0.0 and 1.0"
    assert 0 <= iou_thres <= 1, f"Invalid IoU {iou_thres}, valid values are between 0.0 and 1.0"
    if isinstance(prediction, (list, tuple)):  # YOLOv8 model in validation model, output = (inference_out, loss_out)
        prediction = prediction[0]  # select only inference output

    bs = prediction.shape[0]  # batch size
    nc = nc or (prediction.shape[1] - 4)  # number of classes
    nm = prediction.shape[1] - nc - 4
    mi = 4 + nc  # mask start index
    xc = prediction[:, 4:mi].amax(1) > conf_thres  # candidates

    # Settings
    # min_wh = 2  # (pixels) minimum box width and height
    time_limit = 2.0 + max_time_img * bs  # seconds to quit after
    multi_label &= nc > 1  # multiple labels per box (adds 0.5ms/img)

    prediction = prediction.transpose(-1, -2)  # shape(1,84,6300) to shape(1,6300,84)
    if not rotated:
        if in_place:
            prediction[..., :4] = xywh2xyxy(prediction[..., :4])  # xywh to xyxy
        else:
            prediction = torch.cat((xywh2xyxy(prediction[..., :4]), prediction[..., 4:]), dim=-1)  # xywh to xyxy

    t = time.time()
    output = [torch.zeros((0, 6 + nm), device=prediction.device)] * bs
    for xi, x in enumerate(prediction):  # image index, image inference
        # Apply constraints
        # x[((x[:, 2:4] < min_wh) | (x[:, 2:4] > max_wh)).any(1), 4] = 0  # width-height
        x = x[xc[xi]]  # confidence

        # Cat apriori labels if autolabelling
        if labels and len(labels[xi]) and not rotated:
            lb = labels[xi]
            v = torch.zeros((len(lb), nc + nm + 4), device=x.device)
            v[:, :4] = xywh2xyxy(lb[:, 1:5])  # box
            v[range(len(lb)), lb[:, 0].long() + 4] = 1.0  # cls
            x = torch.cat((x, v), 0)

        # If none remain process next image
        if not x.shape[0]:
            continue

        # Detections matrix nx6 (xyxy, conf, cls)
        box, cls, mask = x.split((4, nc, nm), 1)

        if multi_label:
            i, j = torch.where(cls > conf_thres)
            x = torch.cat((box[i], x[i, 4 + j, None], j[:, None].float(), mask[i]), 1)
        else:  # best class only
            conf, j = cls.max(1, keepdim=True)
            x = torch.cat((box, conf, j.float(), mask), 1)[conf.view(-1) > conf_thres]

        # Filter by class
        if classes is not None:
            x = x[(x[:, 5:6] == torch.tensor(classes, device=x.device)).any(1)]

        # Check shape
        n = x.shape[0]  # number of boxes
        if not n:  # no boxes
            continue
        if n > max_nms:  # excess boxes
            x = x[x[:, 4].argsort(descending=True)[:max_nms]]  # sort by confidence and remove excess boxes

        # Batched NMS
        c = x[:, 5:6] * (0 if agnostic else max_wh)  # classes
        scores = x[:, 4]  # scores
        if rotated:
            boxes = torch.cat((x[:, :2] + c, x[:, 2:4], x[:, -1:]), dim=-1)  # xywhr
            i = nms_rotated(boxes, scores, iou_thres)
        else:
            boxes = x[:, :4] + c  # boxes (offset by class)
            i = torchvision.ops.nms(boxes, scores, iou_thres)  # NMS
        i = i[:max_det]  # limit detections

        # # Experimental
        # merge = False  # use merge-NMS
        # if merge and (1 < n < 3E3):  # Merge NMS (boxes merged using weighted mean)
        #     # Update boxes as boxes(i,4) = weights(i,n) * boxes(n,4)
        #     from .metrics import box_iou
        #     iou = box_iou(boxes[i], boxes) > iou_thres  # IoU matrix
        #     weights = iou * scores[None]  # box weights
        #     x[i, :4] = torch.mm(weights, x[:, :4]).float() / weights.sum(1, keepdim=True)  # merged boxes
        #     redundant = True  # require redundant detections
        #     if redundant:
        #         i = i[iou.sum(1) > 1]  # require redundancy

        output[xi] = x[i]
        if (time.time() - t) > time_limit:
            LOGGER.warning(f"WARNING ⚠️ NMS time limit {time_limit:.3f}s exceeded")
            break  # time limit exceeded

    return output



ultralytics.utils.ops.clip_boxes(boxes, shape)

Prend une liste de boîtes de délimitation et une forme (hauteur, largeur) et clippe les boîtes de délimitation sur la forme.

Paramètres :

Nom Type Description Défaut
boxes Tensor

les boîtes de délimitation à découper

requis
shape tuple

la forme de l'image

requis

Retourne :

Type Description
Tensor | ndarray

Boîtes coupées

Code source dans ultralytics/utils/ops.py
def clip_boxes(boxes, shape):
    """
    Takes a list of bounding boxes and a shape (height, width) and clips the bounding boxes to the shape.

    Args:
        boxes (torch.Tensor): the bounding boxes to clip
        shape (tuple): the shape of the image

    Returns:
        (torch.Tensor | numpy.ndarray): Clipped boxes
    """
    if isinstance(boxes, torch.Tensor):  # faster individually (WARNING: inplace .clamp_() Apple MPS bug)
        boxes[..., 0] = boxes[..., 0].clamp(0, shape[1])  # x1
        boxes[..., 1] = boxes[..., 1].clamp(0, shape[0])  # y1
        boxes[..., 2] = boxes[..., 2].clamp(0, shape[1])  # x2
        boxes[..., 3] = boxes[..., 3].clamp(0, shape[0])  # y2
    else:  # np.array (faster grouped)
        boxes[..., [0, 2]] = boxes[..., [0, 2]].clip(0, shape[1])  # x1, x2
        boxes[..., [1, 3]] = boxes[..., [1, 3]].clip(0, shape[0])  # y1, y2
    return boxes



ultralytics.utils.ops.clip_coords(coords, shape)

Attache les coordonnées de la ligne aux limites de l'image.

Paramètres :

Nom Type Description Défaut
coords Tensor | ndarray

Une liste de coordonnées de lignes.

requis
shape tuple

Un tuple d'entiers représentant la taille de l'image au format (hauteur, largeur).

requis

Retourne :

Type Description
Tensor | ndarray

Coordonnées coupées

Code source dans ultralytics/utils/ops.py
def clip_coords(coords, shape):
    """
    Clip line coordinates to the image boundaries.

    Args:
        coords (torch.Tensor | numpy.ndarray): A list of line coordinates.
        shape (tuple): A tuple of integers representing the size of the image in the format (height, width).

    Returns:
        (torch.Tensor | numpy.ndarray): Clipped coordinates
    """
    if isinstance(coords, torch.Tensor):  # faster individually (WARNING: inplace .clamp_() Apple MPS bug)
        coords[..., 0] = coords[..., 0].clamp(0, shape[1])  # x
        coords[..., 1] = coords[..., 1].clamp(0, shape[0])  # y
    else:  # np.array (faster grouped)
        coords[..., 0] = coords[..., 0].clip(0, shape[1])  # x
        coords[..., 1] = coords[..., 1].clip(0, shape[0])  # y
    return coords



ultralytics.utils.ops.scale_image(masks, im0_shape, ratio_pad=None)

Prend un masque et le redimensionne à la taille de l'image originale.

Paramètres :

Nom Type Description Défaut
masks ndarray

Masques/images redimensionnés et rembourrés, [h, w, num]/[h, w, 3].

requis
im0_shape tuple

la forme de l'image originale

requis
ratio_pad tuple

le rapport entre le rembourrage et l'image originale.

None

Retourne :

Nom Type Description
masks Tensor

Les masques qui sont renvoyés.

Code source dans ultralytics/utils/ops.py
def scale_image(masks, im0_shape, ratio_pad=None):
    """
    Takes a mask, and resizes it to the original image size.

    Args:
        masks (np.ndarray): resized and padded masks/images, [h, w, num]/[h, w, 3].
        im0_shape (tuple): the original image shape
        ratio_pad (tuple): the ratio of the padding to the original image.

    Returns:
        masks (torch.Tensor): The masks that are being returned.
    """
    # Rescale coordinates (xyxy) from im1_shape to im0_shape
    im1_shape = masks.shape
    if im1_shape[:2] == im0_shape[:2]:
        return masks
    if ratio_pad is None:  # calculate from im0_shape
        gain = min(im1_shape[0] / im0_shape[0], im1_shape[1] / im0_shape[1])  # gain  = old / new
        pad = (im1_shape[1] - im0_shape[1] * gain) / 2, (im1_shape[0] - im0_shape[0] * gain) / 2  # wh padding
    else:
        # gain = ratio_pad[0][0]
        pad = ratio_pad[1]
    top, left = int(pad[1]), int(pad[0])  # y, x
    bottom, right = int(im1_shape[0] - pad[1]), int(im1_shape[1] - pad[0])

    if len(masks.shape) < 2:
        raise ValueError(f'"len of masks shape" should be 2 or 3, but got {len(masks.shape)}')
    masks = masks[top:bottom, left:right]
    masks = cv2.resize(masks, (im0_shape[1], im0_shape[0]))
    if len(masks.shape) == 2:
        masks = masks[:, :, None]

    return masks



ultralytics.utils.ops.xyxy2xywh(x)

Convertit les coordonnées de la boîte de délimitation du format (x1, y1, x2, y2) au format (x, y, largeur, hauteur) où (x1, y1) est le coin supérieur gauche et (x2, y2) le coin inférieur droit. coin supérieur gauche et (x2, y2) le coin inférieur droit.

Paramètres :

Nom Type Description Défaut
x ndarray | Tensor

Les coordonnées de la boîte de délimitation d'entrée au format (x1, y1, x2, y2).

requis

Retourne :

Nom Type Description
y ndarray | Tensor

Les coordonnées de la boîte de délimitation au format (x, y, largeur, hauteur).

Code source dans ultralytics/utils/ops.py
def xyxy2xywh(x):
    """
    Convert bounding box coordinates from (x1, y1, x2, y2) format to (x, y, width, height) format where (x1, y1) is the
    top-left corner and (x2, y2) is the bottom-right corner.

    Args:
        x (np.ndarray | torch.Tensor): The input bounding box coordinates in (x1, y1, x2, y2) format.

    Returns:
        y (np.ndarray | torch.Tensor): The bounding box coordinates in (x, y, width, height) format.
    """
    assert x.shape[-1] == 4, f"input shape last dimension expected 4 but input shape is {x.shape}"
    y = torch.empty_like(x) if isinstance(x, torch.Tensor) else np.empty_like(x)  # faster than clone/copy
    y[..., 0] = (x[..., 0] + x[..., 2]) / 2  # x center
    y[..., 1] = (x[..., 1] + x[..., 3]) / 2  # y center
    y[..., 2] = x[..., 2] - x[..., 0]  # width
    y[..., 3] = x[..., 3] - x[..., 1]  # height
    return y



ultralytics.utils.ops.xywh2xyxy(x)

Convertit les coordonnées de la boîte de délimitation du format (x, y, largeur, hauteur) au format (x1, y1, x2, y2) où (x1, y1) est le coin supérieur gauche et (x2, y2) le coin inférieur droit. coin supérieur gauche et (x2, y2) le coin inférieur droit.

Paramètres :

Nom Type Description Défaut
x ndarray | Tensor

Les coordonnées de la boîte de délimitation d'entrée au format (x, y, largeur, hauteur).

requis

Retourne :

Nom Type Description
y ndarray | Tensor

Les coordonnées de la boîte de délimitation au format (x1, y1, x2, y2).

Code source dans ultralytics/utils/ops.py
def xywh2xyxy(x):
    """
    Convert bounding box coordinates from (x, y, width, height) format to (x1, y1, x2, y2) format where (x1, y1) is the
    top-left corner and (x2, y2) is the bottom-right corner.

    Args:
        x (np.ndarray | torch.Tensor): The input bounding box coordinates in (x, y, width, height) format.

    Returns:
        y (np.ndarray | torch.Tensor): The bounding box coordinates in (x1, y1, x2, y2) format.
    """
    assert x.shape[-1] == 4, f"input shape last dimension expected 4 but input shape is {x.shape}"
    y = torch.empty_like(x) if isinstance(x, torch.Tensor) else np.empty_like(x)  # faster than clone/copy
    dw = x[..., 2] / 2  # half-width
    dh = x[..., 3] / 2  # half-height
    y[..., 0] = x[..., 0] - dw  # top left x
    y[..., 1] = x[..., 1] - dh  # top left y
    y[..., 2] = x[..., 0] + dw  # bottom right x
    y[..., 3] = x[..., 1] + dh  # bottom right y
    return y



ultralytics.utils.ops.xywhn2xyxy(x, w=640, h=640, padw=0, padh=0)

Convertit les coordonnées normalisées de la boîte de délimitation en coordonnées de pixels.

Paramètres :

Nom Type Description Défaut
x ndarray | Tensor

Les coordonnées de la boîte de délimitation.

requis
w int

Largeur de l'image. La valeur par défaut est 640

640
h int

Hauteur de l'image. La valeur par défaut est 640

640
padw int

Largeur de l'espacement. La valeur par défaut est 0

0
padh int

Hauteur du rembourrage. La valeur par défaut est 0

0

Retourne : y (np.ndarray | torch.Tensor) : Les coordonnées de la boîte englobante au format [x1, y1, x2, y2] où x1,y1 est le coin supérieur gauche, x2,y2 est le coin inférieur droit de la boîte englobante.

Code source dans ultralytics/utils/ops.py
def xywhn2xyxy(x, w=640, h=640, padw=0, padh=0):
    """
    Convert normalized bounding box coordinates to pixel coordinates.

    Args:
        x (np.ndarray | torch.Tensor): The bounding box coordinates.
        w (int): Width of the image. Defaults to 640
        h (int): Height of the image. Defaults to 640
        padw (int): Padding width. Defaults to 0
        padh (int): Padding height. Defaults to 0
    Returns:
        y (np.ndarray | torch.Tensor): The coordinates of the bounding box in the format [x1, y1, x2, y2] where
            x1,y1 is the top-left corner, x2,y2 is the bottom-right corner of the bounding box.
    """
    assert x.shape[-1] == 4, f"input shape last dimension expected 4 but input shape is {x.shape}"
    y = torch.empty_like(x) if isinstance(x, torch.Tensor) else np.empty_like(x)  # faster than clone/copy
    y[..., 0] = w * (x[..., 0] - x[..., 2] / 2) + padw  # top left x
    y[..., 1] = h * (x[..., 1] - x[..., 3] / 2) + padh  # top left y
    y[..., 2] = w * (x[..., 0] + x[..., 2] / 2) + padw  # bottom right x
    y[..., 3] = h * (x[..., 1] + x[..., 3] / 2) + padh  # bottom right y
    return y



ultralytics.utils.ops.xyxy2xywhn(x, w=640, h=640, clip=False, eps=0.0)

Convertit les coordonnées de la boîte englobante du format (x1, y1, x2, y2) au format (x, y, largeur, hauteur, normalisé). x, y, la largeur et la hauteur sont normalisés en fonction des dimensions de l'image.

Paramètres :

Nom Type Description Défaut
x ndarray | Tensor

Les coordonnées de la boîte de délimitation d'entrée au format (x1, y1, x2, y2).

requis
w int

La largeur de l'image. La valeur par défaut est 640

640
h int

La hauteur de l'image. La valeur par défaut est 640

640
clip bool

Si True, les boîtes seront coupées aux limites de l'image. La valeur par défaut est False

False
eps float

La valeur minimale de la largeur et de la hauteur de la boîte. La valeur par défaut est 0,0

0.0

Retourne :

Nom Type Description
y ndarray | Tensor

Les coordonnées de la boîte de délimitation au format (x, y, largeur, hauteur, normalisé).

Code source dans ultralytics/utils/ops.py
def xyxy2xywhn(x, w=640, h=640, clip=False, eps=0.0):
    """
    Convert bounding box coordinates from (x1, y1, x2, y2) format to (x, y, width, height, normalized) format. x, y,
    width and height are normalized to image dimensions.

    Args:
        x (np.ndarray | torch.Tensor): The input bounding box coordinates in (x1, y1, x2, y2) format.
        w (int): The width of the image. Defaults to 640
        h (int): The height of the image. Defaults to 640
        clip (bool): If True, the boxes will be clipped to the image boundaries. Defaults to False
        eps (float): The minimum value of the box's width and height. Defaults to 0.0

    Returns:
        y (np.ndarray | torch.Tensor): The bounding box coordinates in (x, y, width, height, normalized) format
    """
    if clip:
        x = clip_boxes(x, (h - eps, w - eps))
    assert x.shape[-1] == 4, f"input shape last dimension expected 4 but input shape is {x.shape}"
    y = torch.empty_like(x) if isinstance(x, torch.Tensor) else np.empty_like(x)  # faster than clone/copy
    y[..., 0] = ((x[..., 0] + x[..., 2]) / 2) / w  # x center
    y[..., 1] = ((x[..., 1] + x[..., 3]) / 2) / h  # y center
    y[..., 2] = (x[..., 2] - x[..., 0]) / w  # width
    y[..., 3] = (x[..., 3] - x[..., 1]) / h  # height
    return y



ultralytics.utils.ops.xywh2ltwh(x)

Convertit le format de la boîte de délimitation de [x, y, w, h] en [x1, y1, w, h], où x1, y1 sont les coordonnées en haut à gauche.

Paramètres :

Nom Type Description Défaut
x ndarray | Tensor

L'entrée tensor avec les coordonnées de la boîte de délimitation au format xywh

requis

Retourne :

Nom Type Description
y ndarray | Tensor

Les coordonnées de la boîte de délimitation au format xyltwh.

Code source dans ultralytics/utils/ops.py
def xywh2ltwh(x):
    """
    Convert the bounding box format from [x, y, w, h] to [x1, y1, w, h], where x1, y1 are the top-left coordinates.

    Args:
        x (np.ndarray | torch.Tensor): The input tensor with the bounding box coordinates in the xywh format

    Returns:
        y (np.ndarray | torch.Tensor): The bounding box coordinates in the xyltwh format
    """
    y = x.clone() if isinstance(x, torch.Tensor) else np.copy(x)
    y[..., 0] = x[..., 0] - x[..., 2] / 2  # top left x
    y[..., 1] = x[..., 1] - x[..., 3] / 2  # top left y
    return y



ultralytics.utils.ops.xyxy2ltwh(x)

Convertit nx4 boîtes de délimitation de [x1, y1, x2, y2] en [x1, y1, w, h], où xy1=haut-gauche, xy2=bas-droite.

Paramètres :

Nom Type Description Défaut
x ndarray | Tensor

L'entrée tensor avec les coordonnées des boîtes de délimitation au format xyxy

requis

Retourne :

Nom Type Description
y ndarray | Tensor

Les coordonnées de la boîte de délimitation au format xyltwh.

Code source dans ultralytics/utils/ops.py
def xyxy2ltwh(x):
    """
    Convert nx4 bounding boxes from [x1, y1, x2, y2] to [x1, y1, w, h], where xy1=top-left, xy2=bottom-right.

    Args:
        x (np.ndarray | torch.Tensor): The input tensor with the bounding boxes coordinates in the xyxy format

    Returns:
        y (np.ndarray | torch.Tensor): The bounding box coordinates in the xyltwh format.
    """
    y = x.clone() if isinstance(x, torch.Tensor) else np.copy(x)
    y[..., 2] = x[..., 2] - x[..., 0]  # width
    y[..., 3] = x[..., 3] - x[..., 1]  # height
    return y



ultralytics.utils.ops.ltwh2xywh(x)

Convertit nx4 boîtes de [x1, y1, w, h] en [x, y, w, h] où xy1=haut-gauche, xy=centre.

Paramètres :

Nom Type Description Défaut
x Tensor

l'entrée tensor

requis

Retourne :

Nom Type Description
y ndarray | Tensor

Les coordonnées de la boîte de délimitation au format xywh.

Code source dans ultralytics/utils/ops.py
def ltwh2xywh(x):
    """
    Convert nx4 boxes from [x1, y1, w, h] to [x, y, w, h] where xy1=top-left, xy=center.

    Args:
        x (torch.Tensor): the input tensor

    Returns:
        y (np.ndarray | torch.Tensor): The bounding box coordinates in the xywh format.
    """
    y = x.clone() if isinstance(x, torch.Tensor) else np.copy(x)
    y[..., 0] = x[..., 0] + x[..., 2] / 2  # center x
    y[..., 1] = x[..., 1] + x[..., 3] / 2  # center y
    return y



ultralytics.utils.ops.xyxyxyxy2xywhr(corners)

Convertit les boîtes de délimitation orientées (OBB) de [xy1, xy2, xy3, xy4] en [xywh, rotation]. Les valeurs de rotation sont sont attendues en degrés de 0 à 90.

Paramètres :

Nom Type Description Défaut
corners ndarray | Tensor

Coins d'entrée de la forme (n, 8).

requis

Retourne :

Type Description
ndarray | Tensor

Données converties au format [cx, cy, w, h, rotation] de la forme (n, 5).

Code source dans ultralytics/utils/ops.py
def xyxyxyxy2xywhr(corners):
    """
    Convert batched Oriented Bounding Boxes (OBB) from [xy1, xy2, xy3, xy4] to [xywh, rotation]. Rotation values are
    expected in degrees from 0 to 90.

    Args:
        corners (numpy.ndarray | torch.Tensor): Input corners of shape (n, 8).

    Returns:
        (numpy.ndarray | torch.Tensor): Converted data in [cx, cy, w, h, rotation] format of shape (n, 5).
    """
    is_torch = isinstance(corners, torch.Tensor)
    points = corners.cpu().numpy() if is_torch else corners
    points = points.reshape(len(corners), -1, 2)
    rboxes = []
    for pts in points:
        # NOTE: Use cv2.minAreaRect to get accurate xywhr,
        # especially some objects are cut off by augmentations in dataloader.
        (x, y), (w, h), angle = cv2.minAreaRect(pts)
        rboxes.append([x, y, w, h, angle / 180 * np.pi])
    return (
        torch.tensor(rboxes, device=corners.device, dtype=corners.dtype)
        if is_torch
        else np.asarray(rboxes, dtype=points.dtype)
    )  # rboxes



ultralytics.utils.ops.xywhr2xyxyxyxy(rboxes)

Convertit les boîtes de délimitation orientées (OBB) de [xywh, rotation] en [xy1, xy2, xy3, xy4]. Les valeurs de rotation doivent doivent être exprimées en degrés de 0 à 90.

Paramètres :

Nom Type Description Défaut
rboxes ndarray | Tensor

Boîtes au format [cx, cy, w, h, rotation] de forme (n, 5) ou (b, n, 5).

requis

Retourne :

Type Description
ndarray | Tensor

Points d'angle convertis de la forme (n, 4, 2) ou (b, n, 4, 2).

Code source dans ultralytics/utils/ops.py
def xywhr2xyxyxyxy(rboxes):
    """
    Convert batched Oriented Bounding Boxes (OBB) from [xywh, rotation] to [xy1, xy2, xy3, xy4]. Rotation values should
    be in degrees from 0 to 90.

    Args:
        rboxes (numpy.ndarray | torch.Tensor): Boxes in [cx, cy, w, h, rotation] format of shape (n, 5) or (b, n, 5).

    Returns:
        (numpy.ndarray | torch.Tensor): Converted corner points of shape (n, 4, 2) or (b, n, 4, 2).
    """
    is_numpy = isinstance(rboxes, np.ndarray)
    cos, sin = (np.cos, np.sin) if is_numpy else (torch.cos, torch.sin)

    ctr = rboxes[..., :2]
    w, h, angle = (rboxes[..., i : i + 1] for i in range(2, 5))
    cos_value, sin_value = cos(angle), sin(angle)
    vec1 = [w / 2 * cos_value, w / 2 * sin_value]
    vec2 = [-h / 2 * sin_value, h / 2 * cos_value]
    vec1 = np.concatenate(vec1, axis=-1) if is_numpy else torch.cat(vec1, dim=-1)
    vec2 = np.concatenate(vec2, axis=-1) if is_numpy else torch.cat(vec2, dim=-1)
    pt1 = ctr + vec1 + vec2
    pt2 = ctr + vec1 - vec2
    pt3 = ctr - vec1 - vec2
    pt4 = ctr - vec1 + vec2
    return np.stack([pt1, pt2, pt3, pt4], axis=-2) if is_numpy else torch.stack([pt1, pt2, pt3, pt4], dim=-2)



ultralytics.utils.ops.ltwh2xyxy(x)

Il convertit la boîte de délimitation de [x1, y1, w, h] en [x1, y1, x2, y2] où xy1=haut-gauche, xy2=bas-droite.

Paramètres :

Nom Type Description Défaut
x ndarray | Tensor

l'image d'entrée

requis

Retourne :

Nom Type Description
y ndarray | Tensor

les coordonnées xyxy des boîtes de délimitation.

Code source dans ultralytics/utils/ops.py
def ltwh2xyxy(x):
    """
    It converts the bounding box from [x1, y1, w, h] to [x1, y1, x2, y2] where xy1=top-left, xy2=bottom-right.

    Args:
        x (np.ndarray | torch.Tensor): the input image

    Returns:
        y (np.ndarray | torch.Tensor): the xyxy coordinates of the bounding boxes.
    """
    y = x.clone() if isinstance(x, torch.Tensor) else np.copy(x)
    y[..., 2] = x[..., 2] + x[..., 0]  # width
    y[..., 3] = x[..., 3] + x[..., 1]  # height
    return y



ultralytics.utils.ops.segments2boxes(segments)

Il convertit les étiquettes de segments en étiquettes de boîtes, c'est-à-dire (cls, xy1, xy2, ...) en (cls, xywh).

Paramètres :

Nom Type Description Défaut
segments list

liste de segments, chaque segment est une liste de points, chaque point est une liste de coordonnées x, y

requis

Retourne :

Type Description
ndarray

les coordonnées xywh des boîtes de délimitation.

Code source dans ultralytics/utils/ops.py
def segments2boxes(segments):
    """
    It converts segment labels to box labels, i.e. (cls, xy1, xy2, ...) to (cls, xywh)

    Args:
        segments (list): list of segments, each segment is a list of points, each point is a list of x, y coordinates

    Returns:
        (np.ndarray): the xywh coordinates of the bounding boxes.
    """
    boxes = []
    for s in segments:
        x, y = s.T  # segment xy
        boxes.append([x.min(), y.min(), x.max(), y.max()])  # cls, xyxy
    return xyxy2xywh(np.array(boxes))  # cls, xywh



ultralytics.utils.ops.resample_segments(segments, n=1000)

Entre une liste de segments (n,2) et renvoie une liste de segments (n,2) échantillonnés à n points chacun.

Paramètres :

Nom Type Description Défaut
segments list

une liste de tableaux (n,2), où n est le nombre de points dans le segment.

requis
n int

nombre de points pour rééchantillonner le segment. La valeur par défaut est 1000

1000

Retourne :

Nom Type Description
segments list

les segments rééchantillonnés.

Code source dans ultralytics/utils/ops.py
def resample_segments(segments, n=1000):
    """
    Inputs a list of segments (n,2) and returns a list of segments (n,2) up-sampled to n points each.

    Args:
        segments (list): a list of (n,2) arrays, where n is the number of points in the segment.
        n (int): number of points to resample the segment to. Defaults to 1000

    Returns:
        segments (list): the resampled segments.
    """
    for i, s in enumerate(segments):
        s = np.concatenate((s, s[0:1, :]), axis=0)
        x = np.linspace(0, len(s) - 1, n)
        xp = np.arange(len(s))
        segments[i] = (
            np.concatenate([np.interp(x, xp, s[:, i]) for i in range(2)], dtype=np.float32).reshape(2, -1).T
        )  # segment xy
    return segments



ultralytics.utils.ops.crop_mask(masks, boxes)

Elle prend un masque et une boîte de délimitation, et renvoie un masque qui est recadré par rapport à la boîte de délimitation.

Paramètres :

Nom Type Description Défaut
masks Tensor

[n, h, w] tensor de masques

requis
boxes Tensor

[n, 4] tensor des coordonnées de la bbox sous forme de points relatifs

requis

Retourne :

Type Description
Tensor

Les masques sont recadrés dans la boîte de délimitation.

Code source dans ultralytics/utils/ops.py
def crop_mask(masks, boxes):
    """
    It takes a mask and a bounding box, and returns a mask that is cropped to the bounding box.

    Args:
        masks (torch.Tensor): [n, h, w] tensor of masks
        boxes (torch.Tensor): [n, 4] tensor of bbox coordinates in relative point form

    Returns:
        (torch.Tensor): The masks are being cropped to the bounding box.
    """
    _, h, w = masks.shape
    x1, y1, x2, y2 = torch.chunk(boxes[:, :, None], 4, 1)  # x1 shape(n,1,1)
    r = torch.arange(w, device=masks.device, dtype=x1.dtype)[None, None, :]  # rows shape(1,1,w)
    c = torch.arange(h, device=masks.device, dtype=x1.dtype)[None, :, None]  # cols shape(1,h,1)

    return masks * ((r >= x1) * (r < x2) * (c >= y1) * (c < y2))



ultralytics.utils.ops.process_mask_upsample(protos, masks_in, bboxes, shape)

Prend la sortie de la tête de masque et applique le masque aux boîtes de délimitation. Cela produit des masques de meilleure qualité mais est plus lent.

Paramètres :

Nom Type Description Défaut
protos Tensor

[mask_dim, mask_h, mask_w]

requis
masks_in Tensor

[n, mask_dim], n est le nombre de masques après nms

requis
bboxes Tensor

[n, 4], n est le nombre de masques après nms

requis
shape tuple

la taille de l'image d'entrée (h,w)

requis

Retourne :

Type Description
Tensor

Les masques suréchantillonnés.

Code source dans ultralytics/utils/ops.py
def process_mask_upsample(protos, masks_in, bboxes, shape):
    """
    Takes the output of the mask head, and applies the mask to the bounding boxes. This produces masks of higher quality
    but is slower.

    Args:
        protos (torch.Tensor): [mask_dim, mask_h, mask_w]
        masks_in (torch.Tensor): [n, mask_dim], n is number of masks after nms
        bboxes (torch.Tensor): [n, 4], n is number of masks after nms
        shape (tuple): the size of the input image (h,w)

    Returns:
        (torch.Tensor): The upsampled masks.
    """
    c, mh, mw = protos.shape  # CHW
    masks = (masks_in @ protos.float().view(c, -1)).sigmoid().view(-1, mh, mw)
    masks = F.interpolate(masks[None], shape, mode="bilinear", align_corners=False)[0]  # CHW
    masks = crop_mask(masks, bboxes)  # CHW
    return masks.gt_(0.5)



ultralytics.utils.ops.process_mask(protos, masks_in, bboxes, shape, upsample=False)

Applique des masques aux boîtes de délimitation en utilisant la sortie de la tête de masque.

Paramètres :

Nom Type Description Défaut
protos Tensor

Un tensor de la forme [mask_dim, mask_h, mask_w].

requis
masks_in Tensor

Un tensor de la forme [n, mask_dim], où n est le nombre de masques après NMS.

requis
bboxes Tensor

Un tensor de forme [n, 4], où n est le nombre de masques après NMS.

requis
shape tuple

Un tuple d'entiers représentant la taille de l'image d'entrée au format (h, w).

requis
upsample bool

Un drapeau indiquant s'il faut suréchantillonner le masque à la taille de l'image d'origine. La valeur par défaut est False.

False

Retourne :

Type Description
Tensor

Un masque binaire tensor de forme [n, h, w], où n est le nombre de masques après NMS, et h et w sont la hauteur et la largeur de l'image d'entrée. Le masque est appliqué aux boîtes de délimitation.

Code source dans ultralytics/utils/ops.py
def process_mask(protos, masks_in, bboxes, shape, upsample=False):
    """
    Apply masks to bounding boxes using the output of the mask head.

    Args:
        protos (torch.Tensor): A tensor of shape [mask_dim, mask_h, mask_w].
        masks_in (torch.Tensor): A tensor of shape [n, mask_dim], where n is the number of masks after NMS.
        bboxes (torch.Tensor): A tensor of shape [n, 4], where n is the number of masks after NMS.
        shape (tuple): A tuple of integers representing the size of the input image in the format (h, w).
        upsample (bool): A flag to indicate whether to upsample the mask to the original image size. Default is False.

    Returns:
        (torch.Tensor): A binary mask tensor of shape [n, h, w], where n is the number of masks after NMS, and h and w
            are the height and width of the input image. The mask is applied to the bounding boxes.
    """

    c, mh, mw = protos.shape  # CHW
    ih, iw = shape
    masks = (masks_in @ protos.float().view(c, -1)).sigmoid().view(-1, mh, mw)  # CHW
    width_ratio = mw / iw
    height_ratio = mh / ih

    downsampled_bboxes = bboxes.clone()
    downsampled_bboxes[:, 0] *= width_ratio
    downsampled_bboxes[:, 2] *= width_ratio
    downsampled_bboxes[:, 3] *= height_ratio
    downsampled_bboxes[:, 1] *= height_ratio

    masks = crop_mask(masks, downsampled_bboxes)  # CHW
    if upsample:
        masks = F.interpolate(masks[None], shape, mode="bilinear", align_corners=False)[0]  # CHW
    return masks.gt_(0.5)



ultralytics.utils.ops.process_mask_native(protos, masks_in, bboxes, shape)

Il prend la sortie de la tête de masque et la recadre après un suréchantillonnage dans les boîtes de délimitation.

Paramètres :

Nom Type Description Défaut
protos Tensor

[mask_dim, mask_h, mask_w]

requis
masks_in Tensor

[n, mask_dim], n est le nombre de masques après nms

requis
bboxes Tensor

[n, 4], n est le nombre de masques après nms

requis
shape tuple

la taille de l'image d'entrée (h,w)

requis

Retourne :

Nom Type Description
masks Tensor

Les masques retournés ont les dimensions [h, w, n]

Code source dans ultralytics/utils/ops.py
def process_mask_native(protos, masks_in, bboxes, shape):
    """
    It takes the output of the mask head, and crops it after upsampling to the bounding boxes.

    Args:
        protos (torch.Tensor): [mask_dim, mask_h, mask_w]
        masks_in (torch.Tensor): [n, mask_dim], n is number of masks after nms
        bboxes (torch.Tensor): [n, 4], n is number of masks after nms
        shape (tuple): the size of the input image (h,w)

    Returns:
        masks (torch.Tensor): The returned masks with dimensions [h, w, n]
    """
    c, mh, mw = protos.shape  # CHW
    masks = (masks_in @ protos.float().view(c, -1)).sigmoid().view(-1, mh, mw)
    masks = scale_masks(masks[None], shape)[0]  # CHW
    masks = crop_mask(masks, bboxes)  # CHW
    return masks.gt_(0.5)



ultralytics.utils.ops.scale_masks(masks, shape, padding=True)

Rééchelle les masques de segment en fonction de la forme.

Paramètres :

Nom Type Description Défaut
masks Tensor

(N, C, H, W).

requis
shape tuple

Hauteur et largeur.

requis
padding bool

Si c'est vrai, on suppose que les boîtes sont basées sur l'image augmentée par le style yolo . Si False, on procède à un redimensionnement.

True
Code source dans ultralytics/utils/ops.py
def scale_masks(masks, shape, padding=True):
    """
    Rescale segment masks to shape.

    Args:
        masks (torch.Tensor): (N, C, H, W).
        shape (tuple): Height and width.
        padding (bool): If True, assuming the boxes is based on image augmented by yolo style. If False then do regular
            rescaling.
    """
    mh, mw = masks.shape[2:]
    gain = min(mh / shape[0], mw / shape[1])  # gain  = old / new
    pad = [mw - shape[1] * gain, mh - shape[0] * gain]  # wh padding
    if padding:
        pad[0] /= 2
        pad[1] /= 2
    top, left = (int(pad[1]), int(pad[0])) if padding else (0, 0)  # y, x
    bottom, right = (int(mh - pad[1]), int(mw - pad[0]))
    masks = masks[..., top:bottom, left:right]

    masks = F.interpolate(masks, shape, mode="bilinear", align_corners=False)  # NCHW
    return masks



ultralytics.utils.ops.scale_coords(img1_shape, coords, img0_shape, ratio_pad=None, normalize=False, padding=True)

Rééchelonne les coordonnées du segment (xy) de img1_shape à img0_shape.

Paramètres :

Nom Type Description Défaut
img1_shape tuple

La forme de l'image d'où proviennent les coordonnées.

requis
coords Tensor

les coordonnées à mettre à l'échelle de la forme n,2.

requis
img0_shape tuple

la forme de l'image à laquelle la segmentation est appliquée.

requis
ratio_pad tuple

le rapport entre la taille de l'image et la taille de l'image rembourrée.

None
normalize bool

Si True, les coordonnées seront normalisées sur l'intervalle [0, 1]. La valeur par défaut est False.

False
padding bool

Si c'est vrai, on suppose que les boîtes sont basées sur l'image augmentée par le style yolo . Si False, on procède à un redimensionnement.

True

Retourne :

Nom Type Description
coords Tensor

Les coordonnées mises à l'échelle.

Code source dans ultralytics/utils/ops.py
def scale_coords(img1_shape, coords, img0_shape, ratio_pad=None, normalize=False, padding=True):
    """
    Rescale segment coordinates (xy) from img1_shape to img0_shape.

    Args:
        img1_shape (tuple): The shape of the image that the coords are from.
        coords (torch.Tensor): the coords to be scaled of shape n,2.
        img0_shape (tuple): the shape of the image that the segmentation is being applied to.
        ratio_pad (tuple): the ratio of the image size to the padded image size.
        normalize (bool): If True, the coordinates will be normalized to the range [0, 1]. Defaults to False.
        padding (bool): If True, assuming the boxes is based on image augmented by yolo style. If False then do regular
            rescaling.

    Returns:
        coords (torch.Tensor): The scaled coordinates.
    """
    if ratio_pad is None:  # calculate from img0_shape
        gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1])  # gain  = old / new
        pad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2  # wh padding
    else:
        gain = ratio_pad[0][0]
        pad = ratio_pad[1]

    if padding:
        coords[..., 0] -= pad[0]  # x padding
        coords[..., 1] -= pad[1]  # y padding
    coords[..., 0] /= gain
    coords[..., 1] /= gain
    coords = clip_coords(coords, img0_shape)
    if normalize:
        coords[..., 0] /= img0_shape[1]  # width
        coords[..., 1] /= img0_shape[0]  # height
    return coords



ultralytics.utils.ops.regularize_rboxes(rboxes)

Régularise les boîtes tournantes dans l'intervalle [0, pi/2].

Paramètres :

Nom Type Description Défaut
rboxes Tensor

(N, 5), xywhr.

requis

Retourne :

Type Description
Tensor

Les boîtes régularisées.

Code source dans ultralytics/utils/ops.py
def regularize_rboxes(rboxes):
    """
    Regularize rotated boxes in range [0, pi/2].

    Args:
        rboxes (torch.Tensor): (N, 5), xywhr.

    Returns:
        (torch.Tensor): The regularized boxes.
    """
    x, y, w, h, t = rboxes.unbind(dim=-1)
    # Swap edge and angle if h >= w
    w_ = torch.where(w > h, w, h)
    h_ = torch.where(w > h, h, w)
    t = torch.where(w > h, t, t + math.pi / 2) % math.pi
    return torch.stack([x, y, w_, h_, t], dim=-1)  # regularized boxes



ultralytics.utils.ops.masks2segments(masks, strategy='largest')

Elle prend une liste de masques (n,h,w) et renvoie une liste de segments (n,xy).

Paramètres :

Nom Type Description Défaut
masks Tensor

la sortie du modèle, qui est une tensor de la forme (batch_size, 160, 160)

requis
strategy str

'concat' ou 'largest'. La valeur par défaut est la plus grande

'largest'

Retourne :

Nom Type Description
segments List

liste des masques de segment

Code source dans ultralytics/utils/ops.py
def masks2segments(masks, strategy="largest"):
    """
    It takes a list of masks(n,h,w) and returns a list of segments(n,xy)

    Args:
        masks (torch.Tensor): the output of the model, which is a tensor of shape (batch_size, 160, 160)
        strategy (str): 'concat' or 'largest'. Defaults to largest

    Returns:
        segments (List): list of segment masks
    """
    segments = []
    for x in masks.int().cpu().numpy().astype("uint8"):
        c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
        if c:
            if strategy == "concat":  # concatenate all segments
                c = np.concatenate([x.reshape(-1, 2) for x in c])
            elif strategy == "largest":  # select largest segment
                c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
        else:
            c = np.zeros((0, 2))  # no segments found
        segments.append(c.astype("float32"))
    return segments



ultralytics.utils.ops.convert_torch2numpy_batch(batch)

Convertit un lot de tenseurs FP32 torch (0.0-1.0) en un tableau NumPy uint8 (0-255), en passant de la disposition BCHW à la disposition BHWC.

Paramètres :

Nom Type Description Défaut
batch Tensor

Entrée tensor lot de formes (Batch, Channels, Height, Width) et dtype torch.float32.

requis

Retourne :

Type Description
ndarray

Sortie d'un lot de tableaux NumPy de forme (lot, hauteur, largeur, canaux) et de type uint8.

Code source dans ultralytics/utils/ops.py
def convert_torch2numpy_batch(batch: torch.Tensor) -> np.ndarray:
    """
    Convert a batch of FP32 torch tensors (0.0-1.0) to a NumPy uint8 array (0-255), changing from BCHW to BHWC layout.

    Args:
        batch (torch.Tensor): Input tensor batch of shape (Batch, Channels, Height, Width) and dtype torch.float32.

    Returns:
        (np.ndarray): Output NumPy array batch of shape (Batch, Height, Width, Channels) and dtype uint8.
    """
    return (batch.permute(0, 2, 3, 1).contiguous() * 255).clamp(0, 255).to(torch.uint8).cpu().numpy()



ultralytics.utils.ops.clean_str(s)

Nettoie une chaîne de caractères en remplaçant les caractères spéciaux par des traits de soulignement _

Paramètres :

Nom Type Description Défaut
s str

une chaîne dont les caractères spéciaux doivent être remplacés

requis

Retourne :

Type Description
str

une chaîne dont les caractères spéciaux sont remplacés par un trait de soulignement _

Code source dans ultralytics/utils/ops.py
def clean_str(s):
    """
    Cleans a string by replacing special characters with underscore _

    Args:
        s (str): a string needing special characters replaced

    Returns:
        (str): a string with special characters replaced by an underscore _
    """
    return re.sub(pattern="[|@#!¡·$€%&()=?¿^*;:,¨´><+]", repl="_", string=s)





Créé le 2023-11-12, Mis à jour le 2024-05-08
Auteurs : Burhan-Q (1), Laughing-q (1), glenn-jocher (4)