CoolFace
Apppublic

coreml-community/ControlNet-v1-1-Annotators-cpu

sourceHugging Facemitupdated 2y agoView on Hugging Face
15likes
dataset_mapper.py192 linesDownload Raw Back to data
1# Copyright (c) Facebook, Inc. and its affiliates.2import copy3import logging4import numpy as np5from typing import List, Optional, Union6import torch7 8from annotator.oneformer.detectron2.config import configurable9 10from . import detection_utils as utils11from . import transforms as T12 13"""14This file contains the default mapping that's applied to "dataset dicts".15"""16 17__all__ = ["DatasetMapper"]18 19 20class DatasetMapper:21    """22    A callable which takes a dataset dict in Detectron2 Dataset format,23    and map it into a format used by the model.24 25    This is the default callable to be used to map your dataset dict into training data.26    You may need to follow it to implement your own one for customized logic,27    such as a different way to read or transform images.28    See :doc:`/tutorials/data_loading` for details.29 30    The callable currently does the following:31 32    1. Read the image from "file_name"33    2. Applies cropping/geometric transforms to the image and annotations34    3. Prepare data and annotations to Tensor and :class:`Instances`35    """36 37    @configurable38    def __init__(39        self,40        is_train: bool,41        *,42        augmentations: List[Union[T.Augmentation, T.Transform]],43        image_format: str,44        use_instance_mask: bool = False,45        use_keypoint: bool = False,46        instance_mask_format: str = "polygon",47        keypoint_hflip_indices: Optional[np.ndarray] = None,48        precomputed_proposal_topk: Optional[int] = None,49        recompute_boxes: bool = False,50    ):51        """52        NOTE: this interface is experimental.53 54        Args:55            is_train: whether it's used in training or inference56            augmentations: a list of augmentations or deterministic transforms to apply57            image_format: an image format supported by :func:`detection_utils.read_image`.58            use_instance_mask: whether to process instance segmentation annotations, if available59            use_keypoint: whether to process keypoint annotations if available60            instance_mask_format: one of "polygon" or "bitmask". Process instance segmentation61                masks into this format.62            keypoint_hflip_indices: see :func:`detection_utils.create_keypoint_hflip_indices`63            precomputed_proposal_topk: if given, will load pre-computed64                proposals from dataset_dict and keep the top k proposals for each image.65            recompute_boxes: whether to overwrite bounding box annotations66                by computing tight bounding boxes from instance mask annotations.67        """68        if recompute_boxes:69            assert use_instance_mask, "recompute_boxes requires instance masks"70        # fmt: off71        self.is_train               = is_train72        self.augmentations          = T.AugmentationList(augmentations)73        self.image_format           = image_format74        self.use_instance_mask      = use_instance_mask75        self.instance_mask_format   = instance_mask_format76        self.use_keypoint           = use_keypoint77        self.keypoint_hflip_indices = keypoint_hflip_indices78        self.proposal_topk          = precomputed_proposal_topk79        self.recompute_boxes        = recompute_boxes80        # fmt: on81        logger = logging.getLogger(__name__)82        mode = "training" if is_train else "inference"83        logger.info(f"[DatasetMapper] Augmentations used in {mode}: {augmentations}")84 85    @classmethod86    def from_config(cls, cfg, is_train: bool = True):87        augs = utils.build_augmentation(cfg, is_train)88        if cfg.INPUT.CROP.ENABLED and is_train:89            augs.insert(0, T.RandomCrop(cfg.INPUT.CROP.TYPE, cfg.INPUT.CROP.SIZE))90            recompute_boxes = cfg.MODEL.MASK_ON91        else:92            recompute_boxes = False93 94        ret = {95            "is_train": is_train,96            "augmentations": augs,97            "image_format": cfg.INPUT.FORMAT,98            "use_instance_mask": cfg.MODEL.MASK_ON,99            "instance_mask_format": cfg.INPUT.MASK_FORMAT,100            "use_keypoint": cfg.MODEL.KEYPOINT_ON,101            "recompute_boxes": recompute_boxes,102        }103 104        if cfg.MODEL.KEYPOINT_ON:105            ret["keypoint_hflip_indices"] = utils.create_keypoint_hflip_indices(cfg.DATASETS.TRAIN)106 107        if cfg.MODEL.LOAD_PROPOSALS:108            ret["precomputed_proposal_topk"] = (109                cfg.DATASETS.PRECOMPUTED_PROPOSAL_TOPK_TRAIN110                if is_train111                else cfg.DATASETS.PRECOMPUTED_PROPOSAL_TOPK_TEST112            )113        return ret114 115    def _transform_annotations(self, dataset_dict, transforms, image_shape):116        # USER: Modify this if you want to keep them for some reason.117        for anno in dataset_dict["annotations"]:118            if not self.use_instance_mask:119                anno.pop("segmentation", None)120            if not self.use_keypoint:121                anno.pop("keypoints", None)122 123        # USER: Implement additional transformations if you have other types of data124        annos = [125            utils.transform_instance_annotations(126                obj, transforms, image_shape, keypoint_hflip_indices=self.keypoint_hflip_indices127            )128            for obj in dataset_dict.pop("annotations")129            if obj.get("iscrowd", 0) == 0130        ]131        instances = utils.annotations_to_instances(132            annos, image_shape, mask_format=self.instance_mask_format133        )134 135        # After transforms such as cropping are applied, the bounding box may no longer136        # tightly bound the object. As an example, imagine a triangle object137        # [(0,0), (2,0), (0,2)] cropped by a box [(1,0),(2,2)] (XYXY format). The tight138        # bounding box of the cropped triangle should be [(1,0),(2,1)], which is not equal to139        # the intersection of original bounding box and the cropping box.140        if self.recompute_boxes:141            instances.gt_boxes = instances.gt_masks.get_bounding_boxes()142        dataset_dict["instances"] = utils.filter_empty_instances(instances)143 144    def __call__(self, dataset_dict):145        """146        Args:147            dataset_dict (dict): Metadata of one image, in Detectron2 Dataset format.148 149        Returns:150            dict: a format that builtin models in detectron2 accept151        """152        dataset_dict = copy.deepcopy(dataset_dict)  # it will be modified by code below153        # USER: Write your own image loading if it's not from a file154        image = utils.read_image(dataset_dict["file_name"], format=self.image_format)155        utils.check_image_size(dataset_dict, image)156 157        # USER: Remove if you don't do semantic/panoptic segmentation.158        if "sem_seg_file_name" in dataset_dict:159            sem_seg_gt = utils.read_image(dataset_dict.pop("sem_seg_file_name"), "L").squeeze(2)160        else:161            sem_seg_gt = None162 163        aug_input = T.AugInput(image, sem_seg=sem_seg_gt)164        transforms = self.augmentations(aug_input)165        image, sem_seg_gt = aug_input.image, aug_input.sem_seg166 167        image_shape = image.shape[:2]  # h, w168        # Pytorch's dataloader is efficient on torch.Tensor due to shared-memory,169        # but not efficient on large generic data structures due to the use of pickle & mp.Queue.170        # Therefore it's important to use torch.Tensor.171        dataset_dict["image"] = torch.as_tensor(np.ascontiguousarray(image.transpose(2, 0, 1)))172        if sem_seg_gt is not None:173            dataset_dict["sem_seg"] = torch.as_tensor(sem_seg_gt.astype("long"))174 175        # USER: Remove if you don't use pre-computed proposals.176        # Most users would not need this feature.177        if self.proposal_topk is not None:178            utils.transform_proposals(179                dataset_dict, image_shape, transforms, proposal_topk=self.proposal_topk180            )181 182        if not self.is_train:183            # USER: Modify this if you want to keep them for some reason.184            dataset_dict.pop("annotations", None)185            dataset_dict.pop("sem_seg_file_name", None)186            return dataset_dict187 188        if "annotations" in dataset_dict:189            self._transform_annotations(dataset_dict, transforms, image_shape)190 191        return dataset_dict192