рд╕рд╛рдордЧреНрд░реА рдкрд░ рдЬрд╛рдПрдВ

рдХреЗ рд▓рд┐рдП рд╕рдВрджрд░реНрдн ultralytics/utils/instance.py

рдиреЛрдЯ

рдпрд╣ рдлрд╝рд╛рдЗрд▓ рдпрд╣рд╛рдБ рдЙрдкрд▓рдмреНрдз рд╣реИ https://github.com/ultralytics/ultralytics/рдмреВрдБрдж/рдореБрдЦреНрдп/ultralytics/utils/instance.py рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдпрджрд┐ рдЖрдк рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рджреЗрдЦрддреЗ рд╣реИрдВ рддреЛ рдХреГрдкрдпрд╛ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдХрд╛ рдпреЛрдЧрджрд╛рди рдХрд░рдХреЗ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВ ЁЯЫая╕Пред ЁЯЩП рдзрдиреНрдпрд╡рд╛рдж !



ultralytics.utils.instance.Bboxes

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд░реНрдЧред

рд╡рд░реНрдЧ 'xyxy', 'xywh', рдФрд░ 'ltwh' рдЬреИрд╕реЗ рд╡рд┐рднрд┐рдиреНрди рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдкреНрд░рд╛рд░реВрдкреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдбреЗрдЯрд╛ numpy рд╕рд░рдгрд┐рдпреЛрдВ рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП.

рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо
bboxes ndarray

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдПрдХ 2 рдбреА рд╕реБрдиреНрди рд╕рд░рдгреА рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрддред

format str

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХрд╛ рдлрд╝реЙрд░реНрдореИрдЯ ("xyxy", "xywh", рдпрд╛ "ltwh").

рдиреЛрдЯ

рдпрд╣ рд╡рд░реНрдЧ рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХреЗ рд╕рд╛рдорд╛рдиреНрдпреАрдХрд░рдг рдпрд╛ рдЕрд╕рд╛рдорд╛рдиреНрдпреАрдХрд░рдг рдХреЛ рд╕рдВрднрд╛рд▓рддрд╛ рдирд╣реАрдВ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
class Bboxes:
    """
    A class for handling bounding boxes.

    The class supports various bounding box formats like 'xyxy', 'xywh', and 'ltwh'.
    Bounding box data should be provided in numpy arrays.

    Attributes:
        bboxes (numpy.ndarray): The bounding boxes stored in a 2D numpy array.
        format (str): The format of the bounding boxes ('xyxy', 'xywh', or 'ltwh').

    Note:
        This class does not handle normalization or denormalization of bounding boxes.
    """

    def __init__(self, bboxes, format="xyxy") -> None:
        """Initializes the Bboxes class with bounding box data in a specified format."""
        assert format in _formats, f"Invalid bounding box format: {format}, format must be one of {_formats}"
        bboxes = bboxes[None, :] if bboxes.ndim == 1 else bboxes
        assert bboxes.ndim == 2
        assert bboxes.shape[1] == 4
        self.bboxes = bboxes
        self.format = format
        # self.normalized = normalized

    def convert(self, format):
        """Converts bounding box format from one type to another."""
        assert format in _formats, f"Invalid bounding box format: {format}, format must be one of {_formats}"
        if self.format == format:
            return
        elif self.format == "xyxy":
            func = xyxy2xywh if format == "xywh" else xyxy2ltwh
        elif self.format == "xywh":
            func = xywh2xyxy if format == "xyxy" else xywh2ltwh
        else:
            func = ltwh2xyxy if format == "xyxy" else ltwh2xywh
        self.bboxes = func(self.bboxes)
        self.format = format

    def areas(self):
        """Return box areas."""
        return (
            (self.bboxes[:, 2] - self.bboxes[:, 0]) * (self.bboxes[:, 3] - self.bboxes[:, 1])  # format xyxy
            if self.format == "xyxy"
            else self.bboxes[:, 3] * self.bboxes[:, 2]  # format xywh or ltwh
        )

    # def denormalize(self, w, h):
    #    if not self.normalized:
    #         return
    #     assert (self.bboxes <= 1.0).all()
    #     self.bboxes[:, 0::2] *= w
    #     self.bboxes[:, 1::2] *= h
    #     self.normalized = False
    #
    # def normalize(self, w, h):
    #     if self.normalized:
    #         return
    #     assert (self.bboxes > 1.0).any()
    #     self.bboxes[:, 0::2] /= w
    #     self.bboxes[:, 1::2] /= h
    #     self.normalized = True

    def mul(self, scale):
        """
        Args:
            scale (tuple | list | int): the scale for four coords.
        """
        if isinstance(scale, Number):
            scale = to_4tuple(scale)
        assert isinstance(scale, (tuple, list))
        assert len(scale) == 4
        self.bboxes[:, 0] *= scale[0]
        self.bboxes[:, 1] *= scale[1]
        self.bboxes[:, 2] *= scale[2]
        self.bboxes[:, 3] *= scale[3]

    def add(self, offset):
        """
        Args:
            offset (tuple | list | int): the offset for four coords.
        """
        if isinstance(offset, Number):
            offset = to_4tuple(offset)
        assert isinstance(offset, (tuple, list))
        assert len(offset) == 4
        self.bboxes[:, 0] += offset[0]
        self.bboxes[:, 1] += offset[1]
        self.bboxes[:, 2] += offset[2]
        self.bboxes[:, 3] += offset[3]

    def __len__(self):
        """Return the number of boxes."""
        return len(self.bboxes)

    @classmethod
    def concatenate(cls, boxes_list: List["Bboxes"], axis=0) -> "Bboxes":
        """
        Concatenate a list of Bboxes objects into a single Bboxes object.

        Args:
            boxes_list (List[Bboxes]): A list of Bboxes objects to concatenate.
            axis (int, optional): The axis along which to concatenate the bounding boxes.
                                   Defaults to 0.

        Returns:
            Bboxes: A new Bboxes object containing the concatenated bounding boxes.

        Note:
            The input should be a list or tuple of Bboxes objects.
        """
        assert isinstance(boxes_list, (list, tuple))
        if not boxes_list:
            return cls(np.empty(0))
        assert all(isinstance(box, Bboxes) for box in boxes_list)

        if len(boxes_list) == 1:
            return boxes_list[0]
        return cls(np.concatenate([b.bboxes for b in boxes_list], axis=axis))

    def __getitem__(self, index) -> "Bboxes":
        """
        Retrieve a specific bounding box or a set of bounding boxes using indexing.

        Args:
            index (int, slice, or np.ndarray): The index, slice, or boolean array to select
                                               the desired bounding boxes.

        Returns:
            Bboxes: A new Bboxes object containing the selected bounding boxes.

        Raises:
            AssertionError: If the indexed bounding boxes do not form a 2-dimensional matrix.

        Note:
            When using boolean indexing, make sure to provide a boolean array with the same
            length as the number of bounding boxes.
        """
        if isinstance(index, int):
            return Bboxes(self.bboxes[index].view(1, -1))
        b = self.bboxes[index]
        assert b.ndim == 2, f"Indexing on Bboxes with {index} failed to return a matrix!"
        return Bboxes(b)

