Boxes come from pixels
Not from projected 3D bounds. An object mostly behind a hangar gets a box around the visible part, because the identity buffer only contains the part that was drawn.
The YOLO format is deliberately minimal: a text file per image, five numbers per object. What it does not tell you is whether those five numbers are correct. Generated from an Unreal scene they come from the engine’s own identity buffer, so the box around a half-hidden crate is the box around the half you can see.
Images and labels in parallel directory trees, matching stems, and a data.yaml at the root. That is all, and getting it slightly wrong is the most common reason a first training run reports zero objects.
dataset/
├── data.yaml
├── images/
│ ├── train/ 31 frames
│ └── val/ 9 frames
└── labels/
├── train/ one .txt per image, same stem
└── val/# data.yaml
path: .
train: images/train
val: images/val
test: images/test
nc: 6
names:
0: person
1: car
2: tank
3: container
4: crate
5: barrelOne line per object: class id, then centre x, centre y, width and height as fractions of the image size. Below is the start of a real exported file, copied verbatim.
# labels/train/dump__plugin_000004.txt
5 0.63125000 0.82546296 0.06041667 0.08055556
3 0.57317708 0.83287037 0.04739583 0.06944444
4 0.66718750 0.92685185 0.02604167 0.04629630
4 0.69609375 0.91388889 0.05260417 0.10555556Read the first line: class 5 is a barrel, sitting at 63% across and 83% down the frame, occupying 6% of the width. On a 1920×1080 image that is a 116 by 87 pixel box, near the bottom of the frame, which is exactly where the barrels are.
Four decisions that separate a dataset you can train on from a directory of text files.
Not from projected 3D bounds. An object mostly behind a hangar gets a box around the visible part, because the identity buffer only contains the part that was drawn.
Anything under 8 pixels on a side, or with an aspect ratio beyond 6:1, is rejected before export rather than exported as an unlearnable target.
Consecutive frames of one capture look nearly identical. The validator hashes images and reports near-duplicates across the train and validation split. The reference export reported zero.
Declaration order, written into data.yaml and used consistently. They do not shuffle between runs because a class happened to appear in a different order.
# export YOLO only, or both formats from one capture
nameframe dataset _out/dump _out/dataset --format yolo --val-frac 0.2
nameframe validate _out/dataset --out _out/validation
# then train
yolo detect train data=_out/dataset/data.yaml model=yolo11n.pt epochs=100 imgsz=1024Two things to look at in the export, both of which are cheaper to notice now.
The sample pack contains the images, the labels, the data.yaml, the COCO version of the same annotations, and the report that graded all of it. Download it (49 MB) and check both before writing any code.