If you work with object detection datasets, you've probably run into at least three different ways of describing the exact same thing: a box drawn around an object in an image, labeled with what it is. YOLO, COCO, Pascal VOC, and VIA CSV all solve this problem — they just disagree on how to write it down. Knowing the difference matters the moment you need to move a dataset between tools, frameworks, or teammates.
What an annotation actually is
At its core, an object detection annotation is three pieces of information tied to one image:
- What the object is (a class label — "car", "person", "defect")
- Where it is (a bounding box, or in some formats, a more precise shape)
- Which image it belongs to
Every format below stores exactly that. The differences are in file structure, coordinate system, and — for one format — whether a box is the only shape available at all.
Bounding box mechanics
A rectangular box can be described two equivalent ways:
- Two corner points — top-left
(xmin, ymin)and bottom-right(xmax, ymax) - Center point plus size —
(x_center, y_center, width, height)
Both describe the same rectangle; it's just arithmetic to convert between them. What actually trips people up is a second, independent choice: whether those numbers are pixel coordinates (tied to one specific image's resolution) or normalized coordinates (a fraction from 0 to 1, independent of resolution). A box at pixel (100, 50) in a 1000×500 image sits at normalized (0.1, 0.1) — same box, different units. This is the detail that makes YOLO annotations unusable without also knowing the image's pixel dimensions, which is exactly why converting YOLO to or from anything else needs that information supplied explicitly.
The four formats
YOLO
One plain-text file per image, sharing its filename (photo1.jpg → photo1.txt). Each line is one object:
0 0.512 0.487 0.234 0.312
That's class_id x_center y_center width height — space-separated, every coordinate normalized to [0, 1]. Class names live in a separate file (classes.txt or a YAML config), not in the annotation file itself, so a YOLO label file alone is meaningless without that mapping alongside it.
COCO
A single JSON file for the entire dataset — not one file per image. Three top-level arrays tie everything together: images, annotations, and categories. Each annotation looks like:
{ "image_id": 1, "category_id": 3, "bbox": [100, 50, 234, 156] }
bbox is [x, y, width, height] in pixel coordinates, measured from the top-left corner — not normalized, and not center-based like YOLO. Category names are defined once in the same file, so a COCO JSON is self-contained.
Pascal VOC
One XML file per image, also self-contained (it includes the image's filename and pixel dimensions in the same file):
<object>
<name>car</name>
<bndbox>
<xmin>100</xmin><ymin>50</ymin>
<xmax>334</xmax><ymax>206</ymax>
</bndbox>
</object>
Pixel coordinates again, but as two corner points (xmin/ymin/xmax/ymax) rather than COCO's corner-plus-size.
VIA CSV
A single CSV from the VGG Image Annotator tool, one row per region. This is the format that breaks the pattern: its region_shape_attributes column can describe a rectangle, but also a circle, ellipse, polygon, polyline, or single point — shapes none of the other three formats can represent at all. If you export a polygon annotation to YOLO, COCO, or Pascal VOC, it has to become something else, because those three only understand boxes.
Format comparison
| YOLO | COCO | Pascal VOC | VIA CSV | |
|---|---|---|---|---|
| File layout | One .txt per image + shared classes.txt | One .json for the whole dataset | One .xml per image | One .csv for the whole dataset |
| Coordinates | Normalized 0–1, center + size | Absolute pixels, top-left + size | Absolute pixels, two corners | Absolute pixels, shape-specific |
| Shapes supported | Rectangle only | Rectangle only | Rectangle only | Rectangle, circle, ellipse, polygon, polyline, point |
| Class names | Separate file, referenced by index | Embedded (categories array) | Embedded (<name> per object) | Embedded (region_attributes per row) |
| Self-contained? | No — needs classes.txt and the image's pixel size | Yes | Yes | Yes |
When should you use each format?
Which format you need is usually dictated by whatever's on the other end, not personal preference:
- YOLO — required if you're training a YOLO-family model (YOLOv5/v8/v11 and similar); those training scripts expect exactly this per-image
.txtlayout and won't accept anything else directly. - COCO — the default for most PyTorch-based detection frameworks (Detectron2, MMDetection, and others) and for sharing a dataset as a single portable file rather than hundreds of loose ones.
- Pascal VOC — mostly relevant if a specific pipeline or an older TensorFlow Object Detection API–style loader already expects it; not usually the first choice for a brand-new project today.
- VIA CSV — the only option when you need shapes beyond boxes (a circle around a wheel, a polygon around an irregular defect), or when you're annotating directly inside VIA and want to keep that richer shape data as long as possible before flattening it to boxes for a bounding-box-only pipeline.
If your dataset is already in one of these formats but your training pipeline expects another, that's a conversion, not a re-annotation. For a fast side-by-side without the full explanation, see YOLO vs COCO vs Pascal VOC: Annotation Format Comparison.
Where conversion fits — and what it can't preserve
Moving a dataset from one of these formats to another is mechanical for boxes: recompute the coordinate system, restructure the file layout, done. It stops being lossless the moment a non-rectangular shape is involved — a circle or polygon converted into YOLO/COCO/Pascal VOC can only become its bounding rectangle (the smallest box that contains it), and a bare point or open polyline has no meaningful bounding box at all, so it has nothing to convert to. A tool that converts silently and drops that detail is doing you a disservice; one that tells you exactly what changed and what got left out is doing the job properly. For the full walkthrough, see how to convert between YOLO, COCO, and Pascal VOC annotations.
Where visual verification fits
None of the four formats can be sanity-checked by reading the raw file — a coordinate typo, a swapped width/height, or a class ID off by one all look completely plausible as numbers and are only obvious once you see the box actually drawn on the image. That's a separate step from both creating and converting annotations, and it's easy to skip when a conversion "completes successfully" with no errors. Successfully converting a file and correctly converting a file aren't the same guarantee — see how to visually verify annotations before training for what to actually look for.
Where each step happens
- Creating annotations from scratch — draw boxes directly on your images with the Image Annotator, and export in whichever of the four formats you need. If your objects are common everyday categories, the Object Detector can draft boxes automatically first — see how to use AI object detection to speed up annotation.
- Converting between formats — the Bounding Box Converter handles all twelve directions between YOLO, COCO, Pascal VOC, and VIA CSV, and tells you upfront exactly how many regions the target format can't represent; the YOLO Dataset Converter does the same YOLO↔COCO/Pascal VOC conversion across a whole dataset folder in one batch.
- Checking a whole dataset's structure — the YOLO, COCO, and Pascal VOC Dataset Health Checkers catch malformed boxes, missing images, and duplicate or out-of-bounds annotations across an entire dataset in one pass, before you ever look at an image.
- Verifying the result visually — the Annotation Visualizer renders your annotations directly on top of the source images, so a bad conversion or a bad label is visible at a glance instead of discovered after a training run.