text: # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
  import copy
  import os
  
  from detectron2.data import DatasetCatalog, MetadataCatalog
  
  from .coco import load_coco_json, load_sem_seg
  
  """
  This file contains functions to register a COCO-format dataset to the DatasetCatalog.
  """
  
  __all__ = ["register_coco_instances", "register_coco_panoptic_separated"]
  
  
  def register_coco_instances(name, metadata, json_file, image_root):
      """
      Register a dataset in COCO's json annotation format for
      instance detection, instance segmentation and keypoint detection.
      (i.e., Type 1 and 2 in http://cocodataset.org/#format-data.
      `instances*.json` and `person_keypoints*.json` in the dataset).
  
      This is an example of how to register a new dataset.
      You can do something similar to this function, to register new datasets.
  
      Args:
          name (str): the name that identifies a dataset, e.g. "coco_2014_train".
          metadata (dict): extra metadata associated with this dataset.  You can
              leave it as an empty dict.
          json_file (str): path to the json instance annotation file.
          image_root (str or path-like): directory which contains all the images.
      """
      assert isinstance(name, str), name
      assert isinstance(json_file, (str, os.PathLike)), json_file
      assert isinstance(image_root, (str, os.PathLike)), image_root
      # 1. register a function which returns dicts
      DatasetCatalog.register(name, lambda: load_coco_json(json_file, image_root, name))
  
      # 2. Optionally, add metadata about this dataset,
      # since they might be useful in evaluation, visualization or logging
      # MetadataCatalog.get(name).set(
      #     json_file=json_file, image_root=image_root, evaluator_type="coco", **metadata
      # )
      MetadataCatalog.get(name).set(
          json_file=json_file, image_root=image_root, evaluator_type="coco", **metadata
      )
  
  
  def register_coco_panoptic_separated(
      name, metadata, image_root, panoptic_root, panoptic_json, sem_seg_root, instances_json
  ):
      """
      Register a COCO panoptic segmentation dataset named `name`.
      The annotations in this registered dataset will contain both instance annotations and
      semantic annotations, each with its own contiguous ids. Hence it's called "separated".
  
      It follows the setting used by the PanopticFPN paper:
  
      1. The instance annotations directly come from polygons in the COCO
         instances annotation task, rather than from the masks in the COCO panoptic annotations.
  
         The two format have small differences:
         Polygons in the instance annotations may have overlaps.
         The mask annotations are produced by labeling the overlapped polygons
         with depth ordering.
  
      2. The semantic annotations are converted from panoptic annotations, where
         all "things" are assigned a semantic id of 0.
         All semantic categories will therefore have ids in contiguous
         range [1, #stuff_categories].
  
      This function will also register a pure semantic segmentation dataset
      named ``name + '_stuffonly'``.
  
      Args:
          name (str): the name that identifies a dataset,
              e.g. "coco_2017_train_panoptic"
          metadata (dict): extra metadata associated with this dataset.
          image_root (str): directory which contains all the images
          panoptic_root (str): directory which contains panoptic annotation images
          panoptic_json (str): path to the json panoptic annotation file
          sem_seg_root (str): directory which contains all the ground truth segmentation annotations.
          instances_json (str): path to the json instance annotation file
      """
      panoptic_name = name + "_separated"
      DatasetCatalog.register(
          panoptic_name,
          lambda: merge_to_panoptic(
              load_coco_json(instances_json, image_root, panoptic_name),
              load_sem_seg(sem_seg_root, image_root),
          ),
      )
      MetadataCatalog.get(panoptic_name).set(
          panoptic_root=panoptic_root,
          image_root=image_root,
          panoptic_json=panoptic_json,
          sem_seg_root=sem_seg_root,
          json_file=instances_json,  # TODO rename
          evaluator_type="coco_panoptic_seg",
          **metadata
      )
  
      semantic_name = name + "_stuffonly"
      DatasetCatalog.register(semantic_name, lambda: load_sem_seg(sem_seg_root, image_root))
      MetadataCatalog.get(semantic_name).set(
          sem_seg_root=sem_seg_root, image_root=image_root, evaluator_type="sem_seg", **metadata
      )
  
  
  def merge_to_panoptic(detection_dicts, sem_seg_dicts):
      """
      Create dataset dicts for panoptic segmentation, by
      merging two dicts using "file_name" field to match their entries.
  
      Args:
          detection_dicts (list[dict]): lists of dicts for object detection or instance segmentation.
          sem_seg_dicts (list[dict]): lists of dicts for semantic segmentation.
  
      Returns:
          list[dict] (one per input image): Each dict contains all (key, value) pairs from dicts in
              both detection_dicts and sem_seg_dicts that correspond to the same image.
              The function assumes that the same key in different dicts has the same value.
      """
      results = []
      sem_seg_file_to_entry = {x["file_name"]: x for x in sem_seg_dicts}
      assert len(sem_seg_file_to_entry) > 0
  
      for det_dict in detection_dicts:
          dic = copy.copy(det_dict)
          dic.update(sem_seg_file_to_entry[dic["file_name"]])
          results.append(dic)
      return results
  