Zum Inhalt springen

Referenz fĂŒr ultralytics/utils/ops.py

Hinweis

Diese Datei ist verfĂŒgbar unter https://github.com/ultralytics/ ultralytics/blob/main/ ultralytics/utils/ops .py. Wenn du ein Problem entdeckst, hilf bitte mit, es zu beheben, indem du einen Pull Request đŸ› ïž einreichst. Vielen Dank 🙏!



ultralytics.utils.ops.Profile

Basen: ContextDecorator

YOLOv8 Profil-Klasse. Verwende sie als Dekorator mit @Profile() oder als Kontextmanager mit 'with Profile():'.

Beispiel
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"
Quellcode 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__()

Startzeitpunkt.

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

__exit__(type, value, traceback)

Stoppzeit.

Quellcode 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)

Initialisiere die Profilklasse.

Parameter:

Name Typ Beschreibung Standard
t float

Anfangszeit. Der Standardwert ist 0,0.

0.0
device device

FĂŒr die Modellinferenz verwendete GerĂ€te. Der Standardwert ist None (cpu).

None
Quellcode 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__()

Gibt einen lesbaren String zurĂŒck, der die aufgelaufene Zeit im Profiler angibt.

Quellcode 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()

Erhalte die aktuelle Zeit.

Quellcode 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)

Konvertiere ein Segment-Label in ein Box-Label und wende dabei die BeschrÀnkung auf das innere Bild an, d.h. (xy1, xy2, ...) in (xyxy).

Parameter:

Name Typ Beschreibung Standard
segment Tensor

die Segmentbezeichnung

erforderlich
width int

die Breite des Bildes. Der Standardwert ist 640

640
height int

Die Höhe des Bildes. Der Standardwert ist 640

640

Retouren:

Typ Beschreibung
ndarray

die minimalen und maximalen x- und y-Werte des Segments.

Quellcode 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)

Skaliert die Begrenzungsrahmen (standardmĂ€ĂŸig im Format xyxy) von der Form des Bildes, in dem sie ursprĂŒnglich (img1_shape) auf die Form eines anderen Bildes (img0_shape).

Parameter:

Name Typ Beschreibung Standard
img1_shape tuple

Die Form des Bildes, fĂŒr das die Begrenzungsrahmen bestimmt sind, im Format (Höhe, Breite).

erforderlich
boxes Tensor

die Begrenzungsrahmen der Objekte im Bild im Format (x1, y1, x2, y2)

erforderlich
img0_shape tuple

die Form des Zielbildes, im Format (Höhe, Breite).

erforderlich
ratio_pad tuple

ein Tupel aus (ratio, pad) fĂŒr die Skalierung der Boxen. Wenn nichts angegeben wird, werden VerhĂ€ltnis und Abstand auf der Grundlage des GrĂ¶ĂŸenunterschieds zwischen den beiden Bildern berechnet.

None
padding bool

Wenn True, wird angenommen, dass die Boxen auf einem Bild basieren, das durch den yolo Stil erweitert wurde. Wenn False, dann erfolgt eine normale neu skaliert.

True
xywh bool

Das Boxformat ist xywh oder nicht, Standard=False.

False

Retouren:

Name Typ Beschreibung
boxes Tensor

Die skalierten Boundingboxen im Format (x1, y1, x2, y2)

Quellcode 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)

Gibt die nĂ€chstgelegene Zahl zurĂŒck, die durch den angegebenen Divisor teilbar ist.

Parameter:

Name Typ Beschreibung Standard
x int

Die Zahl, die teilbar gemacht werden muss.

erforderlich
divisor int | Tensor

Der Divisor.

erforderlich

Retouren:

Typ Beschreibung
int

Die nÀchstgelegene Zahl, die durch den Divisor teilbar ist.

Quellcode 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 fĂŒr obbs, angetrieben von probiou und fast-nms.

Parameter:

Name Typ Beschreibung Standard
boxes Tensor

(N, 5), xywhr.

erforderlich
scores Tensor

(N, ).

erforderlich
threshold float

IoU-Schwelle.

0.45

