Ultralytics YOLO27: Join the waitlist.
Get Started
Computer Vision Foundations·Datasets and Labels·Lesson 6/10
Lessonbeginner

Datasets that Reflect Reality

Audit a real dataset for coverage gaps before you label more, and turn the gaps into a collection plan with hard negatives.

Most disappointing vision models aren't bad models — they're good models trained on a dataset that doesn't look like the place they're deployed. The previous lesson's COCO detector found zero boats from a drone because COCO's boats are photographed from the side. A five-minute audit shows those gaps before you spend money on labels.

Outcome

Run a coverage audit on a YOLO dataset and turn its numbers into a ranked collection plan.

Fast Track
If you already know your way around, here's the short version.
  1. Sample the real deployment cameras before labeling anything.

  2. Cover lighting, weather, occlusion, and camera viewpoint on purpose.

  3. Audit counts: images per split, instances per class, background images, box sizes, resolutions, brightness.

  4. Add 0–10% background images, chosen as hard negatives from your environment.

  5. Empty cells in the class-by-condition grid are your collection plan.

Hands-on

Models learn the dataset, not the world#

A model interpolates between the examples it has seen. Train on sunny daytime streets and deploy in a foggy garage at night, and it fails — not because cars look different, but because it never saw a car under those conditions. This mismatch is called domain shift, and validation can't warn you about it when the validation images come from the same skewed collection:

The fix is structural, not algorithmic: sample the deployment world deliberately, before you label. The data collection and annotation guide covers the mechanics.

Audit a real dataset#

Ultralytics Platform dataset page for medical-pills: a grid of blister-pack images with blue pill boxes, the class and image counts, and the train, val, and test split bar

The medical-pills dataset above — close-ups of blister packs with every pill boxed — is a good subject for an audit. Ultralytics Platform shows its headline counts on the dataset page; the script below computes the numbers that reveal coverage, on the copy that ships with ultralytics:

from collections import Counter
from pathlib import Path

from PIL import Image, ImageStat
from ultralytics.data.utils import check_det_dataset

data = check_det_dataset("medical-pills.yaml")  # downloads the dataset on first use

for split in ("train", "val"):
    images = sorted(Path(data[split]).glob("*.jpg"))
    labels = [Path(str(p).replace("/images/", "/labels/")).with_suffix(".txt") for p in images]
    rows = [line.split() for f in labels if f.exists() for line in f.read_text().splitlines()]
    classes = Counter(data["names"][int(r[0])] for r in rows)
    backgrounds = sum(not f.exists() or not f.read_text().strip() for f in labels)
    areas = sorted(float(r[3]) * float(r[4]) for r in rows)  # box area as a share of the image
    sizes = Counter(Image.open(p).size for p in images)
    brightness = [ImageStat.Stat(Image.open(p).convert("L")).mean[0] for p in images]
    print(f"{split}: {len(images)} images, {backgrounds} backgrounds, {dict(classes)}, sizes {dict(sizes)}")
    print(f"  boxes: median {areas[len(areas) // 2]:.1%} of the image, {sum(a < 0.01 for a in areas)} of {len(areas)} under 1%")
    print(f"  brightness: {min(brightness):.0f} to {max(brightness):.0f} (0 = black, 255 = white)")
train: 92 images, 0 backgrounds, {'pill': 1623}, sizes {(1920, 1080): 92}
  boxes: median 1.4% of the image, 320 of 1623 under 1%
  brightness: 171 to 198 (0 = black, 255 = white)
val: 23 images, 0 backgrounds, {'pill': 399}, sizes {(1920, 1080): 23}
  boxes: median 1.4% of the image, 79 of 399 under 1%
  brightness: 171 to 198 (0 = black, 255 = white)

Read it as a coverage report, one finding per line:

