MISSION LOG

MISSION LOG

RECORD OPEN

ATILIM UAV · GROUND CONTROL STATION

MISSION LOG / DETAIL

Archive

lıVE · READ MODE

Software

Augmentation Guide: scale, mosaic, flip — What Does Each One Actually Do?

Augmentation Guide: scale, mosaic, flip — What Does Each One Actually Do?

FIG. 01

RECORD DATA

Category

Software

TARİH

TÜM KAYITLAR

Everybody does the same thing when they write their training command: they copy the augmentation lines out of a forum post or somebody's Kaggle notebook and paste them in. degrees=15, mixup=0.15, erasing=0.4... It looks like it works. Then validation mAP lands below what you expected and you can't figure out why.

It happened to us too. Our first dataset was mostly scraped from the web, with only a small share of it being real aerial footage. We piled aggressive settings on top of that on the theory that more augmentation is always better, and the model got worse on aerial imagery. The problem wasn't augmentation itself; it was that we had never asked which transforms were physically possible in our problem.

In this post we walk through the Ultralytics augmentation parameters one at a time: what they do, their official defaults, and — the part that actually matters — when they hurt. Every value here was checked against the Ultralytics default.yaml and the official documentation (as of 2026).

The full parameter table

In Ultralytics, augmentation isn't a separate library; it lives right inside the training configuration. Here are the defaults:

Parameter

Default

Range

What it does

hsv_h

0.015

0.0–1.0

Hue (color) shift

hsv_s

0.7

0.0–1.0

Saturation shift

hsv_v

0.4

0.0–1.0

Brightness shift

degrees

0.0

0–180

Rotation by ±N degrees

translate

0.1

0.0–1.0

Shift by a fraction of the image size

scale

0.5

0.0–1.0

Scaling between (1−scale) and (1+scale)

shear

0.0

−180–+180

Shear (skew transform)

perspective

0.0

0.0–0.001

Perspective warp

flipud

0.0

0.0–1.0

Probability of a vertical flip

fliplr

0.5

0.0–1.0

Probability of a horizontal flip

bgr

0.0

0.0–1.0

Probability of an RGB↔BGR channel swap

mosaic

1.0

0.0–1.0

Probability of stitching 4 images onto one canvas

close_mosaic

10

integer

Disable mosaic for the last N epochs (0 = never disable)

mixup

0.0

0.0–1.0

Blend two images and their labels

cutmix

0.0

0.0–1.0

Cut and paste rectangular regions between images

copy_paste

0.0

0.0–1.0

Object copying (segmentation only)

copy_paste_mode

flip

flip / mixup

Where the copied object comes from

auto_augment

randaugment

Classification only

erasing

0.4

0.0–0.9

Classification only

Note what stands out: by default only mosaic, fliplr, scale, translate and the HSV trio are active. Everything else is off. It's no accident that Ultralytics picked a non-aggressive baseline.

scale: the one that helps most and gets overlooked most

scale=0.5 randomly resizes the image somewhere between 0.5x and 1.5x. Scale diversity pays off directly in object detection, because the same target shows up at wildly different pixel sizes from 20 m and from 60 m.

For us this was critical: most of our dataset was ground-level imagery where the object filled the frame. In flight, targets are far smaller within the frame. scale is the cheapest tool available for closing part of that gap.

scale also accepts a (min, max) tuple instead of a float, which means you can hand it an asymmetric range. If small objects are your problem, it makes sense to weight the range toward shrinking:

model.train(
    data="suas.yaml",
    imgsz=1280,
    scale=(0.4, 1.2),   # weight toward shrinking
    mosaic=1.0,
    close_mosaic=10,
)
model.train(
    data="suas.yaml",
    imgsz=1280,
    scale=(0.4, 1.2),   # weight toward shrinking
    mosaic=1.0,
    close_mosaic=10,
)

A warning: mosaic already shrinks objects, since it packs four images onto a single canvas. Stack an aggressive scale on top of that and objects can drop to a handful of pixels, get caught by the label filters, and vanish completely. Tune the two together, not separately.

fliplr and flipud: from the air, both are fair game

fliplr (horizontal flip) defaults to 0.5, so half your images get mirrored. That's safe for most problems — but it destroys the signal for text, license plates, or any class that carries a left/right distinction.

flipud (vertical flip) defaults to 0.0, and the reason is obvious: in ground-level imagery, gravity is a real constraint. An upside-down person is a scene that has no business being in a training set.

Looking straight down, that constraint disappears. With a nadir camera, the heading the drone happens to be flying while holding altitude makes object orientation in the frame arbitrary. The same tent appears 180 degrees apart on a northbound pass and a southbound pass. That's why flipud=0.5 isn't merely safe on aerial datasets, it's actively useful — and unlike rotation, it doesn't distort the box geometry.

degrees: the quiet cost of loosening the box

Rotation looks innocent, but it fights with the label format. YOLO labels are axis-aligned boxes; their edges are always parallel to the image edges. There is no field in which to store a rotated box.

In the Ultralytics source, RandomPerspective.apply_bboxes does exactly this: it pushes the box's four corners through the transform matrix, then builds a new axis-aligned box from the x.min(), y.min(), x.max(), y.max() of the transformed corners. So the box drawn around a rotated object is wider than the original, and it carries pixels that don't belong to the object.

The loss peaks at 45 degrees, and it's far more pronounced on long, thin objects (a person lying down, for instance). On roughly square objects it's negligible. The practical upshot: keep degrees small — 5–10 covers most scenarios — or, if you genuinely need full 360-degree orientation diversity, reach for the flipud + fliplr combination instead of rotation. Neither of those loosens the box at all.