Retouren:

Quellcode 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)

FĂŒhre die Nicht-Maximum-UnterdrĂŒckung (NMS) fĂŒr eine Reihe von Boxen durch, mit UnterstĂŒtzung fĂŒr Masken und mehrere Etiketten pro Box.

Parameter:

Name Typ Beschreibung Standard
prediction Tensor

Eine tensor der Form (batch_size, num_classes + 4 + num_masks, num_boxes) mit den vorhergesagten Feldern, Klassen und Masken. Die tensor sollte das Format haben haben, das von einem Modell ausgegeben wird, z. B. YOLO.

erforderlich
conf_thres float

Die Konfidenzschwelle, unterhalb derer die KĂ€stchen herausgefiltert werden. GĂŒltige Werte liegen zwischen 0,0 und 1,0.

0.25
iou_thres float

Der IoU-Schwellenwert, unter dem die Boxen wĂ€hrend der NMS herausgefiltert werden. GĂŒltige Werte liegen zwischen 0,0 und 1,0.

0.45
classes List[int]

Eine Liste der zu berĂŒcksichtigenden Klassenindizes. Wenn Keine, werden alle Klassen berĂŒcksichtigt.

None
agnostic bool

Wenn True, ist das Modell unabhÀngig von der Anzahl der Klassen und alle Klassen werden als eine Klasse betrachtet.

False
multi_label bool

Wenn True, kann jedes Feld mehrere Beschriftungen haben.

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

Eine Liste von Listen, wobei jede innere Liste die Apriori-Beschriftungen fĂŒr ein bestimmtes Bild enthĂ€lt. Die Liste sollte das Format haben haben, wobei jedes Label ein Tupel aus (class_index, x1, y1, x2, y2) ist.

()
max_det int

Die maximale Anzahl der Boxen, die nach NMS behalten werden sollen.

300
nc int

Die Anzahl der Klassen, die das Modell ausgibt. Alle Indizes nach diesem Wert werden als Masken betrachtet.

0
max_time_img float

Die maximale Zeit (Sekunden) fĂŒr die Verarbeitung eines Bildes.

0.05
max_nms int

Die maximale Anzahl von Boxen in torchvision.ops.nms().

30000
max_wh int

Die maximale Breite und Höhe der Box in Pixeln.

7680
in_place bool

Wenn True, wird die Eingabevorhersage tensor an Ort und Stelle geÀndert.

True

Retouren:

Typ Beschreibung
List[Tensor]

Eine Liste der LÀnge batch_size, wobei jedes Element eine tensor der Form (num_boxes, 6 + num_masks) ist, die die gehaltenen Boxen enthÀlt, mit Spalten (x1, y1, x2, y2, confidence, class, mask1, mask2, ...).

Quellcode 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  # number of masks
    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)

Nimmt eine Liste von Begrenzungsrahmen und eine Form (Höhe, Breite) und klammert die Begrenzungsrahmen an die Form.

Parameter:

Name Typ Beschreibung Standard
boxes Tensor

die zu beschneidenden Bounding Boxes

erforderlich
shape tuple

die Form des Bildes

erforderlich

Retouren:

Typ Beschreibung
Tensor | ndarray

Abgeschnittene Kisten

Quellcode 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)

Schneide die Linienkoordinaten an den Bildgrenzen ab.

Parameter:

Name Typ Beschreibung Standard
coords Tensor | ndarray

Eine Liste von Linienkoordinaten.

erforderlich
shape tuple

Ein Tupel aus ganzen Zahlen, die die GrĂ¶ĂŸe des Bildes im Format (Höhe, Breite) angeben.

erforderlich

Retouren:

Typ Beschreibung
Tensor | ndarray

Abgeschnittene Koordinaten

Quellcode 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)

Nimmt eine Maske und passt sie an die ursprĂŒngliche BildgrĂ¶ĂŸe an.

Parameter:

Name Typ Beschreibung Standard
masks ndarray

grĂ¶ĂŸenverĂ€nderte und aufgefĂŒllte Masken/Bilder, [h, w, num]/[h, w, 3].

