text: # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
  import logging
  import os
  
  from fvcore.common.timer import Timer
  from detectron2.structures import BoxMode
  from fvcore.common.file_io import PathManager
  from detectron2.data import DatasetCatalog, MetadataCatalog
  from detectron2.engine import default_argument_parser
  
  from .lvis_v0_5_categories import LVIS_CATEGORIES
  from .lvis_categories_mapper import lvis_cate_mapper, cate_id_list
  
  """
  This file contains functions to parse LVIS-format annotations into dicts in the
  "Detectron2 format".
  """
  
  logger = logging.getLogger(__name__)
  
  __all__ = ["load_lvis_json", "register_lvis_instances", "get_lvis_instances_meta"]
  
  
  def register_lvis_instances(name, metadata, json_file, image_root):
      """
      Register a dataset in LVIS's json annotation format for instance detection and segmentation.
  
      Args:
          name (str): a name that identifies the dataset, e.g. "lvis_v0.5_train".
          metadata (dict): extra metadata associated with this dataset. It can be an empty dict.
          json_file (str): path to the json instance annotation file.
          image_root (str): directory which contains all the images.
      """
      DatasetCatalog.register(name, lambda: load_lvis_json(json_file, image_root, name))
      MetadataCatalog.get(name).set(
          json_file=json_file, image_root=image_root, evaluator_type="lvis", **metadata
      )
  
  
  def load_lvis_json(json_file, image_root, dataset_name=None, freq_reindex = False):
      """
      Load a json file in LVIS's annotation format.
  
      Args:
          json_file (str): full path to the LVIS json annotation file.
          image_root (str): the directory where the images in this json file exists.
          dataset_name (str): the name of the dataset (e.g., "lvis_v0.5_train").
              If provided, this function will put "thing_classes" into the metadata
              associated with this dataset.
  
      Returns:
          list[dict]: a list of dicts in Detectron2 standard format. (See
          `Using Custom Datasets </tutorials/datasets.html>`_ )
  
      Notes:
          1. This function does not read the image files.
             The results do not have the "image" field.
      """
      args = default_argument_parser().parse_args()
      from lvis import LVIS
  
      json_file = PathManager.get_local_path(json_file)
      fcr_mapper = lvis_cate_mapper()
      timer = Timer()
      lvis_api = LVIS(json_file)
      if timer.seconds() > 1:
          logger.info("Loading {} takes {:.2f} seconds.".format(json_file, timer.seconds()))
  
      if dataset_name is not None:
          meta = get_lvis_instances_meta(dataset_name)
          MetadataCatalog.get(dataset_name).set(**meta)
  
      # sort indices for reproducible results
      img_ids = sorted(list(lvis_api.imgs.keys()))
      # imgs is a list of dicts, each looks something like:
      # {'license': 4,
      #  'url': 'http://farm6.staticflickr.com/5454/9413846304_881d5e5c3b_z.jpg',
      #  'file_name': 'COCO_val2014_000000001268.jpg',
      #  'height': 427,
      #  'width': 640,
      #  'date_captured': '2013-11-17 05:57:24',
      #  'id': 1268}
      imgs = lvis_api.load_imgs(img_ids)
      # anns is a list[list[dict]], where each dict is an annotation
      # record for an object. The inner list enumerates the objects in an image
      # and the outer list enumerates over images. Example of anns[0]:
      # [{'segmentation': [[192.81,
      #     247.09,
      #     ...
      #     219.03,
      #     249.06]],
      #   'area': 1035.749,
      #   'image_id': 1268,
      #   'bbox': [192.81, 224.8, 74.73, 33.43],
      #   'category_id': 16,
      #   'id': 42986},
      #  ...]
      anns = [lvis_api.img_ann_map[img_id] for img_id in img_ids]
  
      # Sanity check that each annotation has a unique id
      ann_ids = [ann["id"] for anns_per_image in anns for ann in anns_per_image]
      assert len(set(ann_ids)) == len(ann_ids), "Annotation ids in '{}' are not unique".format(
          json_file
      )
  
      imgs_anns = list(zip(imgs, anns))
  
      logger.info("Loaded {} images in the LVIS format from {}".format(len(imgs_anns), json_file))
      if args.ann_reindex:
          logger.info("Note!!! Reindex 1230 classes into f, c, r 3 Classes head")
      f_id_list, c_id_list, r_id_list, _, _ = cate_id_list()
      
      dataset_dicts = []
  #     test_all = set()
  #     test_f = set()
  #     test_c = set()
  #     test_r = set()
      for (img_dict, anno_dict_list) in imgs_anns:
          record = {}
          file_name = img_dict["file_name"]
          if img_dict["file_name"].startswith("COCO"):
              # Convert form the COCO 2014 file naming convention of
              # COCO_[train/val/test]2014_000000000000.jpg to the 2017 naming convention of
              # 000000000000.jpg (LVIS v1 will fix this naming issue)
              file_name = file_name[-16:]
          record["file_name"] = os.path.join(image_root, file_name)
          record["height"] = img_dict["height"]
          record["width"] = img_dict["width"]
          record["not_exhaustive_category_ids"] = img_dict.get("not_exhaustive_category_ids", [])
          record["neg_category_ids"] = img_dict.get("neg_category_ids", [])
          image_id = record["image_id"] = img_dict["id"]
  
          objs = []
          for anno in anno_dict_list:
              # Check that the image_id in this annotation is the same as
              # the image_id we're looking at.
              # This fails only when the data parsing logic or the annotation file is buggy.
              assert anno["image_id"] == image_id
              obj = {"bbox": anno["bbox"], "bbox_mode": BoxMode.XYWH_ABS}
              obj["category_id"] = anno["category_id"] - 1  # Convert 1-indexed to 0-indexed
              obj["frequency"] = fcr_mapper[anno["category_id"]]
  
  #             logger.info("Note!!! split 1230 classes into f, c, r")
              if args.ann_reindex:
                  if obj["frequency"] == 0:
                      obj["category_id"] = f_id_list.index(obj["category_id"]+1)
  #                     test_f.add(obj["category_id"])
                  if obj["frequency"] == 1:
                      obj["category_id"] = c_id_list.index(obj["category_id"]+1)
  #                     test_c.add(obj["category_id"])
                  if obj["frequency"] == 2:
                      obj["category_id"] = r_id_list.index(obj["category_id"]+1)
  #                     test_r.add(obj["category_id"])
  
              segm = anno["segmentation"]  # list[list[float]]
              # filter out invalid polygons (< 3 points)
              valid_segm = [poly for poly in segm if len(poly) % 2 == 0 and len(poly) >= 6]
              assert len(segm) == len(
                  valid_segm
              ), "Annotation contains an invalid polygon with < 3 points"
              assert len(segm) > 0
              obj["segmentation"] = segm
              objs.append(obj)
          record["annotations"] = objs
          dataset_dicts.append(record)
      
      
  
  
      return dataset_dicts
  
  
  def get_lvis_instances_meta(dataset_name):
      """
      Load LVIS metadata.
  
      Args:
          dataset_name (str): LVIS dataset name without the split name (e.g., "lvis_v0.5").
  
      Returns:
          dict: LVIS metadata with keys: thing_classes
      """
      if "v0.5" in dataset_name:
          return _get_lvis_instances_meta_v0_5()
      # There will be a v1 in the future
      # elif dataset_name == "lvis_v1":
      #   return get_lvis_instances_meta_v1()
      raise ValueError("No built-in metadata for dataset {}".format(dataset_name))
  
  
  def _get_lvis_instances_meta_v0_5():
      assert len(LVIS_CATEGORIES) == 1230
      cat_ids = [k["id"] for k in LVIS_CATEGORIES]
      assert min(cat_ids) == 1 and max(cat_ids) == len(
          cat_ids
      ), "Category ids are not in [1, #categories], as expected"
      # Ensure that the category list is sorted by id
      lvis_categories = [k for k in sorted(LVIS_CATEGORIES, key=lambda x: x["id"])]
      thing_classes = [k["synonyms"][0] for k in lvis_categories]
      meta = {"thing_classes": thing_classes}
      return meta
  
  
  if __name__ == "__main__":
      """
      Test the LVIS json dataset loader.
  
      Usage:
          python -m detectron2.data.datasets.lvis \
              path/to/json path/to/image_root dataset_name vis_limit
      """
      import sys
      import numpy as np
      from detectron2.utils.logger import setup_logger
      from PIL import Image
      import detectron2.data.datasets  # noqa # add pre-defined metadata
      from detectron2.utils.visualizer import Visualizer
  
      logger = setup_logger(name=__name__)
      meta = MetadataCatalog.get(sys.argv[3])
  
      dicts = load_lvis_json(sys.argv[1], sys.argv[2], sys.argv[3])
      logger.info("Done loading {} samples.".format(len(dicts)))
  
      dirname = "lvis-data-vis"
      os.makedirs(dirname, exist_ok=True)
      for d in dicts[: int(sys.argv[4])]:
          img = np.array(Image.open(d["file_name"]))
          visualizer = Visualizer(img, metadata=meta)
          vis = visualizer.draw_dataset_dict(d)
          fpath = os.path.join(dirname, os.path.basename(d["file_name"]))
          vis.save(fpath)
  