__getitem__(index)

рдЕрдиреБрдХреНрд░рдордг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдпрд╛ рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХрд╛ рдПрдХ рд╕реЗрдЯ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

рдкреИрд░рд╛рдореАрдЯрд░:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо рдЪреВрдХ
index int, slice, or np.ndarray

рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП index, slice рдпрд╛ boolean рд╕рд░рдгреА рд╡рд╛рдВрдЫрд┐рдд рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ред

рдЖрд╡рд╢реНрдпрдХ

рджреЗрддрд╛:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо
Bboxes Bboxes

рдПрдХ рдирдпрд╛ Bboxes рдСрдмреНрдЬреЗрдХреНрдЯ рдЬрд┐рд╕рдореЗрдВ рдЪрдпрдирд┐рдд рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рд╣реИрдВред

рдЙрдард╛рддреА:

рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо
AssertionError

рдпрджрд┐ рдЕрдиреБрдХреНрд░рдорд┐рдд рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ 2-рдЖрдпрд╛рдореА рдореИрдЯреНрд░рд┐рдХреНрд╕ рдирд╣реАрдВ рдмрдирд╛рддреЗ рд╣реИрдВред

рдиреЛрдЯ

рдмреВрд▓рд┐рдпрди рдЗрдВрдбреЗрдХреНрд╕рд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдЙрд╕реА рдХреЗ рд╕рд╛рде рдПрдХ рдмреВрд▓рд┐рдпрди рд╕рд░рдгреА рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рд▓рдВрдмрд╛рдИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def __getitem__(self, index) -> "Bboxes":
    """
    Retrieve a specific bounding box or a set of bounding boxes using indexing.

    Args:
        index (int, slice, or np.ndarray): The index, slice, or boolean array to select
                                           the desired bounding boxes.

    Returns:
        Bboxes: A new Bboxes object containing the selected bounding boxes.

    Raises:
        AssertionError: If the indexed bounding boxes do not form a 2-dimensional matrix.

    Note:
        When using boolean indexing, make sure to provide a boolean array with the same
        length as the number of bounding boxes.
    """
    if isinstance(index, int):
        return Bboxes(self.bboxes[index].view(1, -1))
    b = self.bboxes[index]
    assert b.ndim == 2, f"Indexing on Bboxes with {index} failed to return a matrix!"
    return Bboxes(b)

__init__(bboxes, format='xyxy')

рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде Bboxes рд╡рд░реНрдЧ рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def __init__(self, bboxes, format="xyxy") -> None:
    """Initializes the Bboxes class with bounding box data in a specified format."""
    assert format in _formats, f"Invalid bounding box format: {format}, format must be one of {_formats}"
    bboxes = bboxes[None, :] if bboxes.ndim == 1 else bboxes
    assert bboxes.ndim == 2
    assert bboxes.shape[1] == 4
    self.bboxes = bboxes
    self.format = format

__len__()

рдмрдХреНрд╕реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд▓реМрдЯрд╛рдПрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def __len__(self):
    """Return the number of boxes."""
    return len(self.bboxes)

add(offset)

рдкреИрд░рд╛рдореАрдЯрд░:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо рдЪреВрдХ
offset tuple | list | int

рдЪрд╛рд░ рдХреЙрд░реНрдб рдХреЗ рд▓рд┐рдП рдСрдлрд╕реЗрдЯред