erforderlich
im0_shape tuple

die ursprĂŒngliche Bildform

erforderlich
ratio_pad tuple

das VerhĂ€ltnis der FĂŒllung zum Originalbild.

None

Retouren:

Name Typ Beschreibung
masks Tensor

Die Masken, die zurĂŒckgegeben werden.

Quellcode 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)

Konvertiert Bounding-Box-Koordinaten vom Format (x1, y1, x2, y2) in das Format (x, y, Breite, Höhe), wobei (x1, y1) die linke obere Ecke und (x2, y2) die rechte untere Ecke ist. linke obere Ecke und (x2, y2) die rechte untere Ecke ist.

Parameter:

Name Typ Beschreibung Standard
x ndarray | Tensor

Die Koordinaten des eingegebenen Begrenzungsrahmens im Format (x1, y1, x2, y2).

erforderlich

Retouren:

Name Typ Beschreibung
y ndarray | Tensor

Die Koordinaten des Begrenzungsrahmens im Format (x, y, Breite, Höhe).

Quellcode 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)

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. Note: ops per 2 channels faster than per channel.

Parameter:

Name Typ Beschreibung Standard
x ndarray | Tensor

Die Koordinaten des eingegebenen Begrenzungsrahmens im Format (x, y, Breite, Höhe).

erforderlich

Retouren:

Name Typ Beschreibung
y ndarray | Tensor

Die Koordinaten des Begrenzungsrahmens im Format (x1, y1, x2, y2).

Quellcode 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. Note: ops per 2 channels faster than per channel.

    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
    xy = x[..., :2]  # centers
    wh = x[..., 2:] / 2  # half width-height
    y[..., :2] = xy - wh  # top left xy
    y[..., 2:] = xy + wh  # bottom right xy
    return y



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

Wandelt normalisierte Bounding-Box-Koordinaten in Pixelkoordinaten um.

Parameter:

Name Typ Beschreibung Standard
x ndarray | Tensor

Die Koordinaten des Begrenzungsrahmens.

erforderlich
w int

Breite des Bildes. Der Standardwert ist 640

640
h int

Höhe des Bildes. Der Standardwert ist 640

640
padw int

AuffĂŒllungsbreite. Standardwert ist 0

0
padh int

Höhe der Polsterung. StandardmĂ€ĂŸig ist 0

0

RĂŒckgabe: y (np.ndarray | torch.Tensor): Die Koordinaten des Begrenzungsrahmens im Format [x1, y1, x2, y2], wobei x1,y1 die linke obere Ecke und x2,y2 die rechte untere Ecke des Begrenzungsrahmens ist.

Quellcode 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)

Konvertiert Bounding-Box-Koordinaten vom Format (x1, y1, x2, y2) in das Format (x, y, Breite, Höhe, normalisiert). x, y, Breite und Höhe werden auf die Bildmaße normiert.

Parameter:

Name Typ Beschreibung Standard
x ndarray | Tensor

Die Koordinaten des eingegebenen Begrenzungsrahmens im Format (x1, y1, x2, y2).

erforderlich
w int

Die Breite des Bildes. Der Standardwert ist 640

640
h int

Die Höhe des Bildes. Der Standardwert ist 640

640
clip bool

Bei True werden die Boxen an den Bildgrenzen abgeschnitten. StandardmĂ€ĂŸig ist False

False
eps float

Der Mindestwert fĂŒr die Breite und Höhe der Box. Standardwert ist 0.0

0.0

Retouren:

Name Typ Beschreibung
y ndarray | Tensor

Die Koordinaten des Begrenzungsrahmens im Format (x, y, Breite, Höhe, normalisiert)

Quellcode 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)

Konvertiere das Format des Begrenzungsrahmens von [x, y, w, h] in [x1, y1, w, h], wobei x1, y1 die Koordinaten oben links sind.

Parameter:

Name Typ Beschreibung Standard
x ndarray | Tensor

Die Eingabe tensor mit den Bounding-Box-Koordinaten im xywh-Format

erforderlich

Retouren:

Name Typ Beschreibung
y ndarray | Tensor

