Annotate images for YOLO by setting the tool to YOLO export format before the first box. Draw each edge within about 5 pixels of the part's visible extent, keep a stable classes.txt, and check every exported line: class index, center x, center y, width, height, all normalized to 0-1. On a 4000 × 3000 image, a box from (1200, 900) to (1800, 1500) exports as the line 0 0.375 0.400 0.150 0.200. That line is the whole format, and this guide walks the annotation step end to end around it.
Most detection projects that disappoint on the line fail before training starts: the labels are inconsistent. One annotator includes the mating surface, the next does not. A class list changes order halfway through the set. A folder of PascalVOC XML reaches a YOLO trainer. This guide covers setting the format, drawing tight boxes, keeping classes stable, and verifying every exported file with arithmetic you can do by hand. The workflow fits images from any camera you already run; the capture side only decides how many pixels each object gets.
Which annotation tool and format do you set before the first box?
Set the export format before you draw anything. In LabelImg, now maintained as part of Label Studio, the format button to the right of Save starts on PascalVOC. Click it once until it reads YOLO: every box saved before the switch lands in XML your trainer cannot read.
The tool's own documentation describes that toolbar switch, and the same toolbar loads a whole folder of images in one action with Open/OpenDIR, so labels stay beside the images they describe. The drawing gesture is a diagonal: press at one corner of the object, drag to the opposite corner, release, and the box appears ready for its class name. That is the whole interaction. Spend thirty seconds of practice on ten images before you face two thousand.
The working loop:
- Put all training images in one folder and write classes.txt beside them, one class name per line, in the order you think of them.
- Load the folder with Open/OpenDIR so images and labels never separate.
- Click the format button until it reads YOLO.
- Draw each object with Create RectBox, corner to opposite corner.
- Type the class name exactly as spelled in classes.txt.
- Save after every image; the tool writes one same-named .txt beside each one.
How tight should a YOLO bounding box be?
Draw every edge within about 5 pixels of the object's visible edge — roughly 0.1% of a 4000-pixel-wide image — and include none of the neighboring part. YOLO learns where an object ends from your boxes, and every loose edge trains background in as object.
The arithmetic shows why the tolerance matters. On a part that is 600 × 600 px, a 5 px margin on each side gives a 610 × 610 box: 372,100 px² against 360,000 px², about 3.4% extra background, acceptable. A 25 px margin gives a 650 × 650 box, 422,500 px², about 17% background riding along as object; across two thousand images the detector's idea of the part swells by that much. The tolerance cuts the other way too: keep 2-3 px of background rather than clip visible part pixels. A box that amputates the part in half your images teaches a variable, unreliable extent. If two people annotate, agree the edge rule on the same ten images before splitting the set; diverging edge habits are invisible in the files and obvious in the predictions.
How many pixels does an object need before it is worth a label?
Label what the production decision needs and give each such object at least 15-20 pixels on its short side in the training images. Below roughly 15 px, change the capture — tighter field of view or more sensor pixels — instead of annotating objects the detector will never find.
The floor comes from detector practice: most YOLO families downsample the input by 8× or more before the finest prediction grid, so a 15 px object spans barely two cells there and gives the head almost nothing to learn from. Work the capture backward from the smallest defect that matters. Say the inspection must catch a 5 mm burr anywhere in a 300 mm wide field of view, captured on a 4000 × 3000 sensor:
- Pixel scale: 300 mm / 4000 px = 0.075 mm/px.
- Burr in pixels: 5 mm / 0.075 mm/px ≈ 67 px, comfortably above the floor.
- Smallest labelable feature at this scale: 15 px × 0.075 mm/px ≈ 1.1 mm.
If real defects reach down to 1 mm, halve the field of view to 150 mm: the scale drops to 0.0375 mm/px and the same chip now spans 27 px. The resolution calculator below runs the same sums from your field of view and smallest feature:
Both capture routes follow from that arithmetic — a 12 MP USB3 area scan model for the bench, and an X86-platform smart camera when the trained model must run where the frames were captured:
- Sensor format
- 1/1.7"
- Interface
- USB3
- Interface
- USB 2.0
- Resolution
- 6-10 MP
Capture training frames with the camera you deploy, or at least the same sensor and optics: identical spectrum, noise and mounting geometry mean every box you draw applies unchanged at inference. The camera finder filters by resolution, sensor format and shutter if the capture side is still open.
How do you keep classes consistent across thousands of images?
Fix the class list before the first box and annotate one class at a time across the whole set: keep classes.txt stable from the first session to the last, and re-check a random sample of about 20 images per class after every session against the ones you drew first.
Each line's leading number is the line position in classes.txt, so reordering or renaming entries re-labels the entire dataset silently — the classic route to a model trained on swapped names. If labels travel through a spreadsheet or a JSON export, the same index mapping decides everything, and the CSV-to-YOLO conversion guide shows where those mappings break. One pass per class keeps extent criteria uniform: label every instance of the first class across all images, then start the second, so your personal edge tolerance drifts between classes instead of within one. When a class comes up thin, the images-per-class guide sets the per-class budget and the image-count guide covers the total before you spend more annotation hours. Renaming later means re-saving every affected image, not editing one file.
What do you do with occluded, overlapping or cut-off objects?
Label the visible extent and keep the class: draw around the pixels you can actually see, never extend the box into the occluding part, and skip an object only when you genuinely cannot tell what it is. An unlabeled but visible object teaches YOLO to ignore exactly the clutter production images are full of.
Three recurring cases, one rule each:
- Occluded part: box the visible pixels; a screw hidden by 40% and labeled on its visible half is still a correct example of screw.
- Cut off at the image border: end the box at the border; normalized coordinates handle it, and the line simply carries an edge value at the 0 or 1 boundary.
- Several touching parts of one class: one box per part when the part is the class; merge into a single box only when the group itself is the class you will detect.
The occluded-object labeling guide works through the masking cases in more depth, including when a partially visible object is better left out.
What does each line in the exported txt file mean?
One .txt file per image, one line per object, five numbers per line: class_index, x_center, y_center, width, height — the four coordinates divided by image width and height, so they span 0 to 1 and 0.5 means the middle of the image at any resolution.
Worked example on a 4000 × 3000 image with a box drawn from corner (1200, 900) to corner (1800, 1500):
- Center in pixels: x = (1200 + 1800) / 2 = 1500; y = (900 + 1500) / 2 = 1200.
- Normalized center: 1500 / 4000 = 0.375; 1200 / 3000 = 0.400.
- Box size in pixels: 600 × 600; normalized: 600 / 4000 = 0.150; 600 / 3000 = 0.200.
- Line for class 0:
0 0.375 0.400 0.150 0.200.
The tool writes more decimal places than this; the values are identical. The class number is the position of the name in classes.txt, which is why the class-consistency section above guards that file's order. Background frames carry an empty .txt with the matching file name — no lines at all.
How do you verify the labels before training starts?
Check a 5% sample on three points: every image has a same-named .txt file, every line holds five numbers between 0 and 1, and boxes drawn back over the images sit on the objects. An empty .txt is a valid background frame; a missing .txt is a broken pair.
Render the sample with a short script of your own: read each line, multiply the four coordinates by the image width and height, and draw the rectangle — a page of code in any plotting library. On 2000 labeled images the 5% sample is 100 images, about an hour of looking that routinely catches what a failed training run wastes a day discovering. Read the class numbers against classes.txt while you render, and treat any coordinate above 1 as a caught error before it costs a run.
Which annotation mistakes train a model that finds nothing?
Four label-side failures produce identical symptoms — a loss that plateaus and a model with no detections: a class order that no longer matches classes.txt, pixel values pasted where 0-1 values belong, boxes offset by a resize, and PascalVOC XML fed to a YOLO trainer. Test the labels first.
In the order to check them:
- Class-index mismatch — the txt indices and classes.txt disagree; the no-detections label checklist walks this failure end to end.
- Unnormalized values — any coordinate above 1; re-run the four formulas above by hand on one line.
- Boxes offset by a resize — annotate original images, because letterboxing at train time shifts coordinates; the double-letterbox fix and the non-square image size guide cover that geometry.
- Wrong format — XML in a folder the trainer reads as txt; go back to the format switch in the first section.
Add background frames while you are in the set: images with empty label files, kept to roughly 0-10% of the total as the YOLO training guides commonly recommend, are the cheapest false-positive reduction available. And annotate only sharp frames — a rolling-shutter sensor shears a part moving through the frame, so every box on it is slightly wrong. For parts that move through the frame, a global-shutter sensor freezes motion instead of shearing it:
- Sensor format
- 1/1.7"
- Lens mount
- C-mount
- Interface
- GigE
- Resolution
- Up to 3 MP
Capture first, annotate second: size the field of view to your smallest defect, pull frames from the line, then annotate with the checks above. If the capture side is still open, configure a camera around it, browse smart cameras and area scan cameras, or talk it through with us before the first training run.
Questions
Can AI-assisted labeling do the drawing for me?
Yes, as a first pass. Auto-labeling tools pre-fill boxes from a model, and you then correct every box by hand; never train on pre-fills you have not reviewed, because systematic tool errors replicate across the whole set. Tools such as X-AnyLabeling also export oriented boxes in Ultralytics YOLO layout when parts sit at arbitrary angles.
Can YOLO use rotated bounding boxes?
Yes. Standard YOLO consumes axis-aligned boxes, but oriented-bounding-box variants exist for elongated parts lying at random angles, where an upright box would swallow neighboring parts. These formats carry rotated corner points instead of an upright rectangle, so label the rotated extent itself rather than the smallest upright box around it.
Can I annotate frames pulled from a video?
Yes, but space the frames out. Consecutive frames are near-duplicates: they inflate the image count without adding new poses, lighting or defect appearances. Skip enough frames that the part moves by at least its own size between picks, then annotate those; spaced frames cover far more conditions per hour of drawing.
What if I already annotated a class with the wrong name?
Fix it at the source before training. Because each line starts with the class index, a renamed or reordered class list silently re-labels every image. Correct the name in the annotation tool's class list, re-save the affected images so their txt files regenerate, and re-run your sample check before the first training run.


