code: def generate_images_annotations_json(
      main_dir, metadata_dir, subset, cls_index, version="v4"
  ):
      validation_image_ids = {}
  
      if version == "v4":
          annotations_path = os.path.join(
              metadata_dir,
              subset,
              "{}-annotations-bbox.csv".format(subset),
          )
      elif version == "challenge2018":
          validation_image_ids_path = os.path.join(
              metadata_dir, "challenge-2018-image-ids-valset-od.csv"
          )
  
          with open(validation_image_ids_path, "r") as csv_file:
              reader = csv.DictReader(csv_file, fieldnames=["ImageID"])
              next(reader)
              for line, row in enumerate(reader):
                  image_id = row["ImageID"]
                  validation_image_ids[image_id] = True
  
          annotations_path = os.path.join(
              metadata_dir, "challenge-2018-train-annotations-bbox.csv"
          )
      else:
          annotations_path = os.path.join(
              metadata_dir, subset, "annotations-human-bbox.csv"
          )
  
      fieldnames = [
          "ImageID",
          "Source",
          "LabelName",
          "Confidence",
          "XMin",
          "XMax",
          "YMin",
          "YMax",
          "IsOccluded",
          "IsTruncated",
          "IsGroupOf",
          "IsDepiction",
          "IsInside",
      ]
  
      id_annotations = dict()
      with open(annotations_path, "r") as csv_file:
          reader = csv.DictReader(csv_file, fieldnames=fieldnames)
          next(reader)
  
          images_sizes = {}
          for line, row in enumerate(reader):
              frame = row["ImageID"]
  
              if version == "challenge2018":
                  if subset == "train":
                      if frame in validation_image_ids:
                          continue
                  elif subset == "validation":
                      if frame not in validation_image_ids:
                          continue
                  else:
                      raise NotImplementedError(
                          "This generator handles only the train and validation subsets"
                      )
  
              class_name = row["LabelName"]
  
              if class_name not in cls_index:
                  continue
  
              cls_id = cls_index[class_name]
  
              if version == "challenge2018":
                  # We recommend participants to use the provided subset of the training set as a validation set.
                  # This is preferable over using the V4 val/test sets, as the training set is more densely annotated.
                  img_path = os.path.join(
                      main_dir, "images", "train", frame + ".jpg"
                  )
              else:
                  img_path = os.path.join(
                      main_dir, "images", subset, frame + ".jpg"
                  )
  
              if frame in images_sizes:
                  width, height = images_sizes[frame]
              else:
                  try:
                      with Image.open(img_path) as img:
                          width, height = img.width, img.height
                          images_sizes[frame] = (width, height)
                  except Exception as ex:
                      if version == "challenge2018":
                          raise ex
                      continue
  
              x1 = float(row["XMin"])
              x2 = float(row["XMax"])
              y1 = float(row["YMin"])
              y2 = float(row["YMax"])
  
              x1_int = int(round(x1 * width))
              x2_int = int(round(x2 * width))
              y1_int = int(round(y1 * height))
              y2_int = int(round(y2 * height))
  
              # Check that the bounding box is valid.
              if x2 <= x1:
                  raise ValueError(
                      "line {}: x2 ({}) must be higher than x1 ({})".format(
                          line, x2, x1
                      )
                  )
              if y2 <= y1:
                  raise ValueError(
                      "line {}: y2 ({}) must be higher than y1 ({})".format(
                          line, y2, y1
                      )
                  )
  
              if y2_int == y1_int:
                  warnings.warn(
                      "filtering line {}: rounding y2 ({}) and y1 ({}) makes them equal".format(
                          line, y2, y1
                      )
                  )
                  continue
  
              if x2_int == x1_int:
                  warnings.warn(
                      "filtering line {}: rounding x2 ({}) and x1 ({}) makes them equal".format(
                          line, x2, x1
                      )
                  )
                  continue
  
              img_id = row["ImageID"]
              annotation = {
                  "cls_id": cls_id,
                  "x1": x1,
                  "x2": x2,
                  "y1": y1,
                  "y2": y2,
              }
  
              if img_id in id_annotations:
                  annotations = id_annotations[img_id]
                  annotations["boxes"].append(annotation)
              else:
                  id_annotations[img_id] = {
                      "w": width,
                      "h": height,
                      "boxes": [annotation],
                  }
      return id_annotations
  
imports: import csv
  import json
  import os
  import warnings
  import numpy
  from PIL import Image
  from .generator import Generator
  from ..utils.image import read_image_bgr
label_desc: Use image node_id 5 for calling a global function with example usage: generate_images_annotations_json(main_dir, metadata_dir, subset, cls_index, version) and returns: id_annotations