Die Bounding-Box-Koordinaten im Format xyltwh

Quellcode 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)

Konvertiere nx4 Boundingboxen von [x1, y1, x2, y2] nach [x1, y1, w, h], wobei xy1=oben links, xy2=unten rechts ist.

Parameter:

Name Typ Beschreibung Standard
x ndarray | Tensor

Die Eingabe tensor mit den Koordinaten der Boundingboxen im xyxy-Format

erforderlich

Retouren:

Name Typ Beschreibung
y ndarray | Tensor

Die Bounding-Box-Koordinaten im Format xyltwh.

Quellcode 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)

Konvertiere nx4 Boxen von [x1, y1, w, h] nach [x, y, w, h], wobei xy1=oben links, xy=Mitte.

Parameter:

Name Typ Beschreibung Standard
x Tensor

die Eingabe tensor

erforderlich

Retouren:

Name Typ Beschreibung
y ndarray | Tensor

Die Bounding-Box-Koordinaten im xywh-Format.

Quellcode 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(x)

Konvertiere gestapelte Oriented Bounding Boxes (OBB) von [xy1, xy2, xy3, xy4] nach [xywh, Rotation]. Die Werte fĂŒr die Drehung werden in Grad von 0 bis 90 erwartet.

Parameter:

Name Typ Beschreibung Standard
x ndarray | Tensor

Input box corners [xy1, xy2, xy3, xy4] of shape (n, 8).

erforderlich

Retouren:

Typ Beschreibung
ndarray | Tensor

Konvertierte Daten im Format [cx, cy, w, h, rotation] der Form (n, 5).

