Data & convert¶
Bring a YOLO detection dataset into the COCO layout DFINE.train(data=...) and
DFINE.val(data=...) consume — no manual reshuffling.
The two layouts¶
YOLO stores one .txt per image (class cx cy w h, normalized, class 0-indexed), with
images under images/<split>/ and labels under the mirror labels/<split>/:
yolo/
images/{train,val}/*.jpg
labels/{train,val}/*.txt
data.yaml # optional: class names + split paths
yolo_to_coco writes the COCO layout D-FINE trains on:
Category ids stay 0-indexed (= the YOLO class id), so they line up with the model's
contiguous labels under the default remap_mscoco_category=False.
Quickstart¶
from dfine import yolo_to_coco
written = yolo_to_coco("yolo/", "coco/")
# {"train": "coco/annotations/instances_train.json", "val": ".../instances_val.json"}
Then train straight on the output:
from dfine import DFINE
import json
num_classes = len(json.load(open(written["train"]))["categories"])
model = DFINE(size="s", num_classes=num_classes, imgsz=640)
model.train(data="coco/", epochs=100)
Or from the shell:
Where splits and class names come from¶
- Class names: an explicit
class_names=[...]wins; otherwisedata.yaml'snames(list or{id: name}dict) is used; otherwise names are inferred asclass_<i>from the label ids. - Splits: an explicit
splits={...}wins; otherwise thetrain/val/testpaths declared indata.yamlare used (resolved relative to the yaml, including the common Roboflow../valid/imagesform); otherwise folders are auto-detected (images/<split>and<split>/images, withvalid/validationaccepted as val-split aliases). A split declared indata.yamlbut not found on disk, or a missingvalsplit, logs a warning instead of being silently dropped.
Roboflow / Ultralytics exports
These declare their splits in data.yaml (often val: ../valid/images) and name the
validation folder valid. yolo_to_coco reads those paths and folder aliases
directly, so a stock Roboflow export converts both splits with no extra flags.
Common variations¶
# Explicit class names (skip data.yaml)
yolo_to_coco("yolo/", "coco/", class_names=["cat", "dog", "bird"])
# Point at split image dirs yourself (relative to the root, or absolute)
yolo_to_coco("yolo/", "coco/", splits={"train": "images/train", "val": "images/val"})
# Symlink images instead of copying (saves disk on large datasets)
yolo_to_coco("yolo/", "coco/", copy_images=False)
# Rename the output split folders
yolo_to_coco("yolo/", "coco/", split_names={"train": "train2017", "val": "val2017"})
Segmentation-style rows (a class id followed by polygon points) are accepted too — their
bounding box is derived. The converter is torch-free (only needs Pillow for image sizes,
and PyYAML to read a data.yaml).
API¶
dfine.convert.yolo_to_coco ¶
yolo_to_coco(yolo_root: str | PathLike, output_dir: str | PathLike, *, class_names: list[str] | None = None, splits: dict[str, str] | None = None, copy_images: bool = True, split_names: dict[str, str] | None = None) -> dict[str, str]
Convert a YOLO detection dataset to the COCO layout under output_dir.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
yolo_root
|
str | PathLike
|
dataset root (with |
required |
output_dir
|
str | PathLike
|
where the COCO |
required |
class_names
|
list[str] | None
|
class names (index = class id). Falls back to |
None
|
splits
|
dict[str, str] | None
|
explicit |
None
|
copy_images
|
bool
|
copy images (default) or symlink them into the output. |
True
|
split_names
|
dict[str, str] | None
|
override the split→folder map (default |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
|