Основы CV
~22 мин

Обработка изображений

Пиксели, каналы, цветовые пространства (RGB, HSV, LAB), аугментации, torchvision transforms, Albumentations.

Обработка изображений — фундамент Computer Vision

Прежде чем подавать картинку в нейросеть, нужно понимать, что она из себя представляет. Изображение — это трёхмерный тензор (H × W × C): высота, ширина и каналы. Каждый пиксель — числовое значение яркости. Всё, что «видит» модель — это числа. Задача предобработки — подготовить эти числа так, чтобы модели было легче учиться.

Примеры аугментаций изображений: flip, rotation, crop, color jitter
Основные виды аугментаций: геометрические (flip, rotate, crop) и цветовые (brightness, contrast, color jitter)

Пиксели и каналы

Чёрно-белое изображение — 2D матрица, каждый элемент [0, 255] (uint8) или [0.0, 1.0] (float). Цветное — 3 канала. Стандартный формат: RGB (Red, Green, Blue). Каждый пиксель — вектор из 3 значений. Изображение 224×224 RGB = тензор (224, 224, 3) = 150 528 чисел.

Важно: PyTorch использует формат CHW (channels first: 3 × 224 × 224), а NumPy/PIL — HWC (224 × 224 × 3). Частая ошибка — забыть transpose при конвертации.

from PIL import Image
import numpy as np
import torch

# PIL → NumPy (HWC)
img = Image.open("photo.jpg")
arr = np.array(img)  # shape: (H, W, 3), dtype=uint8, range [0, 255]

# NumPy → PyTorch (CHW, float, normalized)
tensor = torch.from_numpy(arr).permute(2, 0, 1).float() / 255.0
# shape: (3, H, W), dtype=float32, range [0.0, 1.0]

Цветовые пространства

RGB — стандарт для нейросетей. Но не всегда оптимален:

  • HSV (Hue, Saturation, Value) — отделяет цвет от яркости. Полезно для задач, где освещение меняется: детекция объектов по цвету (красный светофор), аугментации цвета.
  • LAB (Lightness, A, B) — перцептуально равномерное пространство. Евклидово расстояние в LAB соответствует человеческому восприятию разницы цветов. Используется в style transfer и колоризации.
  • Grayscale — один канал. Для задач, где цвет не важен (OCR, рентгены). Уменьшает размерность в 3 раза.
import cv2

img_bgr = cv2.imread("photo.jpg")        # OpenCV читает в BGR (!)
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
img_lab = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2LAB)
img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)  # (H, W)

Нормализация

Нейросети обучаются лучше, когда входные данные нормализованы. Стандартная практика для моделей, предобученных на ImageNet:

import torchvision.transforms as T

transform = T.Compose([
    T.Resize(256),
    T.CenterCrop(224),
    T.ToTensor(),          # [0, 255] uint8 → [0.0, 1.0] float
    T.Normalize(
        mean=[0.485, 0.456, 0.406],   # ImageNet mean
        std=[0.229, 0.224, 0.225],     # ImageNet std
    ),
])

Эти числа (mean/std) — статистики ImageNet. Если модель предобучена на ImageNet, обязательно используй эти значения. Для своих данных — считай mean/std по своему тренировочному набору.

Аугментации — ключ к обобщению

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

Базовые аугментации:

  • Геометрические: horizontal/vertical flip, rotation, random crop, affine transforms, perspective
  • Цветовые: brightness, contrast, saturation, hue jitter, color dropout
  • Шум/blur: Gaussian noise, motion blur, JPEG compression artifacts
  • Cutout/erasing: случайно «вырезаем» часть изображения — заставляет модель не полагаться на одну область

Продвинутые аугментации:

  • Mixup — линейная комбинация двух изображений и их лейблов: x = λx₁ + (1−λ)x₂
  • CutMix — вырезаем patch из одного изображения и вставляем в другое, лейбл пропорционален площади
  • AutoAugment / RandAugment — автоматический поиск оптимальной стратегии аугментаций. RandAugment проще: случайно выбираем N трансформаций с магнитудой M
  • Mosaic (YOLO) — склеиваем 4 изображения в одно. Модель видит больше объектов за один forward pass
import albumentations as A
from albumentations.pytorch import ToTensorV2

# Production-ready пайплайн аугментаций
train_transform = A.Compose([
    A.RandomResizedCrop(224, 224, scale=(0.08, 1.0)),
    A.HorizontalFlip(p=0.5),
    A.ColorJitter(brightness=0.4, contrast=0.4, saturation=0.4, hue=0.1),
    A.GaussianBlur(blur_limit=(3, 7), p=0.3),
    A.CoarseDropout(max_holes=1, max_height=56, max_width=56, p=0.3),
    A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ToTensorV2(),
])

val_transform = A.Compose([
    A.Resize(256, 256),
    A.CenterCrop(224, 224),
    A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ToTensorV2(),
])

Albumentations vs torchvision.transforms

torchvision.transforms: встроен в PyTorch, удобен для простых пайплайнов, работает с PIL. Albumentations: быстрее (OpenCV под капотом), больше аугментаций, поддерживает bounding boxes и маски (для detection/segmentation). В production CV — стандарт.

🎯 На собеседовании

Типичные вопросы

Зачем нормализация с ImageNet mean/std? Модели предобучены на ImageNet — ожидают такое распределение входов. Без нормализации pretrained веса не работают. • Какие аугментации для detection? Геометрические трансформации должны применяться и к bounding boxes. Albumentations поддерживает это из коробки. • CHW vs HWC? PyTorch = CHW (channels first), NumPy/PIL/OpenCV = HWC. Не забыть permute/transpose. • Mixup и CutMix — зачем? Регуляризация: модель учится на «промежуточных» примерах, лучше калибрует уверенность. +1-2% accuracy на ImageNet.