mosaic and close_mosaic: turn it on, then turn it off

mosaic=1.0 stitches four images into a 2x2 canvas for every training sample. That raises class diversity and context variation within a single frame, and it helps small-object performance too, because objects naturally get smaller.

But the frame it produces is not a real frame. It's a seamed composite of four different scenes, and the camera will never hand you an image like that in flight. That is exactly why close_mosaic=10 (the default) exists: mosaic shuts off for the last 10 epochs and the model fine-tunes on real, single-piece frames. Your validation metrics usually pick up noticeably right at that point.

Set close_mosaic to 0 and mosaic stays on until the end — on short runs that means the model never sees a "clean" frame at all. On a 100-epoch run, you should have a specific reason before you touch the default of 10.

mixup and cutmix: visitors from classification

mixup blends two images with transparency and mixes their labels along with them. cutmix cuts a rectangular region out of one image and pastes it into another. Both default to 0.0 — off.

These come out of the classification literature and are considerably more debatable on a detection task. mixup produces semi-transparent ghost objects. Only reach for either one when you're actually seeing overfitting, and then only at small values (0.05–0.15).

copy_paste: it does nothing without segmentation masks

This is the single most misunderstood parameter. copy_paste is the direct way to fix class imbalance — cut objects out of one image, paste them into another scene — which sounds exactly like the answer to our own 7:1 class imbalance.

Here's the catch: cutting an object out cleanly requires pixel-level segmentation masks. A box isn't enough. The Ultralytics source handles this silently:

if len(labels["instances"].segments) == 0 or self.p == 0:
    return labels
if len(labels["instances"].segments) == 0 or self.p == 0:
    return labels

So if you write copy_paste=0.5 on a box-only detection dataset, you get no error whatsoever; the augmentation simply never runs. You'll sit through epochs assuming it's doing something.

copy_paste_mode takes two values: flip (the default) copies objects from the same image, mixup pulls them from different images. In both cases the paste only goes through if the overlap with existing objects stays below 30%.

erasing and auto_augment: these belong to classification

The erasing=0.4 and auto_augment='randaugment' defaults sit under the "Classification-Specific Augmentations" heading in the documentation. Writing those lines into a detection run has no effect at all.

If you are training a classifier, there's still a caveat: when the object fills most of the frame, erasing buys you robustness to partial occlusion. When the object is already small, the erased rectangle can cover the whole thing, and you end up handing the model an X-free image together with a label that says "there is an X in this image" — straight noise. Note as well that erasing's scale, ratio and value sub-parameters can't be changed in the current implementation.

When each one hurts

Parameter

Hurts when

What to do

scale (high)

Objects are already small and mosaic is on too

Narrow the range; tune it together with mosaic

fliplr

Left/right carries meaning (text, plates, arrows)

Set it to 0.0

flipud

Ground-level or oblique view where gravity is visible

Leave it at 0.0 unless the view is nadir

degrees

Long, thin objects; camera orientation already fixed

Keep it between 0 and 10, or prefer the flips

shear, perspective

Camera geometry is fixed and known

Leave them off

hsv_s / hsv_h (high)

Color is what separates the classes (red vs. green target)

Dial down the hue shift, keep the brightness

mosaic (in the final epochs)

The model never sees a clean frame

Don't set close_mosaic to 0

mixup / cutmix

Small dataset, detection task

Start with them off; turn them on only if you overfit

copy_paste

No mask labels

It silently does nothing — generate segmentation labels

erasing

Object is small within the frame

Lower it even in classification

Traps people fall into

Using augmentation to cover for missing data. If a class has few examples, augmentation doesn't multiply them; it just shows the same handful of examples over and over. Our dataset had a 7:1 gap between classes, and trying to close it with augmentation got us nowhere. The fix was collecting more real aerial frames.

Leaking augmentation into the validation set. Ultralytics doesn't augment during validation, but if you write your own preprocessing step and bake offline augmentations into the dataset, make sure variants of the same image don't land on both the train and the val side. Split on the source image, not on the variant.

Generating physically impossible scenes. The test in Ultralytics' own training material is simple: could this image actually occur in deployment? If it couldn't, you're burning model capacity.

Changing everything at once. Move five parameters together and look at mAP, and you'll never learn what any one of them did. Start from the defaults and change one parameter at a time.

Confusing training resolution with flight resolution. We train at imgsz=1280 and run 640 full-frame inference in flight. Judge the effective object size that augmentation produces against the training resolution — but measure what actually works on a validation set that's close to flight conditions. The configuration that got us to 0.950 mAP50 on our aerial-only validation set looked like a completely different animal once we measured it on the mixed set.

Practical summary

  1. Start from the defaults. mosaic=1.0, fliplr=0.5, scale=0.5, translate=0.1, the HSV trio — everything else off. That baseline is sensible for most detection problems.

  2. If you're flying a nadir (down-looking) camera, turn flipud=0.5 on. It's the only transform that buys you orientation diversity without distorting the box geometry.

  3. Prefer the flips over degrees. Rotation widens the axis-aligned box and packs background pixels into the label.

  4. Don't set close_mosaic to 0. Fine-tuning on real frames in the final epochs cleans up mosaic's seams.

  5. Generate masks before you reach for copy_paste. Without segmentation labels the parameter is silently ignored; don't sit there waiting for an error message.

  6. Measure every change on the same validation set and make sure that set represents flight conditions.

©2026 ATILIM UAV TEAM

©2026 ATILIM UAV TEAM

Create a free website with Framer, the website builder loved by startups, designers and agencies.