Quellcode in ultralytics/utils/ops.py
def xyxyxyxy2xywhr(x):
    """
    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:
        x (numpy.ndarray | torch.Tensor): Input box corners [xy1, xy2, xy3, xy4] 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(x, torch.Tensor)
    points = x.cpu().numpy() if is_torch else x
    points = points.reshape(len(x), -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.
        (cx, cy), (w, h), angle = cv2.minAreaRect(pts)
        rboxes.append([cx, cy, w, h, angle / 180 * np.pi])
    return torch.tensor(rboxes, device=x.device, dtype=x.dtype) if is_torch else np.asarray(rboxes)



ultralytics.utils.ops.xywhr2xyxyxyxy(x)

Konvertiere gepackte Oriented Bounding Boxes (OBB) von [xywh, Rotation] in [xy1, xy2, xy3, xy4]. Die Werte fĂŒr die Drehung sollten in Grad von 0 bis 90 angegeben werden.

Parameter:

Name Typ Beschreibung Standard
x ndarray | Tensor

Boxen im Format [cx, cy, w, h, rotation] der Form (n, 5) oder (b, n, 5).

erforderlich

Retouren:

Typ Beschreibung
ndarray | Tensor

Umgewandelte Eckpunkte der Form (n, 4, 2) oder (b, n, 4, 2).

Quellcode in ultralytics/utils/ops.py
def xywhr2xyxyxyxy(x):
    """
    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:
        x (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).
    """
    cos, sin, cat, stack = (
        (torch.cos, torch.sin, torch.cat, torch.stack)
        if isinstance(x, torch.Tensor)
        else (np.cos, np.sin, np.concatenate, np.stack)
    )

    ctr = x[..., :2]
    w, h, angle = (x[..., 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 = cat(vec1, -1)
    vec2 = cat(vec2, -1)
    pt1 = ctr + vec1 + vec2
    pt2 = ctr + vec1 - vec2
    pt3 = ctr - vec1 - vec2
    pt4 = ctr - vec1 + vec2
    return stack([pt1, pt2, pt3, pt4], -2)



ultralytics.utils.ops.ltwh2xyxy(x)

Sie wandelt das Begrenzungsrechteck von [x1, y1, w, h] in [x1, y1, x2, y2] um, wobei xy1=oben links, xy2=unten rechts ist.

Parameter:

Name Typ Beschreibung Standard
x ndarray | Tensor

das Eingangsbild

erforderlich

Retouren:

Name Typ Beschreibung
y ndarray | Tensor

die xyxy-Koordinaten der Boundingboxen.

Quellcode 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)

Sie wandelt Segmentbeschriftungen in Boxbeschriftungen um, d.h. (cls, xy1, xy2, ...) in (cls, xywh)

Parameter:

Name Typ Beschreibung Standard
segments list

Liste von Segmenten, jedes Segment ist eine Liste von Punkten, jeder Punkt ist eine Liste von x, y Koordinaten

erforderlich

Retouren:

Typ Beschreibung
ndarray

die xywh-Koordinaten der Boundingboxen.

Quellcode 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)

Gibt eine Liste von Segmenten (n,2) ein und gibt eine Liste von Segmenten (n,2) zurĂŒck, die jeweils auf n Punkte hochgerechnet wurden.

Parameter:

Name Typ Beschreibung Standard
segments list

eine Liste von (n,2) Arrays, wobei n die Anzahl der Punkte im Segment ist.

erforderlich
n int

Anzahl der Punkte, auf die das Segment neu abgetastet wird. StandardmĂ€ĂŸig sind es 1000

1000

Retouren:

Name Typ Beschreibung
segments list

die neu abgetasteten Segmente.

Quellcode 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)

Sie nimmt eine Maske und einen Begrenzungsrahmen und gibt eine Maske zurĂŒck, die auf den Begrenzungsrahmen zugeschnitten ist.

Parameter:

Name Typ Beschreibung Standard
masks Tensor

[n, h, w] tensor der Masken

erforderlich
boxes Tensor

[n, 4] tensor der bbox-Koordinaten in relativer Punktform

erforderlich

Retouren:

Typ Beschreibung
Tensor

Die Masken werden auf den Begrenzungsrahmen zugeschnitten.

Quellcode 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)

Nimmt die Ausgabe des Maskenkopfs und wendet die Maske auf die Begrenzungsrahmen an. Dies erzeugt Masken von höherer QualitÀt ist aber langsamer.

Parameter:

Name Typ Beschreibung Standard
protos Tensor

[mask_dim, mask_h, mask_w]

erforderlich
masks_in Tensor

[n, mask_dim], n ist die Anzahl der Masken nach nms

erforderlich
bboxes Tensor

[n, 4], n ist die Anzahl der Masken nach nms

erforderlich
shape tuple

die GrĂ¶ĂŸe des Eingangsbildes (h,w)

erforderlich

Retouren:

Typ Beschreibung
Tensor

Die upgesampelten Masken.

Quellcode 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)

Wende Masken auf Begrenzungsrahmen an, indem du die Ausgabe des Maskenkopfes verwendest.

Parameter:

Name Typ Beschreibung Standard
protos Tensor

A tensor der Form [mask_dim, mask_h, mask_w].

erforderlich
masks_in Tensor

Eine tensor der Form [n, mask_dim], wobei n die Anzahl der Masken nach NMS ist.

erforderlich
bboxes Tensor

A tensor der Form [n, 4], wobei n die Anzahl der Masken nach NMS ist.

erforderlich
shape tuple

Ein Tupel aus ganzen Zahlen, das die GrĂ¶ĂŸe des Eingabebildes im Format (h, w) angibt.

erforderlich
upsample bool

Ein Flag, das angibt, ob die Maske auf die ursprĂŒngliche BildgrĂ¶ĂŸe hochgerechnet werden soll. Die Voreinstellung ist False.

False

Retouren:

Typ Beschreibung
Tensor

Eine binÀre Maske tensor der Form [n, h, w], wobei n die Anzahl der Masken nach NMS ist und h und w die Höhe und Breite des Eingangsbildes sind. Die Maske wird auf die Boundingboxen angewendet.

Quellcode 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)

Sie nimmt die Ausgabe des Maskenkopfes und schneidet sie nach dem Upsampling auf die Boundingboxen zu.

Parameter:

Name Typ Beschreibung Standard
protos Tensor

[mask_dim, mask_h, mask_w]

erforderlich
masks_in Tensor

[n, mask_dim], n ist die Anzahl der Masken nach nms

erforderlich
bboxes Tensor

[n, 4], n ist die Anzahl der Masken nach nms

erforderlich
shape tuple

die GrĂ¶ĂŸe des Eingangsbildes (h,w)

erforderlich

Retouren:

Name Typ Beschreibung
masks Tensor

Die zurĂŒckgegebenen Masken mit den Dimensionen [h, w, n]

Quellcode 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)

Skaliere die Segmentmasken auf die Form um.

Parameter:

Name Typ Beschreibung Standard
masks Tensor

(N, C, H, W).

erforderlich
shape tuple

Höhe und Breite.

erforderlich
padding bool

Wenn True, wird angenommen, dass die Boxen auf einem Bild basieren, das durch den yolo Stil erweitert wurde. Wenn False, dann erfolgt eine normale neu skaliert.

True
Quellcode 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)

Skaliere die Segmentkoordinaten (xy) von img1_shape nach img0_shape um.

Parameter:

Name Typ Beschreibung Standard
img1_shape tuple

Die Form des Bildes, aus dem die Koordinaten stammen.

erforderlich
coords Tensor

die zu skalierenden Koordinaten der Form n,2.

erforderlich
img0_shape tuple

die Form des Bildes, auf das die Segmentierung angewendet wird.

erforderlich
ratio_pad tuple

das VerhĂ€ltnis zwischen der BildgrĂ¶ĂŸe und der GrĂ¶ĂŸe des aufgefĂŒllten Bildes.

None
normalize bool

Wenn True, werden die Koordinaten auf den Bereich [0, 1] normalisiert. Der Standardwert ist False.

False
padding bool

Wenn True, wird angenommen, dass die Boxen auf einem Bild basieren, das durch den yolo Stil erweitert wurde. Wenn False, dann erfolgt eine normale neu skaliert.

True

Retouren:

Name Typ Beschreibung
coords Tensor

Die skalierten Koordinaten.

Quellcode 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)

Reguliere gedrehte Boxen im Bereich [0, pi/2].

Parameter:

Name Typ Beschreibung Standard
rboxes Tensor

Input boxes of shape(N, 5) in xywhr format.

erforderlich

Retouren:

Typ Beschreibung
Tensor

Die regulierten Boxen.

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

    Args:
        rboxes (torch.Tensor): Input boxes of shape(N, 5) in xywhr format.

    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')

Sie nimmt eine Liste von Masken(n,h,w) und gibt eine Liste von Segmenten(n,xy) zurĂŒck

Parameter:

Name Typ Beschreibung Standard
masks Tensor

die Ausgabe des Modells, die eine tensor der Form (batch_size, 160, 160) ist

erforderlich
strategy str

'concat' oder 'largest'. StandardmĂ€ĂŸig ist die grĂ¶ĂŸte

'largest'

Retouren:

Name Typ Beschreibung
segments List

Liste der Segmentmasken

Quellcode 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)

Konvertiere einen Stapel FP32 torch Tensoren (0.0-1.0) in ein NumPy uint8 Array (0-255), indem du vom BCHW- zum BHWC-Layout wechselst.

Parameter:

Name Typ Beschreibung Standard
batch Tensor

Eingabe tensor batch of shape (Batch, Channels, Height, Width) und dtype torch.float32.

erforderlich

Retouren:

Typ Beschreibung
ndarray

Ausgabe des NumPy-Arrays batch of shape (Batch, Height, Width, Channels) und dtype uint8.

Quellcode 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)

Bereinigt eine Zeichenkette, indem es Sonderzeichen durch Unterstriche ersetzt _

Parameter:

Name Typ Beschreibung Standard
s str

eine Zeichenfolge, die durch Sonderzeichen ersetzt werden muss

erforderlich

Retouren:

Typ Beschreibung
str

eine Zeichenfolge, bei der Sonderzeichen durch einen Unterstrich ersetzt werden _

Quellcode 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)





Created 2023-11-12, Updated 2024-06-02
Authors: glenn-jocher (6), Burhan-Q (1), Laughing-q (1)