рдЖрд╡рд╢реНрдпрдХ
рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def add(self, offset):
    """
    Args:
        offset (tuple | list | int): the offset for four coords.
    """
    if isinstance(offset, Number):
        offset = to_4tuple(offset)
    assert isinstance(offset, (tuple, list))
    assert len(offset) == 4
    self.bboxes[:, 0] += offset[0]
    self.bboxes[:, 1] += offset[1]
    self.bboxes[:, 2] += offset[2]
    self.bboxes[:, 3] += offset[3]

areas()

рд╡рд╛рдкрд╕реА рдмреЙрдХреНрд╕ рдХреНрд╖реЗрддреНрд░ред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def areas(self):
    """Return box areas."""
    return (
        (self.bboxes[:, 2] - self.bboxes[:, 0]) * (self.bboxes[:, 3] - self.bboxes[:, 1])  # format xyxy
        if self.format == "xyxy"
        else self.bboxes[:, 3] * self.bboxes[:, 2]  # format xywh or ltwh
    )

concatenate(boxes_list, axis=0) classmethod

Bboxes рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреА рд╕реВрдЪреА рдХреЛ рдПрдХрд▓ Bboxes рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░реЗрдВред

рдкреИрд░рд╛рдореАрдЯрд░:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо рдЪреВрдХ
boxes_list List[Bboxes]

Bboxes рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХреА рдПрдХ рд╕реВрдЪреАред

рдЖрд╡рд╢реНрдпрдХ
axis int

рдЕрдХреНрд╖ рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╣реИред 0 рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯред

0

рджреЗрддрд╛:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо
Bboxes Bboxes

рдПрдХ рдирдпрд╛ Bboxes рдСрдмреНрдЬреЗрдХреНрдЯ рдЬрд┐рд╕рдореЗрдВ concatenated рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рд╣реИрдВред

рдиреЛрдЯ

рдЗрдирдкреБрдЯ Bboxes рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреА рдПрдХ рд╕реВрдЪреА рдпрд╛ рдЯрдкрд▓ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
@classmethod
def concatenate(cls, boxes_list: List["Bboxes"], axis=0) -> "Bboxes":
    """
    Concatenate a list of Bboxes objects into a single Bboxes object.

    Args:
        boxes_list (List[Bboxes]): A list of Bboxes objects to concatenate.
        axis (int, optional): The axis along which to concatenate the bounding boxes.
                               Defaults to 0.

    Returns:
        Bboxes: A new Bboxes object containing the concatenated bounding boxes.

    Note:
        The input should be a list or tuple of Bboxes objects.
    """
    assert isinstance(boxes_list, (list, tuple))
    if not boxes_list:
        return cls(np.empty(0))
    assert all(isinstance(box, Bboxes) for box in boxes_list)

    if len(boxes_list) == 1:
        return boxes_list[0]
    return cls(np.concatenate([b.bboxes for b in boxes_list], axis=axis))

convert(format)

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рд╕реНрд╡рд░реВрдк рдХреЛ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╕реЗ рджреВрд╕рд░реЗ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рдХрдирд╡рд░реНрдЯ рдХрд░рддрд╛ рд╣реИ.

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def convert(self, format):
    """Converts bounding box format from one type to another."""
    assert format in _formats, f"Invalid bounding box format: {format}, format must be one of {_formats}"
    if self.format == format:
        return
    elif self.format == "xyxy":
        func = xyxy2xywh if format == "xywh" else xyxy2ltwh
    elif self.format == "xywh":
        func = xywh2xyxy if format == "xyxy" else xywh2ltwh
    else:
        func = ltwh2xyxy if format == "xyxy" else ltwh2xywh
    self.bboxes = func(self.bboxes)
    self.format = format

mul(scale)

рдкреИрд░рд╛рдореАрдЯрд░:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо рдЪреВрдХ
scale tuple | list | int

рдЪрд╛рд░ рдХреЙрд░реНрдб рдХреЗ рд▓рд┐рдП рдкреИрдорд╛рдирд╛ред

рдЖрд╡рд╢реНрдпрдХ
рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def mul(self, scale):
    """
    Args:
        scale (tuple | list | int): the scale for four coords.
    """
    if isinstance(scale, Number):
        scale = to_4tuple(scale)
    assert isinstance(scale, (tuple, list))
    assert len(scale) == 4
    self.bboxes[:, 0] *= scale[0]
    self.bboxes[:, 1] *= scale[1]
    self.bboxes[:, 2] *= scale[2]
    self.bboxes[:, 3] *= scale[3]



ultralytics.utils.instance.Instances

рдПрдХ рдЫрд╡рд┐ рдореЗрдВ рдкрддрд╛ рд▓рдЧрд╛рдП рдЧрдП рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕, рд╕реЗрдЧрдореЗрдВрдЯ рдФрд░ рдХреАрдкреЙрдЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдХрдВрдЯреЗрдирд░ред

рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо
_bboxes Bboxes

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдВрддрд░рд┐рдХ рд╡рд╕реНрддреБред

keypoints ndarray

рдХреАрдкреЙрдЗрдВрдЯреНрд╕ (x, y, рджреГрд╢реНрдпрдорд╛рди) рдЖрдХрд╛рд░ [N, 17, 3] рдХреЗ рд╕рд╛рдеред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдХреЛрдИ рдирд╣реАрдВ рд╣реИред

normalized bool

