Vai al contenuto

Riferimento per ultralytics/utils/ops.py

Nota

Questo file è disponibile all'indirizzo https://github.com/ultralytics/ ultralytics/blob/main/ ultralytics/utils/ops .py. Se noti un problema, contribuisci a risolverlo inviando una Pull Request 🛠️. Grazie 🙏!



ultralytics.utils.ops.Profile

Basi: ContextDecorator

YOLOv8 Classe Profilo. Utilizzala come decoratore con @Profile() o come gestore del contesto con 'with Profile():'.

Esempio
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"
Codice sorgente in 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__()

Orario di inizio.

Codice sorgente in ultralytics/utils/ops.py
def __enter__(self):
    """Start timing."""
    self.start = self.time()
    return self

__exit__(type, value, traceback)

Interrompi la tempistica.

Codice sorgente in 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)

Inizializza la classe Profilo.

Parametri:

Nome Tipo Descrizione Predefinito
t float

Tempo iniziale. Il valore predefinito è 0,0.

0.0
device device

Dispositivi utilizzati per l'inferenza del modello. Il valore predefinito è Nessuno (cpu).

None
Codice sorgente in 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__()

Restituisce una stringa leggibile dall'uomo che rappresenta il tempo trascorso accumulato nel profiler.

Codice sorgente in 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()

Ottieni l'ora corrente.

Codice sorgente in 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)

Convertire 1 etichetta di segmento in 1 etichetta di casella, applicando il vincolo dell'immagine interna, cioè (xy1, xy2, ...) in (xyxy).

Parametri:

Nome Tipo Descrizione Predefinito
segment Tensor

l'etichetta del segmento

richiesto
width int

la larghezza dell'immagine. Il valore predefinito è 640

640
height int

L'altezza dell'immagine. Valore predefinito: 640

640

Restituzione:

Tipo Descrizione
ndarray

i valori x e y minimi e massimi del segmento.

Codice sorgente in 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)

Ridimensiona i riquadri di delimitazione (nel formato xyxy per impostazione predefinita) dalla forma dell'immagine in cui sono stati originariamente specificati (img1_shape) alla forma di un'immagine diversa (img0_shape). (img1_shape) alla forma di un'altra immagine (img0_shape).

Parametri:

Nome Tipo Descrizione Predefinito
img1_shape tuple

La forma dell'immagine a cui si riferiscono i riquadri di delimitazione, nel formato (altezza, larghezza).

richiesto
boxes Tensor

le caselle di delimitazione degli oggetti nell'immagine, nel formato (x1, y1, x2, y2)

richiesto
img0_shape tuple

la forma dell'immagine di destinazione, nel formato (altezza, larghezza).

richiesto
ratio_pad tuple

una tupla di (ratio, pad) per scalare le caselle. Se non viene fornita, il rapporto e il blocco verranno calcolati in base alla differenza di dimensioni tra le due immagini.

None
padding bool

Se True, assume che le caselle siano basate sull'immagine aumentata dallo stile yolo . Se Falso, allora esegui il normale ridimensionamento.

True
xywh bool

Il formato della casella è xywh o no, default=False.

False

Restituzione:

Nome Tipo Descrizione
boxes Tensor

I riquadri di delimitazione in scala, nel formato di (x1, y1, x2, y2)

Codice sorgente in 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)

Restituisce il numero più vicino che è divisibile per il divisore dato.

Parametri:

Nome Tipo Descrizione Predefinito
x int

Il numero da rendere divisibile.

richiesto
divisor int | Tensor

Il divisore.

richiesto

Restituzione:

Tipo Descrizione
int

Il numero più vicino divisibile per il divisore.

Codice sorgente in 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 per obbs, alimentato da probiou e fast-nms.

Parametri:

Nome Tipo Descrizione Predefinito
boxes Tensor

(N, 5), xywhr.

richiesto
scores Tensor

(N, ).

richiesto
threshold float

Soglia IoU.

0.45

Restituzione:

Codice sorgente in 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)

Esegui la soppressione non massimale (NMS) su un insieme di scatole, con il supporto di maschere ed etichette multiple per scatola.

Parametri:

Nome Tipo Descrizione Predefinito
prediction Tensor

