code: def prepare_panoptic_annotations(dataset_dir: str):
      dataset_dir = Path(dataset_dir)
  
      for name, dirname in [
          ("train", "training"),
          ("val", "validation"),
      ]:
          image_dir = dataset_dir / "images" / dirname
          semantic_dir = dataset_dir / "annotations" / dirname
          instance_dir = dataset_dir / "annotations_instance" / dirname
  
          # folder to store panoptic PNGs
          out_folder = dataset_dir / f"ade20k_panoptic_{name}"
          # json with segmentations information
          out_file = dataset_dir / f"ade20k_panoptic_{name}.json"
  
          mkdir_or_exist(out_folder)
  
          # catid mapping
          neworder_categories = []
          all_classes = ORIGINAL_CATEGORIES
          thing_classes = ADE20KPanopticDataset.METAINFO[
              "thing_classes"
          ]
          stuff_classes = ADE20KPanopticDataset.METAINFO[
              "stuff_classes"
          ]
          palette = ADE20KPanopticDataset.METAINFO["palette"]
  
          old_2_new_mapping = {}
          new_2_old_mapping = {}
          for i, t in enumerate(thing_classes):
              j = list(all_classes).index(t)
              old_2_new_mapping[j] = i
              new_2_old_mapping[i] = j
  
          for i, t in enumerate(stuff_classes):
              j = list(all_classes).index(t)
              old_2_new_mapping[j] = i + len(thing_classes)
              new_2_old_mapping[i + len(thing_classes)] = j
  
          for old, new in old_2_new_mapping.items():
              neworder_categories.append(
                  {
                      "id": new,
                      "name": all_classes[old],
                      "isthing": int(new < len(thing_classes)),
                      "color": palette[new],
                  }
              )
          categories_dict = {
              cat["id"]: cat for cat in neworder_categories
          }
  
          panoptic_json_categories = neworder_categories[:]
          panoptic_json_images = []
          panoptic_json_annotations = []
  
          filenames = sorted(list(image_dir.iterdir()))
          progressbar = ProgressBar(len(filenames))
          for filename in filenames:
              panoptic_json_image = {}
  
              image_id = filename.stem
  
              panoptic_json_image["id"] = image_id
              panoptic_json_image["file_name"] = filename.name
  
              original_format = np.array(Image.open(filename))
              panoptic_json_image["height"] = original_format.shape[0]
              panoptic_json_image["width"] = original_format.shape[1]
  
              pan_seg = np.zeros(
                  (
                      original_format.shape[0],
                      original_format.shape[1],
                      3,
                  ),
                  dtype=np.uint8,
              )
              id_generator = IdGenerator(categories_dict)
  
              filename_semantic = semantic_dir / f"{image_id}.png"
              filename_instance = instance_dir / f"{image_id}.png"
  
              sem_seg = np.array(Image.open(filename_semantic))
              ins_seg = np.array(Image.open(filename_instance))
  
              assert sem_seg.dtype == np.uint8
              assert ins_seg.dtype == np.uint8
  
              semantic_cat_ids = sem_seg - 1
              instance_cat_ids = ins_seg[..., 0] - 1
              # instance id starts from 1!
              # because 0 is reserved as VOID label
              instance_ins_ids = ins_seg[..., 1]
  
              segm_info = []
  
              # process stuffs
              for semantic_cat_id in np.unique(semantic_cat_ids):
                  if semantic_cat_id == 255:
                      continue
                  if (
                      categories_dict[
                          old_2_new_mapping[int(semantic_cat_id)]
                      ]["isthing"]
                      == 1
                  ):
                      continue
                  mask = semantic_cat_ids == semantic_cat_id
                  # should not have any overlap
                  assert pan_seg[mask].sum() == 0
  
                  segment_id, color = id_generator.get_id_and_color(
                      old_2_new_mapping[int(semantic_cat_id)]
                  )
                  pan_seg[mask] = color
  
                  area = np.sum(mask)
                  # bbox computation for a segment
                  hor = np.sum(mask, axis=0)
                  hor_idx = np.nonzero(hor)[0]
                  x = hor_idx[0]
                  width = hor_idx[-1] - x + 1
                  vert = np.sum(mask, axis=1)
                  vert_idx = np.nonzero(vert)[0]
                  y = vert_idx[0]
                  height = vert_idx[-1] - y + 1
                  bbox = [int(x), int(y), int(width), int(height)]
  
                  segm_info.append(
                      {
                          "id": int(segment_id),
                          "category_id": old_2_new_mapping[
                              int(semantic_cat_id)
                          ],
                          "area": int(area),
                          "bbox": bbox,
                          "iscrowd": 0,
                      }
                  )
  
              # process things
              for thing_id in np.unique(instance_ins_ids):
                  if thing_id == 0:
                      continue
                  mask = instance_ins_ids == thing_id
  
                  instance_cat_id = np.unique(instance_cat_ids[mask])
                  assert len(instance_cat_id) == 1
  
                  segment_id, color = id_generator.get_id_and_color(
                      instance_cat_id[0]
                  )
                  pan_seg[mask] = color
  
                  area = np.sum(mask)
                  # bbox computation for a segment
                  hor = np.sum(mask, axis=0)
                  hor_idx = np.nonzero(hor)[0]
                  x = hor_idx[-1] - x + 1
                  width = hor_idx[-1] - x + 1
                  vert = np.sum(mask, axis=1)
                  vert_idx = np.nonzero(vert)[0]
                  y = vert_idx[0]
                  height = vert_idx[-1] - y + 1
                  bbox = [int(x), int(y), int(width), int(height)]
  
                  segm_info.append(
                      {
                          "id": int(segment_id),
                          "category_id": int(instance_cat_id[0]),
                          "area": int(area),
                          "bbox": bbox,
                          "iscrowd": 0,
                      }
                  )
  
              panoptic_json_annotation = {
                  "image_id": image_id,
                  "file_name": image_id + ".png",
                  "segments_info": segm_info,
              }
  
              Image.fromarray(pan_seg).save(
                  out_folder / f"{image_id}.png"
              )
  
              panoptic_json_images.append(panoptic_json_image)
              panoptic_json_annotations.append(panoptic_json_annotation)
  
              progressbar.update()
  
          panoptic_json = {
              "images": panoptic_json_images,
              "annotations": panoptic_json_annotations,
              "categories": panoptic_json_categories,
          }
          save_json(panoptic_json, out_file)
  
file_path: mmdetection/tools/dataset_converters/ade20k2coco.py
imports: import argparse
  import json
  import os
  from pathlib import Path
  import numpy
  import pycocotools.mask
  from mmengine.utils import ProgressBar, mkdir_or_exist
  from panopticapi.utils import IdGenerator, save_json
  from PIL import Image
  from mmdet.datasets.ade20k import ADE20KPanopticDataset
label_desc: Use image node_id 3 for calling a global function with example usage: prepare_panoptic_annotations(dataset_dir) without return types