Аугментация изображения и рамок: почему horizontal flip портит разметку

Для детектора мало данных, поэтому команда отражает половину фотографий по горизонтали. Изображения становятся разнообразнее, а качество модели неожиданно падает. На проверке видно: после отражения объект переместился вправо, а рамка осталась слева. Аугментация создала систематически неверную разметку.

Геометрия применяется к паре «изображение — рамка»

Для полуоткрытой рамки (x1, y1, x2, y2) и ширины W горизонтальное отражение даёт (W−x2, y1, W−x1, y2). Важно менять местами левую и правую границы, а не просто заменять каждую x на W−x. Ниже ImageOps.mirror отражает пиксели, а код рядом переносит рамку в ту же систему координат.

from PIL import Image, ImageOps

image = Image.new("RGB", (10, 6), "white")
box = (2, 1, 5, 4)  # xyxy, полуоткрытые границы
flipped = ImageOps.mirror(image)
width = image.width
x1, y1, x2, y2 = box
flipped_box = (width - x2, y1, width - x1, y2)
print("размер:", flipped.size)
print("новая рамка:", flipped_box)
assert flipped_box == (5, 1, 8, 4)

Исходная рамка от x=2 до x=5 на изображении шириной 10 переходит в диапазон от 5 до 8. Высота и y-координаты не меняются. Проверка утверждает конкретный результат. Если вместо полуоткрытых границ разметка использует включённую координату последнего пикселя, формула будет другой; сначала закрепите формат рамки на тестовом изображении.

Почему тест должен смотреть на результат

Числовая проверка ловит ошибку формулы, но не всегда ловит несовпадение библиотечных соглашений. Нарисуйте несколько исходных и отражённых кадров с рамками поверх и проверьте объект у краёв. После кропа или поворота рамку нужно ещё обрезать по новым границам и решить, сохранять ли объект, который почти полностью вышел из кадра. В цепочке нескольких аугментаций порядок операций влияет на координаты.

Аугментации задавайте только для обучающей части. Если сначала создать отражённые копии, а затем случайно разделить всё на train и validation, исходник может оказаться в обучении, а зеркальная почти копия — в проверке. Это завысит метрику. Для видео и серийных кадров ситуация ещё хуже; разбор утечки между кадрами помогает выбрать границу.

Сравните качество с аугментацией и без неё на одном и том же независимом наборе. Отражение полезно не для всякой сцены: текст, дорожные знаки и левая/правая сторона объекта могут менять смысл. Если метка зависит от ориентации, одновременно с рамкой потребуется преобразовать и класс либо отказаться от отражения.

Если вы используете библиотечный трансформер, который обещает менять изображение и рамки вместе, всё равно проведите этот простой контрольный опыт через его API. Обёртка может ожидать формат xywh или нормализованные координаты, а ваши рамки — xyxy в пикселях. На симметричном объекте ошибка незаметна; выбирайте тестовую рамку, сдвинутую к одному краю, как в примере. Так несовпадение соглашений обнаружится до запуска обучения.

В курсе «Computer Vision Engineer: от детекции и Doc-AI до продакшна» вы готовите разметку, применяете аугментации, обучаете детекторы и проверяете метрики на отдельном наборе. Это позволяет увидеть эффект отражения по качеству модели, а не по числу новых картинок. Откройте программу курса.

Продолжить на практике

  • Computer Vision Engineer: от детекции и Doc-AI до продакшна ↗

    Практический курс по Computer Vision. Соберёте продакшн-сервис: датасет → обучение (YOLO/RT-DETR, SAM), трекинг, OCR/Doc-AI, веб-приложение (UI+API) и мониторинг. Экспорт в ONNX/TensorRT/OpenVINO, батчинг/квантование под CPU/GPU. Плюс профессиональные блоки: mAP/IoU/Dice и калибровка доверия, QA разметки и аугментации, p95/стоимость, дрейф данных и алерты, guardrails (NMS/правила), A/B-тесты, Triton/gRPC/FastAPI.