Un tensor di forma (batch_size, num_classes + 4 + num_masks, num_boxes) contenente le caselle, le classi e le maschere previste. Il file tensor deve essere nel formato prodotto da un modello, come ad esempio YOLO.

richiesto
conf_thres float

La soglia di fiducia al di sotto della quale le caselle saranno filtrate. I valori validi sono compresi tra 0,0 e 1,0.

0.25
iou_thres float

La soglia IoU al di sotto della quale le caselle saranno filtrate durante l'NMS. I valori validi sono compresi tra 0.0 e 1.0.

0.45
classes List[int]

Un elenco di indici di classe da considerare. Se Nessuno, verranno considerate tutte le classi.

None
agnostic bool

Se Vero, il modello è agnostico rispetto al numero di classi e tutte le classi saranno considerate come una sola. saranno considerate come un'unica classe.

False
multi_label bool

Se Vero, ogni casella può avere più etichette.

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

Un elenco di liste, dove ogni lista interna contiene le etichette apriori per una determinata immagine. L'elenco dovrebbe essere nel formato prodotto da un dataloader, in cui ogni etichetta è una tupla di (class_index, x1, y1, x2, y2).

()
max_det int

Il numero massimo di caselle da conservare dopo l'NMS.

300
nc int

Il numero di classi prodotte dal modello. Tutti gli indici successivi a questo saranno considerati maschere.

0
max_time_img float

Il tempo massimo (secondi) per l'elaborazione di un'immagine.

0.05
max_nms int

Il numero massimo di caselle in torchvision.ops.nms().

30000
max_wh int

La larghezza e l'altezza massima del riquadro in pixel.

7680
in_place bool

Se è vero, la previsione di ingresso tensor verrà modificata sul posto.

True

Restituzione:

Tipo Descrizione
List[Tensor]

Un elenco di lunghezza lotto_dimensioni, in cui ogni elemento è un tensor di (num_boxes, 6 + num_masks) contenente le scatole conservate, con le colonne (x1, y1, x2, y2, fiducia, classe, maschera1, maschera2, ...).

Codice sorgente in 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)

Prende un elenco di rettangoli di selezione e una forma (altezza, larghezza) e ritaglia i rettangoli di selezione alla forma.

Parametri:

Nome Tipo Descrizione Predefinito
boxes Tensor

le caselle di delimitazione da ritagliare

richiesto
shape tuple

la forma dell'immagine

richiesto

Restituzione:

Tipo Descrizione
Tensor | ndarray

Scatole tagliate

Codice sorgente in 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)

Appunta le coordinate delle linee ai confini dell'immagine.

Parametri:

Nome Tipo Descrizione Predefinito
coords Tensor | ndarray

Un elenco di coordinate di linea.

richiesto
shape tuple

Una tupla di numeri interi che rappresentano le dimensioni dell'immagine nel formato (altezza, larghezza).

richiesto

Restituzione:

Tipo Descrizione
Tensor | ndarray

Coordinate ritagliate

Codice sorgente in 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)

Prende una maschera e la ridimensiona alle dimensioni dell'immagine originale.

Parametri:

Nome Tipo Descrizione Predefinito
masks ndarray

maschere/immagini ridimensionate e imbottite, [h, w, num]/[h, w, 3].

richiesto
im0_shape tuple

la forma dell'immagine originale

richiesto
ratio_pad tuple

il rapporto tra il padding e l'immagine originale.

None

Restituzione:

Nome Tipo Descrizione
masks Tensor

Le maschere che vengono restituite.

Codice sorgente in 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)

Converte le coordinate del rettangolo di selezione dal formato (x1, y1, x2, y2) al formato (x, y, larghezza, altezza) dove (x1, y1) è l'angolo in alto a sinistra e (x2, y2) è l'angolo in basso a destra. angolo in alto a sinistra e (x2, y2) è l'angolo in basso a destra.

Parametri:

Nome Tipo Descrizione Predefinito
x ndarray | Tensor

Le coordinate del rettangolo di selezione in ingresso nel formato (x1, y1, x2, y2).

richiesto

Restituzione:

Nome Tipo Descrizione
y ndarray | Tensor

Le coordinate del rettangolo di selezione in formato (x, y, larghezza, altezza).

Codice sorgente in 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)

