def add_coco_labels(
    sample_collection,
    label_field,
    labels_or_path,
    categories,
    label_type="detections",
    coco_id_field=None,
    include_annotation_id=False,
    extra_attrs=True,
    use_polylines=False,
    tolerance=None,
):
    """Adds the given COCO labels to the collection.

    The ``labels_or_path`` argument can be any of the following:

    -   a list of COCO annotations in the format below
    -   the path to a JSON file containing a list of COCO annotations
    -   the path to a JSON file whose ``"annotations"`` key contains a list of
        COCO annotations

    When ``label_type="detections"``, the labels should have format::

        [
            {
                "id": 1,
                "image_id": 1,
                "category_id": 1,
                "bbox": [260, 177, 231, 199],

                # optional
                "score": 0.95,
                "area": 45969,
                "iscrowd": 0,

                # extra attrs
                ...
            },
            ...
        ]

    When ``label_type="segmentations"``, the labels should have format::

        [
            {
                "id": 1,
                "image_id": 1,
                "category_id": 1,
                "bbox": [260, 177, 231, 199],
                "segmentation": [...],

                # optional
                "score": 0.95,
                "area": 45969,
                "iscrowd": 0,

                # extra attrs
                ...
            },
            ...
        ]

    When ``label_type="keypoints"``, the labels should have format::

        [
            {
                "id": 1,
                "image_id": 1,
                "category_id": 1,
                "keypoints": [224, 226, 2, ...],
                "num_keypoints": 10,

                # extra attrs
                ...
            },
            ...
        ]

    See `this page <https://cocodataset.org/#format-data>`_ for more
    information about the COCO data format.

    Args:
        sample_collection: a
            :class:`fiftyone.core.collections.SampleCollection`
        label_field: the label field in which to store the labels. The field
            will be created if necessary
        labels_or_path: a list of COCO annotations or the path to a JSON file
            containing such data on disk
        categories: can be any of the following:

            -   a list of category dicts in the format of
                :meth:`parse_coco_categories` specifying the classes and their
                category IDs
            -   a dict mapping class IDs to class labels
            -   a list of class labels whose 1-based ordering is assumed to
                correspond to the category IDs in the provided COCO labels
        label_type ("detections"): the type of labels to load. Supported values
            are ``("detections", "segmentations", "keypoints")``
        coco_id_field (None): this parameter determines how to map the
            predictions onto samples in ``sample_collection``. The supported
            values are:

            -   ``None`` (default): in this case, the ``image_id`` of the
                predictions are assumed to be the 1-based positional indexes of
                samples in ``sample_collection``
            -   the name of a field of ``sample_collection`` containing the
                COCO IDs for the samples that correspond to the ``image_id`` of
                the predictions
        include_annotation_id (False): whether to include the COCO ID of each
            annotation in the loaded labels
        extra_attrs (True): whether to load extra annotation attributes onto
            the imported labels. Supported values are:

            -   ``True``: load all extra attributes found
            -   ``False``: do not load extra attributes
            -   a name or list of names of specific attributes to load
        use_polylines (False): whether to represent segmentations as
            :class:`fiftyone.core.labels.Polylines` instances rather than
            :class:`fiftyone.core.labels.Detections` with dense masks
        tolerance (None): a tolerance, in pixels, when generating approximate
            polylines for instance masks. Typical values are 1-3 pixels
    """
    if etau.is_str(labels_or_path):
        labels = etas.load_json(labels_or_path)
        if isinstance(labels, dict):
            labels = labels["annotations"]
    else:
        labels = labels_or_path

    coco_objects_map = defaultdict(list)
    for d in labels:
        coco_obj = COCOObject.from_anno_dict(d, extra_attrs=extra_attrs)
        coco_objects_map[coco_obj.image_id].append(coco_obj)

    if coco_id_field is not None:
        # Use `coco_id_field` as key to match predictions with samples
        _coco_ids, _ids = sample_collection.values([coco_id_field, "id"])
        id_map = {k: v for k, v in zip(_coco_ids, _ids)}

        coco_ids = sorted(coco_objects_map.keys())
        bad_ids = set(coco_ids) - set(id_map.keys())
        if bad_ids:
            coco_ids = [_id for _id in coco_ids if _id not in bad_ids]
            logger.warning(
                "Ignoring %d labels with nonexistent COCO IDs (eg %s)",
                len(bad_ids),
                next(iter(bad_ids)),
            )

        sample_ids = [id_map[coco_id] for coco_id in coco_ids]
        view = sample_collection.select(sample_ids, ordered=True)
        coco_objects = [coco_objects_map[coco_id] for coco_id in coco_ids]
    else:
        # Assume `image_id` is 1-based sample position
        view = sample_collection
        coco_objects = [coco_objects_map[i] for i in range(1, len(view) + 1)]

    view.compute_metadata()
    widths, heights = view.values(["metadata.width", "metadata.height"])

    if isinstance(categories, dict):
        classes_map = categories
    elif not categories:
        classes_map = {}
    elif isinstance(categories[0], dict):
        classes_map = {c["id"]: c["name"] for c in categories}
    else:
        classes_map = {i: label for i, label in enumerate(categories, 1)}

    labels = []
    for _coco_objects, width, height in zip(coco_objects, widths, heights):
        frame_size = (width, height)

        if label_type == "detections":
            _labels = _coco_objects_to_detections(
                _coco_objects,
                frame_size,
                classes_map,
                None,
                False,
                include_annotation_id,
            )
        elif label_type == "segmentations":
            if use_polylines:
                _labels = _coco_objects_to_polylines(
                    _coco_objects,
                    frame_size,
                    classes_map,
                    None,
                    tolerance,
                    include_annotation_id,
                )
            else:
                _labels = _coco_objects_to_detections(
                    _coco_objects,
                    frame_size,
                    classes_map,
                    None,
                    True,
                    include_annotation_id,
                )
        elif label_type == "keypoints":
            _labels = _coco_objects_to_keypoints(
                _coco_objects,
                frame_size,
                classes_map,
                None,
                include_annotation_id,
            )
        else:
            raise ValueError(
                "Unsupported label_type='%s'. Supported values are %s"
                % (label_type, ("detections", "segmentations", "keypoints"))
            )

        labels.append(_labels)

    view.set_values(label_field, labels)