рдзреНрд╡рдЬ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд╣реИрдВ рдпрд╛ рдирд╣реАрдВред

segments ndarray

рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╕реЗрдЧрдореЗрдВрдЯ рд╕рд░рдгреА [рдПрди, 1000, 2] рдкреБрди: рдирдореВрдирд╛рдХрд░рдг рдХреЗ рдмрд╛рджред

рдкреИрд░рд╛рдореАрдЯрд░:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо рдЪреВрдХ
bboxes ndarray

рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХреА рдПрдХ рд╕рд░рдгреА [рдПрди, 4]ред

рдЖрд╡рд╢реНрдпрдХ
segments list | ndarray

рдСрдмреНрдЬреЗрдХреНрдЯ рдЦрдВрдбреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдпрд╛ рд╕рд░рдгреА. рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдХреЛрдИ рдирд╣реАрдВ рд╣реИред

None
keypoints ndarray

рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде рдХреАрдкреЙрдЗрдВрдЯ рдХреА рдПрдХ рд╕рд░рдгреА [рдПрди, 17, 3]ред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдХреЛрдИ рдирд╣реАрдВ рд╣реИред

None
bbox_format str

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХрд╛ рдлрд╝реЙрд░реНрдореИрдЯ ('xywh' рдпрд╛ 'xyxy'). рдбрд┐рдлрд╝реЙрд▓реНрдЯ 'xywh' рд╣реИред

'xywh'
normalized bool

рдХреНрдпрд╛ рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд╣реИрдВред рдбрд┐рдлрд╝реЙрд▓реНрдЯ True рд╣реИ.

True

рдЙрджрд╛рд╣рд░рдг:

# Create an Instances object
instances = Instances(
    bboxes=np.array([[10, 10, 30, 30], [20, 20, 40, 40]]),
    segments=[np.array([[5, 5], [10, 10]]), np.array([[15, 15], [20, 20]])],
    keypoints=np.array([[[5, 5, 1], [10, 10, 1]], [[15, 15, 1], [20, 20, 1]]])
)
рдиреЛрдЯ

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдкреНрд░рд╛рд░реВрдк рдпрд╛ рддреЛ 'xywh' рдпрд╛ 'xyxy' рд╣реИ, рдФрд░ bbox_format рдпреБрдХреНрддрд┐ред рдпрд╣ рд╡рд░реНрдЧ рдЗрдирдкреБрдЯ рд╕рддреНрдпрд╛рдкрди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рдорд╛рдирддрд╛ рд╣реИ рдХрд┐ рдЗрдирдкреБрдЯ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдмрдиреЗ рд╣реИрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
class Instances:
    """
    Container for bounding boxes, segments, and keypoints of detected objects in an image.

    Attributes:
        _bboxes (Bboxes): Internal object for handling bounding box operations.
        keypoints (ndarray): keypoints(x, y, visible) with shape [N, 17, 3]. Default is None.
        normalized (bool): Flag indicating whether the bounding box coordinates are normalized.
        segments (ndarray): Segments array with shape [N, 1000, 2] after resampling.

    Args:
        bboxes (ndarray): An array of bounding boxes with shape [N, 4].
        segments (list | ndarray, optional): A list or array of object segments. Default is None.
        keypoints (ndarray, optional): An array of keypoints with shape [N, 17, 3]. Default is None.
        bbox_format (str, optional): The format of bounding boxes ('xywh' or 'xyxy'). Default is 'xywh'.
        normalized (bool, optional): Whether the bounding box coordinates are normalized. Default is True.

    Examples:
        ```python
        # Create an Instances object
        instances = Instances(
            bboxes=np.array([[10, 10, 30, 30], [20, 20, 40, 40]]),
            segments=[np.array([[5, 5], [10, 10]]), np.array([[15, 15], [20, 20]])],
            keypoints=np.array([[[5, 5, 1], [10, 10, 1]], [[15, 15, 1], [20, 20, 1]]])
        )
        ```

    Note:
        The bounding box format is either 'xywh' or 'xyxy', and is determined by the `bbox_format` argument.
        This class does not perform input validation, and it assumes the inputs are well-formed.
    """

    def __init__(self, bboxes, segments=None, keypoints=None, bbox_format="xywh", normalized=True) -> None:
        """
        Args:
            bboxes (ndarray): bboxes with shape [N, 4].
            segments (list | ndarray): segments.
            keypoints (ndarray): keypoints(x, y, visible) with shape [N, 17, 3].
        """
        self._bboxes = Bboxes(bboxes=bboxes, format=bbox_format)
        self.keypoints = keypoints
        self.normalized = normalized
        self.segments = segments

    def convert_bbox(self, format):
        """Convert bounding box format."""
        self._bboxes.convert(format=format)

    @property
    def bbox_areas(self):
        """Calculate the area of bounding boxes."""
        return self._bboxes.areas()

    def scale(self, scale_w, scale_h, bbox_only=False):
        """This might be similar with denormalize func but without normalized sign."""
        self._bboxes.mul(scale=(scale_w, scale_h, scale_w, scale_h))
        if bbox_only:
            return
        self.segments[..., 0] *= scale_w
        self.segments[..., 1] *= scale_h
        if self.keypoints is not None:
            self.keypoints[..., 0] *= scale_w
            self.keypoints[..., 1] *= scale_h

    def denormalize(self, w, h):
        """Denormalizes boxes, segments, and keypoints from normalized coordinates."""
        if not self.normalized:
            return
        self._bboxes.mul(scale=(w, h, w, h))
        self.segments[..., 0] *= w
        self.segments[..., 1] *= h
        if self.keypoints is not None:
            self.keypoints[..., 0] *= w
            self.keypoints[..., 1] *= h
        self.normalized = False

    def normalize(self, w, h):
        """Normalize bounding boxes, segments, and keypoints to image dimensions."""
        if self.normalized:
            return
        self._bboxes.mul(scale=(1 / w, 1 / h, 1 / w, 1 / h))
        self.segments[..., 0] /= w
        self.segments[..., 1] /= h
        if self.keypoints is not None:
            self.keypoints[..., 0] /= w
            self.keypoints[..., 1] /= h
        self.normalized = True

    def add_padding(self, padw, padh):
        """Handle rect and mosaic situation."""
        assert not self.normalized, "you should add padding with absolute coordinates."
        self._bboxes.add(offset=(padw, padh, padw, padh))
        self.segments[..., 0] += padw
        self.segments[..., 1] += padh
        if self.keypoints is not None:
            self.keypoints[..., 0] += padw
            self.keypoints[..., 1] += padh

    def __getitem__(self, index) -> "Instances":
        """
        Retrieve a specific instance or a set of instances using indexing.

        Args:
            index (int, slice, or np.ndarray): The index, slice, or boolean array to select
                                               the desired instances.

        Returns:
            Instances: A new Instances object containing the selected bounding boxes,
                       segments, and keypoints if present.

        Note:
            When using boolean indexing, make sure to provide a boolean array with the same
            length as the number of instances.
        """
        segments = self.segments[index] if len(self.segments) else self.segments
        keypoints = self.keypoints[index] if self.keypoints is not None else None
        bboxes = self.bboxes[index]
        bbox_format = self._bboxes.format
        return Instances(
            bboxes=bboxes,
            segments=segments,
            keypoints=keypoints,
            bbox_format=bbox_format,
            normalized=self.normalized,
        )

    def flipud(self, h):
        """Flips the coordinates of bounding boxes, segments, and keypoints vertically."""
        if self._bboxes.format == "xyxy":
            y1 = self.bboxes[:, 1].copy()
            y2 = self.bboxes[:, 3].copy()
            self.bboxes[:, 1] = h - y2
            self.bboxes[:, 3] = h - y1
        else:
            self.bboxes[:, 1] = h - self.bboxes[:, 1]
        self.segments[..., 1] = h - self.segments[..., 1]
        if self.keypoints is not None:
            self.keypoints[..., 1] = h - self.keypoints[..., 1]

    def fliplr(self, w):
        """Reverses the order of the bounding boxes and segments horizontally."""
        if self._bboxes.format == "xyxy":
            x1 = self.bboxes[:, 0].copy()
            x2 = self.bboxes[:, 2].copy()
            self.bboxes[:, 0] = w - x2
            self.bboxes[:, 2] = w - x1
        else:
            self.bboxes[:, 0] = w - self.bboxes[:, 0]
        self.segments[..., 0] = w - self.segments[..., 0]
        if self.keypoints is not None:
            self.keypoints[..., 0] = w - self.keypoints[..., 0]

    def clip(self, w, h):
        """Clips bounding boxes, segments, and keypoints values to stay within image boundaries."""
        ori_format = self._bboxes.format
        self.convert_bbox(format="xyxy")
        self.bboxes[:, [0, 2]] = self.bboxes[:, [0, 2]].clip(0, w)
        self.bboxes[:, [1, 3]] = self.bboxes[:, [1, 3]].clip(0, h)
        if ori_format != "xyxy":
            self.convert_bbox(format=ori_format)
        self.segments[..., 0] = self.segments[..., 0].clip(0, w)
        self.segments[..., 1] = self.segments[..., 1].clip(0, h)
        if self.keypoints is not None:
            self.keypoints[..., 0] = self.keypoints[..., 0].clip(0, w)
            self.keypoints[..., 1] = self.keypoints[..., 1].clip(0, h)

    def remove_zero_area_boxes(self):
        """Remove zero-area boxes, i.e. after clipping some boxes may have zero width or height."""
        good = self.bbox_areas > 0
        if not all(good):
            self._bboxes = self._bboxes[good]
            if len(self.segments):
                self.segments = self.segments[good]
            if self.keypoints is not None:
                self.keypoints = self.keypoints[good]
        return good

    def update(self, bboxes, segments=None, keypoints=None):
        """Updates instance variables."""
        self._bboxes = Bboxes(bboxes, format=self._bboxes.format)
        if segments is not None:
            self.segments = segments
        if keypoints is not None:
            self.keypoints = keypoints

    def __len__(self):
        """Return the length of the instance list."""
        return len(self.bboxes)

    @classmethod
    def concatenate(cls, instances_list: List["Instances"], axis=0) -> "Instances":
        """
        Concatenates a list of Instances objects into a single Instances object.

        Args:
            instances_list (List[Instances]): A list of Instances objects to concatenate.
            axis (int, optional): The axis along which the arrays will be concatenated. Defaults to 0.

        Returns:
            Instances: A new Instances object containing the concatenated bounding boxes,
                       segments, and keypoints if present.

        Note:
            The `Instances` objects in the list should have the same properties, such as
            the format of the bounding boxes, whether keypoints are present, and if the
            coordinates are normalized.
        """
        assert isinstance(instances_list, (list, tuple))
        if not instances_list:
            return cls(np.empty(0))
        assert all(isinstance(instance, Instances) for instance in instances_list)

        if len(instances_list) == 1:
            return instances_list[0]

        use_keypoint = instances_list[0].keypoints is not None
        bbox_format = instances_list[0]._bboxes.format
        normalized = instances_list[0].normalized

        cat_boxes = np.concatenate([ins.bboxes for ins in instances_list], axis=axis)
        cat_segments = np.concatenate([b.segments for b in instances_list], axis=axis)
        cat_keypoints = np.concatenate([b.keypoints for b in instances_list], axis=axis) if use_keypoint else None
        return cls(cat_boxes, cat_segments, cat_keypoints, bbox_format, normalized)

    @property
    def bboxes(self):
        """Return bounding boxes."""
        return self._bboxes.bboxes