Converte le coordinate del rettangolo di selezione dal formato (x, y, larghezza, altezza) al formato (x1, y1, x2, y2) dove (x1, y1) è l'angolo in alto a sinistra e (x2, y2) è l'angolo in basso a destra. angolo in alto a sinistra e (x2, y2) è l'angolo in basso a destra.

Parametri:

Nome Tipo Descrizione Predefinito
x ndarray | Tensor

Le coordinate del rettangolo di selezione in ingresso nel formato (x, y, larghezza, altezza).

richiesto

Restituzione:

Nome Tipo Descrizione
y ndarray | Tensor

Le coordinate del rettangolo di selezione nel formato (x1, y1, x2, y2).

Codice sorgente in 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)

Converte le coordinate normalizzate del rettangolo di selezione in coordinate pixel.

Parametri:

Nome Tipo Descrizione Predefinito
x ndarray | Tensor

Le coordinate del rettangolo di selezione.

richiesto
w int

Larghezza dell'immagine. Valore predefinito: 640

640
h int

Altezza dell'immagine. Valore predefinito: 640

640
padw int

Larghezza del padding. Il valore predefinito è 0

0
padh int

Altezza dell'imbottitura. Il valore predefinito è 0

0

Restituisce: y (np.ndarray | torch.Tensor): Le coordinate del rettangolo di selezione nel formato [x1, y1, x2, y2] dove x1,y1 è l'angolo in alto a sinistra, x2,y2 è l'angolo in basso a destra del rettangolo di selezione.

Codice sorgente in 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)

Converte le coordinate del rettangolo di selezione dal formato (x1, y1, x2, y2) al formato (x, y, larghezza, altezza, normalizzato). x, y, larghezza e altezza sono normalizzate alle dimensioni dell'immagine.

Parametri:

Nome Tipo Descrizione Predefinito
x ndarray | Tensor

Le coordinate del rettangolo di selezione in ingresso nel formato (x1, y1, x2, y2).

richiesto
w int

La larghezza dell'immagine. Valore predefinito: 640

640
h int

L'altezza dell'immagine. Valore predefinito: 640

640
clip bool

Se Vero, i riquadri saranno ritagliati ai confini dell'immagine. Per impostazione predefinita è Falso

False
eps float

Il valore minimo della larghezza e dell'altezza del riquadro. Il valore predefinito è 0,0

0.0

Restituzione:

Nome Tipo Descrizione
y ndarray | Tensor

Le coordinate del rettangolo di selezione in formato (x, y, larghezza, altezza, normalizzato)

Codice sorgente in 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)

Converte il formato del rettangolo di selezione da [x, y, w, h] a [x1, y1, w, h], dove x1, y1 sono le coordinate in alto a sinistra.

Parametri:

Nome Tipo Descrizione Predefinito
x ndarray | Tensor

L'input tensor con le coordinate del rettangolo di selezione nel formato xywh

richiesto

Restituzione:

Nome Tipo Descrizione
y ndarray | Tensor

Le coordinate del rettangolo di selezione nel formato xyltwh

Codice sorgente in 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)

Converte nx4 caselle di delimitazione da [x1, y1, x2, y2] a [x1, y1, w, h], dove xy1=in alto a sinistra, xy2=in basso a destra.

Parametri:

Nome Tipo Descrizione Predefinito
x ndarray | Tensor

L'input tensor con le coordinate delle caselle di delimitazione nel formato xyxy

richiesto

Restituzione:

Nome Tipo Descrizione
y ndarray | Tensor

Le coordinate del rettangolo di selezione nel formato xyltwh.

Codice sorgente in 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)

Converte nx4 caselle da [x1, y1, w, h] a [x, y, w, h] dove xy1=alto a sinistra, xy=centro.

Parametri:

Nome Tipo Descrizione Predefinito
x Tensor

l'ingresso tensor

richiesto

Restituzione:

Nome Tipo Descrizione
y ndarray | Tensor

Le coordinate del rettangolo di selezione nel formato xywh.

Codice sorgente in 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)

Converte le Oriented Bounding Boxes (OBB) da [xy1, xy2, xy3, xy4] a [xywh, rotation]. I valori di rotazione sono previsti in gradi da 0 a 90.

Parametri:

