Importing a YOLO dataset
Zip your YOLO dataset — images, .txt label files and a class list (obj.names, or names in a .yaml/.yml) — then create a project in AnnotateIt and import the archive. Detection rows become bounding boxes, longer even-length rows become polygons, and the format is detected automatically; nothing is uploaded at any point.
What the importer accepts
The import is a single .zip. Inside it, the importer looks for two things: a class list and label files. If it finds both, the archive is recognised as YOLO.
- A class list — either a file ending in obj.names (one class name per line), or a .yaml / .yml file with a names entry. Both the inline form (names: [cat, dog]) and the block form (a list, or index: name pairs) are read.
- Label files — .txt files, one per image. obj.names and obj.data themselves are skipped.
- Images — any image files in the archive are decoded and imported with their real dimensions.
- Videos — any video files found are imported as unannotated media rather than dropped, even though YOLO exports never contain them.
How label rows are read
Every line in a label file is a class index followed by numbers. The row length decides how it is interpreted:
| Row shape | Read as | Becomes |
|---|---|---|
| class cx cy w h (4 values) | Detection box, normalised to the image | A rectangle annotation |
| class x1 y1 x2 y2 … (more than 5 values, even count) | Segmentation polygon, normalised | A polygon annotation in a segmentation project |
Coordinates are multiplied back up by the real image width and height, so the imported annotation lands exactly where it was. A row whose class index is not in the class list is skipped rather than guessed at — the rest of the file still imports.
How label files are matched to images
Matching uses the label file’s path with the extension removed, not just its bare filename. That detail matters for split datasets: labels/train/img1.txt and labels/val/img1.txt are different keys, so same-named files in different split folders do not overwrite each other.
dataset.zip
├── data.yaml # names: [person, forklift, helmet]
├── images/
│ ├── train/img_0001.jpg
│ └── val/img_0002.jpg
└── labels/
├── train/img_0001.txt
└── val/img_0002.txtWhich project types a YOLO archive can create
A recognised YOLO archive offers detection, and instance segmentation as well when at least one label row is a polygon row. Classification is deliberately not offered: a YOLO object row labels a box inside the image, not the image as a whole, so presenting it as an image-level class would misread the data. Pick the project type that matches what you intend to train — the same archive can be imported as a detection project or, if it has polygons, as a segmentation project.
Step by step
- Zip the dataset — images, label files and the class list. The folder layout does not have to match the example above; the importer walks the whole archive.
- In AnnotateIt, create a project of the type you want, or start the import from the projects screen to create one from the archive.
- Import the .zip. The format is detected automatically — Datumaro, COCO, YOLO and Pascal VOC are each recognised by their own markers, and an archive with no annotation files at all is still imported as plain media.
- Check the result in the media grid: every image should show its annotation status, and opening one should show the boxes or polygons in place.
Import runs on your device. The archive is read in the app, decoded in the app, and written to local storage — no part of it is uploaded.
If the archive is not recognised as YOLO
- No class list: add an obj.names file, or a data.yaml with a names entry. Without one, the archive cannot be read as YOLO and falls back to media-only import.
- Label files present but every row is short: rows need at least four values after the class index.
- Annotations import but land on the wrong images: check that label file paths mirror image paths — the stem must match once the extension is removed.
- Classes come out shifted: the class index is a position in the class list, so the order of names in obj.names or data.yaml must match the order used when the labels were written.