bbox_areas property

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВред

bboxes property

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рд▓реМрдЯрд╛рдПрдВред

__getitem__(index)

рдЕрдиреБрдХреНрд░рдордг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрджрд╛рд╣рд░рдг рдпрд╛ рдЖрд╡реГрддреНрддрд┐рдпреЛрдВ рдХрд╛ рдПрдХ рд╕реЗрдЯ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

рдкреИрд░рд╛рдореАрдЯрд░:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо рдЪреВрдХ
index int, slice, or np.ndarray

рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП index, slice рдпрд╛ boolean рд╕рд░рдгреА рд╡рд╛рдВрдЫрд┐рдд рдЙрджрд╛рд╣рд░рдгред

рдЖрд╡рд╢реНрдпрдХ

рджреЗрддрд╛:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо
Instances Instances

рдЪрдпрдирд┐рдд рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рд╡рд╛рд▓реЗ рдПрдХ рдирдП рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ, рд╕реЗрдЧрдореЗрдВрдЯ, рдФрд░ рдХреАрдкреЙрдЗрдВрдЯ рдпрджрд┐ рдореМрдЬреВрдж рд╣реИрдВред

рдиреЛрдЯ

рдмреВрд▓рд┐рдпрди рдЗрдВрдбреЗрдХреНрд╕рд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдЙрд╕реА рдХреЗ рд╕рд╛рде рдПрдХ рдмреВрд▓рд┐рдпрди рд╕рд░рдгреА рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рд▓рдВрдмрд╛рдИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def __getitem__(self, index) -> "Instances":
    """
    Retrieve a specific instance or a set of instances using indexing.

    Args:
        index (int, slice, or np.ndarray): The index, slice, or boolean array to select
                                           the desired instances.

    Returns:
        Instances: A new Instances object containing the selected bounding boxes,
                   segments, and keypoints if present.

    Note:
        When using boolean indexing, make sure to provide a boolean array with the same
        length as the number of instances.
    """
    segments = self.segments[index] if len(self.segments) else self.segments
    keypoints = self.keypoints[index] if self.keypoints is not None else None
    bboxes = self.bboxes[index]
    bbox_format = self._bboxes.format
    return Instances(
        bboxes=bboxes,
        segments=segments,
        keypoints=keypoints,
        bbox_format=bbox_format,
        normalized=self.normalized,
    )

__init__(bboxes, segments=None, keypoints=None, bbox_format='xywh', normalized=True)

рдкреИрд░рд╛рдореАрдЯрд░:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо рдЪреВрдХ
bboxes ndarray

рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде bboxes [N, 4]ред

рдЖрд╡рд╢реНрдпрдХ
segments list | ndarray

рдХреНрд╖реЗрддреНрд░реЛрдВред

None
keypoints ndarray

рдХреАрдкреЙрдЗрдВрдЯреНрд╕ (x, y, рджреГрд╢реНрдпрдорд╛рди) рдЖрдХрд╛рд░ [N, 17, 3] рдХреЗ рд╕рд╛рдеред

None
рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def __init__(self, bboxes, segments=None, keypoints=None, bbox_format="xywh", normalized=True) -> None:
    """
    Args:
        bboxes (ndarray): bboxes with shape [N, 4].
        segments (list | ndarray): segments.
        keypoints (ndarray): keypoints(x, y, visible) with shape [N, 17, 3].
    """
    self._bboxes = Bboxes(bboxes=bboxes, format=bbox_format)
    self.keypoints = keypoints
    self.normalized = normalized
    self.segments = segments

__len__()

рдЖрд╡реГрддреНрддрд┐ рд╕реВрдЪреА рдХреА рд▓рдВрдмрд╛рдИ рд▓реМрдЯрд╛рдПрдВ.

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def __len__(self):
    """Return the length of the instance list."""
    return len(self.bboxes)

add_padding(padw, padh)

рд╕реАрдзреА рдФрд░ рдореЛрдЬрд╝реЗрдХ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рдВрднрд╛рд▓реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def add_padding(self, padw, padh):
    """Handle rect and mosaic situation."""
    assert not self.normalized, "you should add padding with absolute coordinates."
    self._bboxes.add(offset=(padw, padh, padw, padh))
    self.segments[..., 0] += padw
    self.segments[..., 1] += padh
    if self.keypoints is not None:
        self.keypoints[..., 0] += padw
        self.keypoints[..., 1] += padh