Adds the given COCO labels to the collection.

    The ``labels_or_path`` argument can be any of the following:

    -   a list of COCO annotations in the format below
    -   the path to a JSON file containing a list of COCO annotations
    -   the path to a JSON file whose ``"annotations"`` key contains a list of
        COCO annotations

    When ``label_type="detections"``, the labels should have format::

        [
            {
                "id": 1,
                "image_id": 1,
                "category_id": 1,
                "bbox": [260, 177, 231, 199],

                # optional
                "score": 0.95,
                "area": 45969,
                "iscrowd": 0,

                # extra attrs
                ...
            },
            ...
        ]

    When ``label_type="segmentations"``, the labels should have format::

        [
            {
                "id": 1,
                "image_id": 1,
                "category_id": 1,
                "bbox": [260, 177, 231, 199],
                "segmentation": [...],

                # optional
                "score": 0.95,
                "area": 45969,
                "iscrowd": 0,

                # extra attrs
                ...
            },
            ...
        ]

    When ``label_type="keypoints"``, the labels should have format::

        [
            {
                "id": 1,
                "image_id": 1,
                "category_id": 1,
                "keypoints": [224, 226, 2, ...],
                "num_keypoints": 10,

                # extra attrs
                ...
            },
            ...
        ]

    See `this page <https://cocodataset.org/#format-data>`_ for more
    information about the COCO data format.

    Args:
        sample_collection: a
            :class:`fiftyone.core.collections.SampleCollection`
        label_field: the label field in which to store the labels. The field
            will be created if necessary
        labels_or_path: a list of COCO annotations or the path to a JSON file
            containing such data on disk
        categories: can be any of the following:

            -   a list of category dicts in the format of
                :meth:`parse_coco_categories` specifying the classes and their
                category IDs
            -   a dict mapping class IDs to class labels
            -   a list of class labels whose 1-based ordering is assumed to
                correspond to the category IDs in the provided COCO labels
        label_type ("detections"): the type of labels to load. Supported values
            are ``("detections", "segmentations", "keypoints")``
        coco_id_field (None): this parameter determines how to map the
            predictions onto samples in ``sample_collection``. The supported
            values are:

            -   ``None`` (default): in this case, the ``image_id`` of the
                predictions are assumed to be the 1-based positional indexes of
                samples in ``sample_collection``
            -   the name of a field of ``sample_collection`` containing the
                COCO IDs for the samples that correspond to the ``image_id`` of
                the predictions
        include_annotation_id (False): whether to include the COCO ID of each
            annotation in the loaded labels
        extra_attrs (True): whether to load extra annotation attributes onto
            the imported labels. Supported values are:

            -   ``True``: load all extra attributes found
            -   ``False``: do not load extra attributes
            -   a name or list of names of specific attributes to load
        use_polylines (False): whether to represent segmentations as
            :class:`fiftyone.core.labels.Polylines` instances rather than
            :class:`fiftyone.core.labels.Detections` with dense masks
        tolerance (None): a tolerance, in pixels, when generating approximate
            polylines for instance masks. Typical values are 1-3 pixels
    
fiftyone/utils/coco.py