Nome Tipo Descrizione Predefinito
corners ndarray | Tensor

Angoli di ingresso di forma (n, 8).

richiesto

Restituzione:

Tipo Descrizione
ndarray | Tensor

Dati convertiti nel formato [cx, cy, w, h, rotazione] della forma (n, 5).

Codice sorgente in 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)

Converte le Oriented Bounding Boxes (OBB) da [xywh, rotation] a [xy1, xy2, xy3, xy4]. I valori di rotazione devono essere espressi in gradi da 0 a 90.

Parametri:

Nome Tipo Descrizione Predefinito
rboxes ndarray | Tensor

Caselle in formato [cx, cy, w, h, rotazione] di forma (n, 5) o (b, n, 5).

richiesto

Restituzione:

Tipo Descrizione
ndarray | Tensor

Punti d'angolo convertiti di forma (n, 4, 2) o (b, n, 4, 2).

Codice sorgente in 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)

Converte il riquadro di delimitazione da [x1, y1, w, h] a [x1, y1, x2, y2] dove xy1=in alto a sinistra, xy2=in basso a destra.

Parametri:

Nome Tipo Descrizione Predefinito
x ndarray | Tensor

l'immagine in ingresso

richiesto

Restituzione:

Nome Tipo Descrizione
y ndarray | Tensor

le coordinate xyxy delle caselle di delimitazione.

Codice sorgente in 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)

Converte le etichette dei segmenti in etichette delle caselle, cioè (cls, xy1, xy2, ...) in (cls, xywh)

Parametri:

Nome Tipo Descrizione Predefinito
segments list

elenco di segmenti, ogni segmento è un elenco di punti, ogni punto è un elenco di coordinate x, y

richiesto

Restituzione:

Tipo Descrizione
ndarray

le coordinate xywh delle caselle di delimitazione.

Codice sorgente in 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)

Inserisce un elenco di segmenti (n,2) e restituisce un elenco di segmenti (n,2) campionati a n punti ciascuno.

Parametri:

Nome Tipo Descrizione Predefinito
segments list

un elenco di array (n,2), dove n è il numero di punti del segmento.

richiesto
n int

numero di punti a cui ricampionare il segmento. Per impostazione predefinita è 1000

1000

Restituzione:

Nome Tipo Descrizione
segments list

i segmenti ricampionati.

Codice sorgente in 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)

Prende una maschera e un rettangolo di selezione e restituisce una maschera ritagliata sul rettangolo di selezione.

Parametri:

Nome Tipo Descrizione Predefinito
masks Tensor

[n, h, w] tensor di maschere

richiesto
boxes Tensor

[n, 4] tensor di coordinate bbox in forma di punto relativo

richiesto

Restituzione:

Tipo Descrizione
Tensor

Le maschere vengono ritagliate in base al riquadro di delimitazione.

Codice sorgente in 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)

Prende l'output della testa della maschera e applica la maschera ai riquadri di delimitazione. Questo produce maschere di qualità superiore ma è più lenta.

Parametri:

Nome Tipo Descrizione Predefinito
protos Tensor

[mask_dim, mask_h, mask_w]

richiesto
masks_in Tensor

[n, mask_dim], n è il numero di maschere dopo nms

richiesto
bboxes Tensor

[n, 4], n è il numero di maschere dopo nms

richiesto
shape tuple

le dimensioni dell'immagine di ingresso (h,w)

richiesto

Restituzione:

Tipo Descrizione
Tensor

Le maschere sovracampionate.

Codice sorgente in 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)

Applica le maschere ai riquadri di delimitazione utilizzando l'output della testa della maschera.

Parametri:

Nome Tipo Descrizione Predefinito
protos Tensor

Un tensor di forma [mask_dim, mask_h, mask_w].

richiesto
masks_in Tensor

Un tensor di forma [n, mask_dim], dove n è il numero di maschere dopo NMS.

richiesto
bboxes Tensor

Un tensor di forma [n, 4], dove n è il numero di maschere dopo l'NMS.

richiesto
shape tuple

Una tupla di numeri interi che rappresenta la dimensione dell'immagine di input nel formato (h, w).

richiesto
upsample bool

Un flag per indicare se campionare la maschera in base alle dimensioni dell'immagine originale. Il valore predefinito è Falso.