clip(w, h)

рдХреНрд▓рд┐рдк рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕, рд╕реЗрдЧрдореЗрдВрдЯ, рдФрд░ рдХреАрдкреЙрдЗрдВрдЯ рдорд╛рди рдЫрд╡рд┐ рд╕реАрдорд╛рдУрдВ рдХреЗ рднреАрддрд░ рд░рд╣рдиреЗ рдХреЗ рд▓рд┐рдПред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def clip(self, w, h):
    """Clips bounding boxes, segments, and keypoints values to stay within image boundaries."""
    ori_format = self._bboxes.format
    self.convert_bbox(format="xyxy")
    self.bboxes[:, [0, 2]] = self.bboxes[:, [0, 2]].clip(0, w)
    self.bboxes[:, [1, 3]] = self.bboxes[:, [1, 3]].clip(0, h)
    if ori_format != "xyxy":
        self.convert_bbox(format=ori_format)
    self.segments[..., 0] = self.segments[..., 0].clip(0, w)
    self.segments[..., 1] = self.segments[..., 1].clip(0, h)
    if self.keypoints is not None:
        self.keypoints[..., 0] = self.keypoints[..., 0].clip(0, w)
        self.keypoints[..., 1] = self.keypoints[..., 1].clip(0, h)

concatenate(instances_list, axis=0) classmethod

рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреА рдПрдХ рд╕реВрдЪреА рдХреЛ рдПрдХрд▓ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИред

рдкреИрд░рд╛рдореАрдЯрд░:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо рдЪреВрдХ
instances_list List[Instances]

рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ред

рдЖрд╡рд╢реНрдпрдХ
axis int

рд╡рд╣ рдЕрдХреНрд╖ рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рд╕рд░рдгрд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛ред 0 рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯред

0

рджреЗрддрд╛:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо
Instances Instances

рдПрдХ рдирдпрд╛ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдЬрд┐рд╕рдореЗрдВ рд╢реНрд░реЗрдгреАрдмрджреНрдз рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рд╣реИрдВ, рд╕реЗрдЧрдореЗрдВрдЯ, рдФрд░ рдХреАрдкреЙрдЗрдВрдЯ рдпрджрд┐ рдореМрдЬреВрдж рд╣реИрдВред

рдиреЛрдЯ

рд╡рд╣реА Instances рд╕реВрдЪреА рдореЗрдВ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдореЗрдВ рд╕рдорд╛рди рдЧреБрдг рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП, рдЬреИрд╕реЗ рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХрд╛ рдкреНрд░рд╛рд░реВрдк, рдХреНрдпрд╛ рдХреАрдкреЙрдЗрдВрдЯ рдореМрдЬреВрдж рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд╣реИрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
@classmethod
def concatenate(cls, instances_list: List["Instances"], axis=0) -> "Instances":
    """
    Concatenates a list of Instances objects into a single Instances object.

    Args:
        instances_list (List[Instances]): A list of Instances objects to concatenate.
        axis (int, optional): The axis along which the arrays will be concatenated. Defaults to 0.

    Returns:
        Instances: A new Instances object containing the concatenated bounding boxes,
                   segments, and keypoints if present.

    Note:
        The `Instances` objects in the list should have the same properties, such as
        the format of the bounding boxes, whether keypoints are present, and if the
        coordinates are normalized.
    """
    assert isinstance(instances_list, (list, tuple))
    if not instances_list:
        return cls(np.empty(0))
    assert all(isinstance(instance, Instances) for instance in instances_list)

    if len(instances_list) == 1:
        return instances_list[0]

    use_keypoint = instances_list[0].keypoints is not None
    bbox_format = instances_list[0]._bboxes.format
    normalized = instances_list[0].normalized

    cat_boxes = np.concatenate([ins.bboxes for ins in instances_list], axis=axis)
    cat_segments = np.concatenate([b.segments for b in instances_list], axis=axis)
    cat_keypoints = np.concatenate([b.keypoints for b in instances_list], axis=axis) if use_keypoint else None
    return cls(cat_boxes, cat_segments, cat_keypoints, bbox_format, normalized)

convert_bbox(format)

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдкреНрд░рд╛рд░реВрдк рдХрдирд╡рд░реНрдЯ рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def convert_bbox(self, format):
    """Convert bounding box format."""
    self._bboxes.convert(format=format)

denormalize(w, h)

рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рд╕реЗ рдмрдХреНрд╕реЗ, рдЦрдВрдб рдФрд░ рдХреАрдкреЙрдЗрдВрдЯ рдХреЛ рдЕрд╕рд╛рдорд╛рдиреНрдп рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def denormalize(self, w, h):
    """Denormalizes boxes, segments, and keypoints from normalized coordinates."""
    if not self.normalized:
        return
    self._bboxes.mul(scale=(w, h, w, h))
    self.segments[..., 0] *= w
    self.segments[..., 1] *= h
    if self.keypoints is not None:
        self.keypoints[..., 0] *= w
        self.keypoints[..., 1] *= h
    self.normalized = False

