RegionKit Open Editor →
COCO JSON annotation export computer vision instance segmentation dataset format

How to Export Annotations to COCO JSON

Step-by-step guide to creating valid COCO JSON annotation files — using RegionKit to draw annotations and export them, with Python examples for loading and validating the output.

· RegionKit

COCO JSON is the standard format for instance detection and segmentation datasets. It’s accepted by Detectron2, MMDetection, YOLOv8, FiftyOne, and most other modern CV frameworks. Creating valid COCO JSON by hand is tedious — but drawing annotations in a tool that exports it directly takes minutes.

This guide covers the COCO format structure and shows how to export it from RegionKit.

COCO JSON structure

A COCO annotation file has three required top-level arrays:

{
  "images": [...],
  "annotations": [...],
  "categories": [...]
}

images

Each entry describes one image in the dataset:

{
  "id": 1,
  "file_name": "frame_001.jpg",
  "width": 1920,
  "height": 1080
}

annotations

Each entry describes one annotated object:

{
  "id": 1,
  "image_id": 1,
  "category_id": 1,
  "bbox": [120, 80, 200, 150],
  "segmentation": [[120, 80, 320, 80, 320, 230, 120, 230]],
  "area": 30000,
  "iscrowd": 0
}

bbox[x, y, width, height] in pixels, where (x, y) is the top-left corner. Note: this is different from YOLO (which uses centre coordinates) and different from some other formats that use [x1, y1, x2, y2].

segmentation — a list of polygon coordinate arrays, each being a flat [x0, y0, x1, y1, ...] list. For a simple (non-compound) polygon, this is a list with one element.

area — area of the annotation in pixels squared, computed from the segmentation polygon.

iscrowd0 for individual instances, 1 for crowd annotations (a group of objects annotated together).

categories

Each category defines a class:

{
  "id": 1,
  "name": "person",
  "supercategory": "human"
}

Category IDs start at 1 (not 0) in the COCO convention. This is a common source of off-by-one errors when converting to YOLO (which is 0-indexed).

Exporting from RegionKit

  1. Open RegionKit and load your image
  2. Draw bounding boxes (R) and/or polygon segmentation masks (P)
  3. Set the label for each annotation in the Properties panel — this becomes the COCO category name
  4. Click Export → COCO JSON

RegionKit generates a valid COCO file with all three arrays populated:

Loading COCO JSON in Python

import json

with open('annotations.json') as f:
    coco = json.load(f)

# Build lookup maps
img_map = {img['id']: img for img in coco['images']}
cat_map = {cat['id']: cat['name'] for cat in coco['categories']}

# Print each annotation
for ann in coco['annotations']:
    img  = img_map[ann['image_id']]
    cat  = cat_map[ann['category_id']]
    bbox = ann['bbox']
    area = ann.get('area', 0)

    print(f"[{cat}] in {img['file_name']}")
    print(f"  bbox: x={bbox[0]}, y={bbox[1]}, w={bbox[2]}, h={bbox[3]}")
    print(f"  area: {area:.0f} px²")
    if ann.get('segmentation'):
        pts = ann['segmentation'][0]
        n_vertices = len(pts) // 2
        print(f"  polygon: {n_vertices} vertices")

Loading with Detectron2

from detectron2.data.datasets import register_coco_instances
from detectron2.data import MetadataCatalog, DatasetCatalog

register_coco_instances(
    "my_dataset_train",
    {},
    "annotations/train.json",
    "images/train"
)

metadata = MetadataCatalog.get("my_dataset_train")
dataset   = DatasetCatalog.get("my_dataset_train")
print(f"Classes: {metadata.thing_classes}")
print(f"Images: {len(dataset)}")

Validating COCO JSON

The pycocotools library provides a validation and evaluation API:

from pycocotools.coco import COCO

coco = COCO('annotations.json')
print(f"Images: {len(coco.imgs)}")
print(f"Categories: {[c['name'] for c in coco.loadCats(coco.getCatIds())]}")
print(f"Annotations: {len(coco.anns)}")

If the file is malformed (missing fields, inconsistent IDs), COCO() will raise a descriptive error.

Common COCO mistakes

Category IDs starting at 0 — COCO convention uses 1-based IDs. Some tools (including RegionKit’s export) use 1-based IDs; others start at 0. If your framework errors on the first category, check whether it expects 0-based or 1-based.

bbox format confusion — COCO uses [x, y, width, height] (top-left + dimensions), not [x1, y1, x2, y2] (two corners). Converting incorrectly shifts all your annotations.

Missing area field — Some frameworks require area. RegionKit computes it from the polygon using the shoelace formula. If you’re generating COCO JSON manually, compute area as bbox_width * bbox_height (approximate) or from the actual polygon.

Empty segmentation for bounding-box-only tasks — If you’re doing detection (not segmentation), the segmentation field can be an empty list []. Some frameworks require it present; others tolerate it missing.


Related: COCO Format Guide · COCO Annotation Editor

Try RegionKit — it's free

Browser-based ROI editor. No install, no account, no data upload.

Open the Editor