text: """
  Given a json output file, after running evaluation scripts, this can produce the
  qualitative results
  """
  import argparse
  import json
  import os
  from collections import defaultdict
  from PIL import Image
  import cv2
  import numpy as np
  import torch
  import tqdm
  from detectron2.data import DatasetCatalog
  from detectron2.data import MetadataCatalog
  from detectron2.structures import BoxMode
  from detectron2.structures import Boxes
  from detectron2.structures import Instances
  import matplotlib.colors as mplc
  import matplotlib as mpl    
  from detectron2.utils.logger import setup_logger
  from detectron2.utils.visualizer import (
      Visualizer,
      _create_text_labels,
      GenericMask,
      ColorMode,
      VisImage,
      _SMALL_OBJECT_AREA_THRESH,
      random_color,
  )
  from fvcore.common.file_io import PathManager
  
  from immi_dataset import register_dataset
  # from immi_dataset import register_dataset
  
  register_dataset(combined_train_val=False)
  
  
  class CustomVisualizer(Visualizer):
      def __init__(self, img_rgb, metadata=None, scale=1.0, instance_mode=ColorMode.IMAGE):
          """
          Args:
              img_rgb: a numpy array of shape (H, W, C), where H and W correspond to
                  the height and width of the image respectively. C is the number of
                  color channels. The image is required to be in RGB format since that
                  is a requirement of the Matplotlib library. The image is also expected
                  to be in the range [0, 255].
              metadata (Metadata): image metadata.
              instance_mode (ColorMode): defines one of the pre-defined style for drawing
                  instances on an image.
          """
          self.img = np.asarray(img_rgb).clip(0, 255).astype(np.uint8)
          if metadata is None:
              metadata = MetadataCatalog.get("__nonexist__")
          self.metadata = metadata
          self.output = VisImage(self.img, scale=scale)
          self.cpu_device = torch.device("cpu")
  
          # too small texts are useless, therefore clamp to 9
          self._default_font_size = max(np.sqrt(self.output.height * self.output.width) // 50, 10 // scale)
          self._instance_mode = instance_mode
  
      def draw_polygon(self, segment, color, edge_color=None, alpha=0.5,linestyle='dashed'):
          """
          Args:
              segment: numpy array of shape Nx2, containing all the points in the polygon.
              color: color of the polygon. Refer to `matplotlib.colors` for a full list of
                  formats that are accepted.
              edge_color: color of the polygon edges. Refer to `matplotlib.colors` for a
                  full list of formats that are accepted. If not provided, a darker shade
                  of the polygon color will be used instead.
              alpha (float): blending efficient. Smaller values lead to more transparent masks.
  
          Returns:
              output (VisImage): image object with polygon drawn.
          """
          if edge_color is None:
              # make edge color darker than the polygon color
              if alpha > 0.8:
                  edge_color = self._change_color_brightness(color, brightness_factor=-0.7)
              else:
                  edge_color = color
          edge_color = mplc.to_rgb(edge_color) + (1,)
  
          polygon = mpl.patches.Polygon(
              segment,
              fill=True,
              facecolor=mplc.to_rgb(color) + (alpha,),
              edgecolor=edge_color,
              linestyle=linestyle,
              linewidth=max(self._default_font_size // 15 * self.output.scale, 2)
              # linewidth=2
          )
          self.output.ax.add_patch(polygon)
          return self.output
  
      def draw_instance_predictions(self, predictions):
          """
          Draw instance-level prediction results on an image.
  
          Args:
              predictions (Instances): the output of an instance detection/segmentation
                  model. Following fields will be used to draw:
                  "pred_boxes", "pred_classes", "scores", "pred_masks" (or "pred_masks_rle").
  
          Returns:
              output (VisImage): image object with visualizations.
          """
          boxes = None
          scores = None
          labels=None
          classes = predictions.pred_classes if predictions.has("pred_classes") else None
          # labels = _create_text_labels(classes, scores, ["Hv", "Hp", "CLS", "BL", "PD", "PB", "CC", "LM", "D/P"])
          # labels = _create_text_labels(classes, scores, ["PB"])
          keypoints = predictions.pred_keypoints if predictions.has("pred_keypoints") else None
          if predictions.has("pred_masks"):
              masks = np.asarray(predictions.pred_masks)
              masks = [GenericMask(x, self.output.height, self.output.width) for x in masks]
          else:
              masks = None
  
          if self._instance_mode == ColorMode.SEGMENTATION and self.metadata.get("thing_colors"):
              colors = [self._jitter([x / 255 for x in self.metadata.thing_colors[c]]) for c in classes]
              alpha = 0.8
          else:
              colors = None
              alpha = 0
  
          if self._instance_mode == ColorMode.IMAGE_BW:
              self.output.img = self._create_grayscale_image(
                  (predictions.pred_masks.any(dim=0) > 0).numpy() if predictions.has("pred_masks") else None
              )
              alpha = 0.3
          # colors=(1.0, 1.0, 1.0)
          self.overlay_instances(
              masks=masks,
              boxes=boxes,
              labels=labels,
              keypoints=keypoints,
              assigned_colors=colors,
              alpha=alpha,
              linestyle = 'solid'
          )
          return self.output
  
  
      def draw_dataset_dict(self, dic):
          """
          Draw annotations/segmentaions in Detectron2 Dataset format.
  
          Args:
              dic (dict): annotation/segmentation data of one image, in Detectron2 Dataset format.
  
          Returns:
              output (VisImage): image object with visualizations.
          """
          annos = dic.get("annotations", None)
          if annos:
              if "segmentation" in annos[0]:
                  masks = [x["segmentation"] for x in annos]
              else:
                  masks = None
              if "keypoints" in annos[0]:
                  keypts = [x["keypoints"] for x in annos]
                  keypts = np.array(keypts).reshape(len(annos), -1, 3)
              else:
                  keypts = None
  
              boxes = [
                  BoxMode.convert(x["bbox"], x["bbox_mode"], BoxMode.XYXY_ABS) if len(x["bbox"]) == 4 else x["bbox"]
                  for x in annos
              ]
  
              colors = None
              category_ids = [x["category_id"] for x in annos]
              if self._instance_mode == ColorMode.SEGMENTATION and self.metadata.get("thing_colors"):
                  colors = [self._jitter([x / 255 for x in self.metadata.thing_colors[c]]) for c in category_ids]
              names = self.metadata.get("thing_classes", None)
              labels = None
              labels = _create_text_labels(
                  category_ids,
                  scores=None,
                  class_names=["PB"],
                  # is_crowd=[x.get("iscrowd", 0) for x in annos],
              )
              boxes = None
              alpha = 0
              # colors=[(1.0,0.0,0.0)]*99
              # colors=['c'] * 99
              linestyle='dashed'
              self.overlay_instances(
                  labels=labels, boxes=boxes, masks=masks, keypoints=keypts, assigned_colors=colors, alpha=alpha,linestyle='dashed'
              )
  
          sem_seg = dic.get("sem_seg", None)
          if sem_seg is None and "sem_seg_file_name" in dic:
              with PathManager.open(dic["sem_seg_file_name"], "rb") as f:
                  sem_seg = Image.open(f)
                  sem_seg = np.asarray(sem_seg, dtype="uint8")
          if sem_seg is not None:
              self.draw_sem_seg(sem_seg, area_threshold=0, alpha=0.5)
  
          pan_seg = dic.get("pan_seg", None)
          if pan_seg is None and "pan_seg_file_name" in dic:
              with PathManager.open(dic["pan_seg_file_name"], "rb") as f:
                  pan_seg = Image.open(f)
                  pan_seg = np.asarray(pan_seg)
                  from panopticapi.utils import rgb2id
  
                  pan_seg = rgb2id(pan_seg)
          if pan_seg is not None:
              segments_info = dic["segments_info"]
              pan_seg = torch.Tensor(pan_seg)
              self.draw_panoptic_seg(pan_seg, segments_info, area_threshold=0, alpha=0.5)
          return self.output
  
      def overlay_instances(
          self, *, boxes=None, labels=None, masks=None, keypoints=None, assigned_colors=None, alpha=0.5,linestyle
      ):
          """
          Args:
              boxes (Boxes, RotatedBoxes or ndarray): either a :class:`Boxes`,
                  or an Nx4 numpy array of XYXY_ABS format for the N objects in a single image,
                  or a :class:`RotatedBoxes`,
                  or an Nx5 numpy array of (x_center, y_center, width, height, angle_degrees) format
                  for the N objects in a single image,
              labels (list[str]): the text to be displayed for each instance.
              masks (masks-like object): Supported types are:
  
                  * :class:`detectron2.structures.PolygonMasks`,
                    :class:`detectron2.structures.BitMasks`.
                  * list[list[ndarray]]: contains the segmentation masks for all objects in one image.
                    The first level of the list corresponds to individual instances. The second
                    level to all the polygon that compose the instance, and the third level
                    to the polygon coordinates. The third level should have the format of
                    [x0, y0, x1, y1, ..., xn, yn] (n >= 3).
                  * list[ndarray]: each ndarray is a binary mask of shape (H, W).
                  * list[dict]: each dict is a COCO-style RLE.
              keypoints (Keypoint or array like): an array-like object of shape (N, K, 3),
                  where the N is the number of instances and K is the number of keypoints.
                  The last dimension corresponds to (x, y, visibility or score).
              assigned_colors (list[matplotlib.colors]): a list of colors, where each color
                  corresponds to each mask or box in the image. Refer to 'matplotlib.colors'
                  for full list of formats that the colors are accepted in.
  
          Returns:
              output (VisImage): image object with visualizations.
          """
          num_instances = None
          if boxes is not None:
              boxes = self._convert_boxes(boxes)
              num_instances = len(boxes)
          if masks is not None:
              masks = self._convert_masks(masks)
              if num_instances:
                  assert len(masks) == num_instances
              else:
                  num_instances = len(masks)
          if keypoints is not None:
              if num_instances:
                  assert len(keypoints) == num_instances
              else:
                  num_instances = len(keypoints)
              keypoints = self._convert_keypoints(keypoints)
          if labels is not None:
              assert len(labels) == num_instances
          if assigned_colors is None:
              assigned_colors = [random_color(rgb=True, maximum=1) for _ in range(num_instances)]
          if num_instances == 0:
              return self.output
          if boxes is not None and boxes.shape[1] == 5:
              return self.overlay_rotated_instances(boxes=boxes, labels=labels, assigned_colors=assigned_colors)
  
          # Display in largest to smallest order to reduce occlusion.
          areas = None
          if boxes is not None:
              areas = np.prod(boxes[:, 2:] - boxes[:, :2], axis=1)
          elif masks is not None:
              areas = np.asarray([x.area() for x in masks])
  
          if areas is not None:
              sorted_idxs = np.argsort(-areas).tolist()
              # Re-order overlapped instances in descending order.
              boxes = boxes[sorted_idxs] if boxes is not None else None
              labels = [labels[k] for k in sorted_idxs] if labels is not None else None
              masks = [masks[idx] for idx in sorted_idxs] if masks is not None else None
              assigned_colors = [assigned_colors[idx] for idx in sorted_idxs]
              keypoints = keypoints[sorted_idxs] if keypoints is not None else None
  
          for i in range(num_instances):
              # if sorted_idxs[i] != 5:
              #     continue
              color = assigned_colors[i]
              if boxes is not None:
                  self.draw_box(boxes[i], edge_color=color)
  
              if masks is not None:
                  for segment in masks[i].polygons:
                      self.draw_polygon(segment.reshape(-1, 2), color, alpha=alpha,linestyle=linestyle)
  
              if labels is not None:
                  # first get a box
                  if boxes is not None:
                      x0, y0, x1, y1 = boxes[i]
                      text_pos = (x0, y0)  # if drawing boxes, put text on the box corner.
                      horiz_align = "left"
                  elif masks is not None:
                      # skip small mask without polygon
                      if len(masks[i].polygons) == 0:
                          continue
  
                      x0, y0, x1, y1 = masks[i].bbox()
  
                      # draw text in the center (defined by median) when box is not drawn
                      # median is less sensitive to outliers.
                      text_pos = np.median(masks[i].mask.nonzero(), axis=1)[::-1]
                      horiz_align = "center"
                  else:
                      continue  # drawing the box confidence for keypoints isn't very useful.
                  # for small objects, draw text at the side to avoid occlusion
                  instance_area = (y1 - y0) * (x1 - x0)
                  if instance_area < _SMALL_OBJECT_AREA_THRESH * self.output.scale or y1 - y0 < 40 * self.output.scale:
                      if y1 >= self.output.height - 5:
                          text_pos = (x1, y0)
                      else:
                          text_pos = (x0, y1)
  
                  height_ratio = (y1 - y0) / np.sqrt(self.output.height * self.output.width)
                  lighter_color = self._change_color_brightness(color, brightness_factor=0.7)
                  font_size = np.clip((height_ratio - 0.02) / 0.08 + 1, 1.2, 2) * 0.5 * self._default_font_size
                  text_pos = (x0, (y0 + y1) / 2)
                  # lighter_color = (1.0, 1.0, 1.0)
                  self.draw_text(
                      labels[i],
                      text_pos,
                      color=lighter_color,
                      horizontal_alignment=horiz_align,
                      font_size=font_size,
                  )
  
          # draw keypoints
          if keypoints is not None:
              for keypoints_per_instance in keypoints:
                  self.draw_and_connect_keypoints(keypoints_per_instance)
  
          return self.output
  
  
  def create_instances(predictions, image_size):
      ret = Instances(image_size)
  
      score = np.asarray([x["score"] for x in predictions])
      chosen = (score > args.conf_threshold).nonzero()[0]
      score = score[chosen]
      bbox = np.asarray([predictions[i]["bbox"] for i in chosen]).reshape(-1, 4)
      bbox = BoxMode.convert(bbox, BoxMode.XYWH_ABS, BoxMode.XYXY_ABS)
  
      labels = np.asarray([dataset_id_map(predictions[i]["category_id"]) for i in chosen])
  
      ret.scores = score
      ret.pred_boxes = Boxes(bbox)
      ret.pred_classes = labels
  
      try:
          ret.pred_masks = [predictions[i]["segmentation"] for i in chosen]
      except KeyError:
          pass
      return ret
  
  
  if __name__ == "__main__":
      parser = argparse.ArgumentParser(
          description="A script that visualizes the json predictions from COCO or LVIS dataset."
      )
      parser.add_argument("--inputs", required=True, nargs="+", help="JSON file produced by the model")
      parser.add_argument("--output", required=True, help="output directory")
      parser.add_argument("--dataset", help="name of the dataset", default="indiscapes_val")
      parser.add_argument("--conf-threshold", default=0.5, type=float, help="confidence threshold")
      args = parser.parse_args()
  
      logger = setup_logger()
  
      predictions = list()
      for input in args.inputs:
          with PathManager.open(input, "r") as f:
              predictions.append(json.load(f))
  
      pred_by_input = list(defaultdict(list))
      for prediction in predictions:
          pred_by_image = defaultdict(list)
          for p in prediction:
              pred_by_image[p["image_id"]].append(p)
          pred_by_input.append(pred_by_image)
  
      dicts = list(DatasetCatalog.get(args.dataset))
      metadata = MetadataCatalog.get(args.dataset)
  
      if hasattr(metadata, "thing_dataset_id_to_contiguous_id"):
  
          def dataset_id_map(ds_id):
              return metadata.thing_dataset_id_to_contiguous_id[ds_id]
  
      elif "lvis" in args.dataset:
  
          def dataset_id_map(ds_id):
              return ds_id - 1
  
      elif "indiscapes" in args.dataset:
  
          def dataset_id_map(ds_id):
              return ds_id
  
      else:
          raise ValueError(f"Unsupported dataset: {args.dataset}")
  
      os.makedirs(args.output, exist_ok=True)
  
      for dic in tqdm.tqdm(dicts):
          img = cv2.imread(dic["file_name"], cv2.IMREAD_COLOR)[:, :, ::-1]
          basename = os.path.basename(dic["file_name"])
  
          vis_preds = list()
          for pred_by_image in pred_by_input:
              predictions = create_instances(pred_by_image[dic["image_id"]], img.shape[:2])
  
              vis = CustomVisualizer(img, metadata)
              vis_pred = vis.draw_instance_predictions(predictions).get_image()
              vis_preds.append(vis_pred)
  
          vis = CustomVisualizer(vis_pred, metadata)
          # vis_gt= vis.draw_instance_predictions(dic['annotations'][0]).get_image()
          vis_gt = vis.draw_dataset_dict(dic).get_image()
          # stitched_image = np.vstack((vis_gt, np.vstack(vis_preds)))
          filename = f"{os.path.splitext('_'.join(dic['file_name'].split('/')[-3:]))[0]}.jpg"
          cv2.imwrite(os.path.join(args.output, filename), vis_gt[:, :, ::-1])
          # cv2.imshow("img", stitched_image)
          # cv2.waitKey(0)
          # cv2.destroyAllWindows()
  