fliplr(w)

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдФрд░ рд╕реЗрдЧрдореЗрдВрдЯ рдХреЗ рдХреНрд░рдо рдХреЛ рдХреНрд╖реИрддрд┐рдЬ рд░реВрдк рд╕реЗ рдЙрд▓рдЯ рджреЗрддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def fliplr(self, w):
    """Reverses the order of the bounding boxes and segments horizontally."""
    if self._bboxes.format == "xyxy":
        x1 = self.bboxes[:, 0].copy()
        x2 = self.bboxes[:, 2].copy()
        self.bboxes[:, 0] = w - x2
        self.bboxes[:, 2] = w - x1
    else:
        self.bboxes[:, 0] = w - self.bboxes[:, 0]
    self.segments[..., 0] = w - self.segments[..., 0]
    if self.keypoints is not None:
        self.keypoints[..., 0] = w - self.keypoints[..., 0]

flipud(h)

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕, рд╕реЗрдЧрдореЗрдВрдЯ рдФрд░ рдХреАрдкреЙрдЗрдВрдЯреНрд╕ рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреЛ рд▓рдВрдмрд╡рдд рд░реВрдк рд╕реЗ рдлрд╝реНрд▓рд┐рдк рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def flipud(self, h):
    """Flips the coordinates of bounding boxes, segments, and keypoints vertically."""
    if self._bboxes.format == "xyxy":
        y1 = self.bboxes[:, 1].copy()
        y2 = self.bboxes[:, 3].copy()
        self.bboxes[:, 1] = h - y2
        self.bboxes[:, 3] = h - y1
    else:
        self.bboxes[:, 1] = h - self.bboxes[:, 1]
    self.segments[..., 1] = h - self.segments[..., 1]
    if self.keypoints is not None:
        self.keypoints[..., 1] = h - self.keypoints[..., 1]

normalize(w, h)

рдЫрд╡рд┐ рдЖрдпрд╛рдореЛрдВ рдХреЗ рд▓рд┐рдП рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕, рд╕реЗрдЧрдореЗрдВрдЯ рдФрд░ рдХреАрдкреЙрдЗрдВрдЯ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def normalize(self, w, h):
    """Normalize bounding boxes, segments, and keypoints to image dimensions."""
    if self.normalized:
        return
    self._bboxes.mul(scale=(1 / w, 1 / h, 1 / w, 1 / h))
    self.segments[..., 0] /= w
    self.segments[..., 1] /= h
    if self.keypoints is not None:
        self.keypoints[..., 0] /= w
        self.keypoints[..., 1] /= h
    self.normalized = True

remove_zero_area_boxes()

рд╢реВрдиреНрдп-рдХреНрд╖реЗрддреНрд░ рдмрдХреНрд╕реЗ рдирд┐рдХрд╛рд▓реЗрдВ, рдпрд╛рдиреА рдХреНрд▓рд┐рдкрд┐рдВрдЧ рдХреЗ рдмрд╛рдж рдХреБрдЫ рдмрдХреНрд╕реЗ рдореЗрдВ рд╢реВрдиреНрдп рдЪреМрдбрд╝рд╛рдИ рдпрд╛ рдКрдВрдЪрд╛рдИ рд╣реЛ рд╕рдХрддреА рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def remove_zero_area_boxes(self):
    """Remove zero-area boxes, i.e. after clipping some boxes may have zero width or height."""
    good = self.bbox_areas > 0
    if not all(good):
        self._bboxes = self._bboxes[good]
        if len(self.segments):
            self.segments = self.segments[good]
        if self.keypoints is not None:
            self.keypoints = self.keypoints[good]
    return good

scale(scale_w, scale_h, bbox_only=False)

рдпрд╣ denormalize func рдХреЗ рд╕рд╛рде рд╕рдорд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд╕рдВрдХреЗрдд рдХреЗ рдмрд┐рдирд╛ред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def scale(self, scale_w, scale_h, bbox_only=False):
    """This might be similar with denormalize func but without normalized sign."""
    self._bboxes.mul(scale=(scale_w, scale_h, scale_w, scale_h))
    if bbox_only:
        return
    self.segments[..., 0] *= scale_w
    self.segments[..., 1] *= scale_h
    if self.keypoints is not None:
        self.keypoints[..., 0] *= scale_w
        self.keypoints[..., 1] *= scale_h

update(bboxes, segments=None, keypoints=None)

рдЗрдВрд╕реНрдЯреЗрдВрд╕ рд╡реИрд░рд┐рдПрдмрд▓ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def update(self, bboxes, segments=None, keypoints=None):
    """Updates instance variables."""
    self._bboxes = Bboxes(bboxes, format=self._bboxes.format)
    if segments is not None:
        self.segments = segments
    if keypoints is not None:
        self.keypoints = keypoints



ultralytics.utils.instance._ntuple(n)

рд╕реЗ PyTorch рдЖрдВрддрд░рд┐рдХред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/utils/instance.py
def _ntuple(n):
    """From PyTorch internals."""

    def parse(x):
        """Parse bounding boxes format between XYWH and LTWH."""
        return x if isinstance(x, abc.Iterable) else tuple(repeat(x, n))

    return parse





2023-11-12 рдмрдирд╛рдпрд╛ рдЧрдпрд╛, рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ 2024-05-08
рд▓реЗрдЦрдХ: рдмреБрд░рд╣рд╛рди-рдХреНрдпреВ (1), рдЧреНрд▓реЗрди-рдЬреЛрдЪрд░ (3), рд▓рд╛рдлрд┐рдВрдЧ-рдХреНрдпреВ (1)