| |
| |
|
|
| import numpy as np |
| import torch |
|
|
| |
| from detectron2.data.detection_utils import \ |
| annotations_to_instances as base_annotations_to_instances |
| from detectron2.data.detection_utils import \ |
| transform_instance_annotations as base_transform_instance_annotations |
|
|
| |
|
|
|
|
| def annotations_to_instances(annos, image_size, sample_points=0): |
| """ |
| Create an :class:`Instances` object used by the models, |
| from instance annotations in the dataset dict. |
| |
| Args: |
| annos (list[dict]): a list of instance annotations in one image, each |
| element for one instance. |
| image_size (tuple): height, width |
| sample_points (int): subsample points at each iteration |
| |
| Returns: |
| Instances: |
| It will contain fields "gt_boxes", "gt_classes", |
| "gt_point_coords", "gt_point_labels", if they can be obtained from `annos`. |
| This is the format that builtin models with point supervision expect. |
| """ |
| target = base_annotations_to_instances(annos, image_size) |
|
|
| assert ("point_coords" in annos[0]) == ("point_labels" in annos[0]) |
|
|
| if len(annos) and "point_labels" in annos[0]: |
| point_coords = [] |
| point_labels = [] |
| for i, _ in enumerate(annos): |
| |
| point_coords_wrt_image = np.array(annos[i]["point_coords"]) |
| point_labels_wrt_image = np.array(annos[i]["point_labels"]) |
|
|
| if sample_points > 0: |
| random_indices = np.random.choice( |
| point_coords_wrt_image.shape[0], |
| sample_points, |
| replace=point_coords_wrt_image.shape[0] < sample_points, |
| ).astype(int) |
| point_coords_wrt_image = point_coords_wrt_image[random_indices] |
| point_labels_wrt_image = point_labels_wrt_image[random_indices] |
| assert point_coords_wrt_image.shape[0] == point_labels_wrt_image.size |
|
|
| point_coords.append(point_coords_wrt_image) |
| point_labels.append(point_labels_wrt_image) |
|
|
| point_coords = torch.stack([torch.from_numpy(x) for x in point_coords]) |
| point_labels = torch.stack([torch.from_numpy(x) for x in point_labels]) |
| target.gt_point_coords = point_coords |
| target.gt_point_labels = point_labels |
|
|
| return target |
|
|
|
|
| def transform_instance_annotations( |
| annotation, transforms, image_size, *, keypoint_hflip_indices=None |
| ): |
| """ |
| Apply transforms to box, and point annotations of a single instance. |
| It will use `transforms.apply_box` for the box, and |
| `transforms.apply_coords` for points. |
| Args: |
| annotation (dict): dict of instance annotations for a single instance. |
| It will be modified in-place. |
| transforms (TransformList or list[Transform]): |
| image_size (tuple): the height, width of the transformed image |
| keypoint_hflip_indices (ndarray[int]): see `create_keypoint_hflip_indices`. |
| Returns: |
| dict: |
| the same input dict with fields "bbox", "point_coords", "point_labels" |
| transformed according to `transforms`. |
| The "bbox_mode" field will be set to XYXY_ABS. |
| """ |
| annotation = base_transform_instance_annotations( |
| annotation, transforms, image_size, keypoint_hflip_indices |
| ) |
|
|
| assert ("point_coords" in annotation) == ("point_labels" in annotation) |
| if "point_coords" in annotation and "point_labels" in annotation: |
| point_coords = annotation["point_coords"] |
| point_labels = np.array(annotation["point_labels"]).astype(float) |
| point_coords = transforms.apply_coords(point_coords) |
|
|
| |
| inside = (point_coords >= np.array([0, 0])) & (point_coords <= np.array(image_size[::-1])) |
| inside = inside.all(axis=1) |
| point_labels[~inside] = -1 |
|
|
| annotation["point_coords"] = point_coords |
| annotation["point_labels"] = point_labels |
|
|
| return annotation |
|
|