False

Restituzione:

Tipo Descrizione
Tensor

Una maschera binaria tensor di forma [n, h, w], dove n è il numero di maschere dopo l'NMS, e h e w sono l'altezza e la larghezza dell'immagine di input. La maschera viene applicata ai riquadri di delimitazione.

Codice sorgente in 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)

Prende l'output della testa della maschera e lo ritaglia dopo il sovracampionamento ai riquadri di delimitazione.

Parametri:

Nome Tipo Descrizione Predefinito
protos Tensor

[mask_dim, mask_h, mask_w]

richiesto
masks_in Tensor

[n, mask_dim], n è il numero di maschere dopo nms

richiesto
bboxes Tensor

[n, 4], n è il numero di maschere dopo nms

richiesto
shape tuple

le dimensioni dell'immagine di ingresso (h,w)

richiesto

Restituzione:

Nome Tipo Descrizione
masks Tensor

Le maschere restituite con dimensioni [h, w, n]

Codice sorgente in 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)

Ridimensiona le maschere di segmento in base alla forma.

Parametri:

Nome Tipo Descrizione Predefinito
masks Tensor

(N, C, H, W).

richiesto
shape tuple

Altezza e larghezza.

richiesto
padding bool

Se True, assume che le caselle siano basate sull'immagine aumentata dallo stile yolo . Se Falso, allora esegui il normale ridimensionamento.

True
Codice sorgente in 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)

Ridimensiona le coordinate del segmento (xy) da img1_shape a img0_shape.

Parametri:

Nome Tipo Descrizione Predefinito
img1_shape tuple

La forma dell'immagine da cui provengono le coordinate.

richiesto
coords Tensor

le coordinate da scalare della forma n,2.

richiesto
img0_shape tuple

la forma dell'immagine a cui viene applicata la segmentazione.

richiesto
ratio_pad tuple

il rapporto tra la dimensione dell'immagine e la dimensione dell'immagine imbottita.

None
normalize bool

Se Vero, le coordinate saranno normalizzate all'intervallo [0, 1]. L'impostazione predefinita è False.

False
padding bool

Se True, assume che le caselle siano basate sull'immagine aumentata dallo stile yolo . Se Falso, allora esegui il normale ridimensionamento.

True

Restituzione:

Nome Tipo Descrizione
coords Tensor

Le coordinate in scala.

Codice sorgente in 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)

Regolarizza le caselle ruotate nell'intervallo [0, pi/2].

Parametri:

Nome Tipo Descrizione Predefinito
rboxes Tensor

(N, 5), xywhr.

richiesto

Restituzione:

Tipo Descrizione
Tensor

Le scatole regolarizzate.

Codice sorgente in 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')

Prende un elenco di maschere(n,h,w) e restituisce un elenco di segmenti(n,xy)

Parametri:

Nome Tipo Descrizione Predefinito
masks Tensor

l'uscita del modello, che è un tensor di forma (batch_size, 160, 160)

richiesto
strategy str

'concat' o 'largest'. Per impostazione predefinita è il più grande

'largest'

Restituzione:

Nome Tipo Descrizione
segments List

elenco delle maschere di segmento

Codice sorgente in 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)

Converte un gruppo di tensori FP32 torch (0,0-1,0) in un array NumPy uint8 (0-255), passando dal layout BCHW a quello BHWC.

Parametri:

Nome Tipo Descrizione Predefinito
batch Tensor

Input tensor batch di forma (Batch, Canali, Altezza, Larghezza) e dtype torch.float32.

richiesto

Restituzione:

Tipo Descrizione
ndarray

Output NumPy array batch di forma (Batch, Height, Width, Channels) e dtype uint8.

Codice sorgente in 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)

Pulisce una stringa sostituendo i caratteri speciali con il carattere di sottolineatura _

Parametri:

Nome Tipo Descrizione Predefinito
s str

una stringa che deve essere sostituita con caratteri speciali

richiesto

Restituzione:

Tipo Descrizione
str

una stringa con caratteri speciali sostituiti da un trattino basso _

Codice sorgente in 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)





Creato 2023-11-12, Aggiornato 2024-01-23
Autori: Ridere-q (1), glenn-jocher (4)