Generate examples as dicts.

    Args:
      image_dir: `str`, directory containing the images
      annotation_dir: `str`, directory containing
      split_type: `str`, <split_name><year> (ex: train2014)
      has_annotation: `bool`, when False (for the testing set), the annotations
        are not recorded

    Yields:
      Generator yielding the next samples

def _generate_examples(
      self, image_dir, annotation_dir, split_type, has_annotation=True):
    """Generate examples as dicts.

    Args:
      image_dir: `str`, directory containing the images
      annotation_dir: `str`, directory containing
      split_type: `str`, <split_name><year> (ex: train2014)
      has_annotation: `bool`, when False (for the testing set), the annotations
        are not recorded

    Yields:
      Generator yielding the next samples
    """
    if has_annotation:
      instance_filename = "instances_{}.json"
    else:
      instance_filename = "image_info_{}.json"

    # Load the label names and images
    instance_path = os.path.join(
        annotation_dir,
        "annotations",
        instance_filename.format(split_type),
    )
    coco_annotation = CocoAnnotation(instance_path)
    # Each category is a dict:
    # {
    #    'id': 51,  # From 1-91, some entry missing
    #    'name': 'bowl',
    #    'supercategory': 'kitchen',
    # }
    categories = coco_annotation.categories
    # Each image is a dict:
    # {
    #     'id': 262145,
    #     'file_name': 'COCO_train2014_000000262145.jpg'
    #     'flickr_url': 'http://farm8.staticflickr.com/7187/xyz.jpg',
    #     'coco_url': 'http://images.cocodataset.org/train2014/xyz.jpg',
    #     'license': 2,
    #     'date_captured': '2013-11-20 02:07:55',
    #     'height': 427,
    #     'width': 640,
    # }
    images = coco_annotation.images

    # TODO(b/121375022): ClassLabel names should also contains 'id' and
    # and 'supercategory' (in addition to 'name')
    # Warning: As Coco only use 80 out of the 91 labels, the c['id'] and
    # dataset names ids won't match.
    self.info.features["objects"]["label"].names = [
        c["name"] for c in categories
    ]
    # TODO(b/121375022): Conversion should be done by ClassLabel
    categories_id2name = {c["id"]: c["name"] for c in categories}

    # Iterate over all images
    annotation_skipped = 0
    for image_info in sorted(images, key=lambda x: x["id"]):
      if has_annotation:
        # Each instance annotation is a dict:
        # {
        #     'iscrowd': 0,
        #     'bbox': [116.95, 305.86, 285.3, 266.03],
        #     'image_id': 480023,
        #     'segmentation': [[312.29, 562.89, 402.25, ...]],
        #     'category_id': 58,
        #     'area': 54652.9556,
        #     'id': 86,
        # }
        instances = coco_annotation.get_annotations(img_id=image_info["id"])
      else:
        instances = []  # No annotations

      if not instances:
        annotation_skipped += 1

      def build_bbox(x, y, width, height):
        # pylint: disable=cell-var-from-loop
        # build_bbox is only used within the loop so it is ok to use image_info
        return tfds.features.BBox(
            ymin=y / image_info["height"],
            xmin=x / image_info["width"],
            ymax=(y + height) / image_info["height"],
            xmax=(x + width) / image_info["width"],
        )
        # pylint: enable=cell-var-from-loop

      yield {
          "image": os.path.join(image_dir, split_type, image_info["file_name"]),
          "image/filename": image_info["file_name"],
          "objects": [{
              "bbox": build_bbox(*instance_info["bbox"]),
              "label": categories_id2name[instance_info["category_id"]],
              "is_crowd": bool(instance_info["iscrowd"]),
          } for instance_info in instances],
      }
    logging.info(
        "%d/%d images do not contains any annotations",
        annotation_skipped,
        len(images),
    )