FindingWhat it meansDecision
One resolution, 1920×1080One camera, one setupCollect from every camera model you will deploy on
Brightness only 171–198Bright, even studio light, nothing dimCollect dim, backlit, and mixed-light shots before deploying to a pharmacy counter
0 background imagesThe model never sees a scene without pillsAdd empty blister packs, other tablets, and bare counters as hard negatives
Median box is 1.4% of the image; 1 in 5 boxes under 1%Small objectsKeep imgsz high enough and include far-away shots on purpose
One class, pillNo pill typesFine for counting; add classes only if a decision needs them

None of these show up in the validation score, because validation shares every one of them.

The four axes of coverage#

AxisWhat to collectTypical failure if missing
LightingDawn, noon, dusk, night, glare, backlight, flickering fluorescentsRecall collapses at shift changes or in direct sun
Weather and atmosphereRain, fog, snow, dust, condensation on the lensFalse positives on droplets, misses in haze
Occlusion and clutterPartly hidden targets, crowded scenes, objects cut off at the frame edgeMisses whenever the target isn't fully visible
Camera and viewpointLens, mounting height and angle, resolution, compression, motion blurWorks on the pilot camera, fails at the next site

Viewpoint is the axis the marina example missed: the same class from a new angle, and recall dropped to zero.

Hard negatives and background images#

A detector also has to learn what is not the target. Hard negatives look superficially similar: for a forklift detector, a pallet jack, a scissor lift, a forklift's reflection in a polished floor, a safety poster with a forklift printed on it.

In the YOLO format, a background image is simply an image with no label file — nothing to draw. The Ultralytics training tips recommend about 0–10% background images to reduce false positives; COCO itself has about 1%. Fill that share with hard negatives from your own environment rather than random empty frames. Data augmentation can vary brightness and angle, but it can't invent a pallet jack the model has never seen.

Pitfalls#

Labeling before sampling

Symptom: 10,000 labeled images, all daytime, all from the pilot camera. Fix: record from the deployment cameras across the full range of conditions for a couple of weeks, audit the coverage, then pay for labels. Synthetic data can fill a known gap but doesn't replace real captures.

Trusting validation to find coverage gaps

Symptom: high validation mAP, poor results at the first new site. Fix: remember that validation shares the dataset's blind spots. Pull ten random training images and ten production frames, and ask a teammate to tell them apart; if they can, you have a domain gap.

For a sampling plan with target counts per condition, continue with Collect High-Quality, Representative Data in Building High-Performance YOLO Datasets.

Try It

Run the audit script on your own dataset (change the YAML path) or on medical-pills. Turn the output into a class-by-condition grid: rows are classes, columns are the conditions that matter in deployment (lighting, camera, occlusion, weather), with counts or estimates in each cell. List the empty cells ranked by how often that condition occurs in production, plus two hard-negative categories you'll collect.

Done When
You've finished the lesson when all of these are true.
  • You have audit output for a real dataset: images, backgrounds, classes, box sizes, resolutions, and brightness.

  • You have a class-by-condition grid with the empty cells ranked by how often they occur in production.

  • Your plan lists at least two hard-negative categories from the deployment environment.

Show solution

For medical-pills deployed on a pharmacy counter under mixed shop lighting, fill the grid from the audit (brightness 171–198, one 1920×1080 source, zero backgrounds) and a quick scroll through the images, which shows the same packs on the same bright surface with no hands:

ClassBright studio lightDim or warm shop lightBacklit / glarePartly covered by a handPhone camera
pill2,0220000
background000—0

Ranked collection plan:

  1. Dim or warm shop light — the counter's normal condition, currently zero images.
  2. Partly covered by a hand — happens on nearly every real interaction.
  3. Phone camera — a second sensor and resolution.
  4. Backlit / glare — foil packs reflect windows and ceiling lights.

Hard negatives: empty blister packs (same foil, no pills) and other round objects on the counter — coins, buttons, candy. Add them as background images, around 5–10% of the dataset.

What's next

Next: labeling that data so every annotator draws the same thing — and catching the files where they didn't.