Fundamentos de Imagens

Por que “Fundamentos de Imagens” Importam

Modelos modernos de visão computacional (computer vision)—sejam Tarefas Centrais como classificação (classification)/detecção (detection)/segmentação (segmentation) ou sistemas multimodais (multimodal systems) como Multimodal (Modelos Visão-Linguagem (Vision-Language Models))—são extremamente sensíveis à forma como as imagens são decodificadas, redimensionadas, normalizadas e aumentadas. Dois fluxos de processamento (pipelines) que “parecem semelhantes” podem produzir diferenças mensuráveis em acurácia, robustez e equidade.

Este artigo cobre:

  • Como as imagens são representadas (pixels, canais (channels), intervalos, espaços de cor (color spaces))
  • Pré-processamento (preprocessing) (tornar as entradas consistentes e amigáveis ao modelo)
  • Aumento de dados (data augmentation) (aleatoriedade controlada para generalização)
  • Fluxos de trabalho práticos de dados em visão computacional (partições, tratamento de anotações, prevenção de vazamento, eficiência)

O objetivo é conectar teoria (o que as transformações significam) com prática (como implementá-las de forma confiável).

Imagens Digitais: O Que Seu Modelo Realmente Vê

Pixels, canais e layout do tensor (tensor)

Uma imagem RGB típica é uma grade de pixels, cada um com três valores de canal (R, G, B). Em código, isso vira um array/tensor com forma como:

  • HWC: (height, width, channels) — comum em PIL, NumPy, TensorFlow
  • CHW: (channels, height, width) — comum em modelos PyTorch

Cuidado: muitos bugs surgem ao misturar esses formatos sem perceber.

Também observe a ordem dos canais:

  • OpenCV carrega imagens como BGR por padrão.
  • PIL e a maioria das bibliotecas de aprendizado profundo (deep learning) esperam RGB.

Intervalos de valores e tipos (dtypes) (uint8 vs float32)

Imagens decodificadas geralmente são uint8 em [0, 255]. Muitos modelos esperam float32:

  • Ou escaladas para [0, 1] (dividir por 255)
  • Ou normalizadas (subtrair a média, dividir pelo desvio padrão)

Um padrão comum para espinhas dorsais pré-treinadas no ImageNet (ImageNet-pretrained backbones):

  • Escalar para [0,1]
  • Depois normalizar usando média/desvio padrão:
    • mean = [0.485, 0.456, 0.406]
    • std = [0.229, 0.224, 0.225]

Se você esquecer a normalização esperada, pode ver uma grande queda de acurácia—mesmo que as imagens “pareçam boas”.

Gama e “linear vs sRGB” (muitas vezes ignorado, às vezes importante)

A maioria das imagens de consumo é armazenada em sRGB, que é com compressão gama (gamma-compressed). Muitos fluxos de visão computacional tratam os valores de pixel como sinais lineares, o que não é estritamente correto. Para muitas tarefas, essa aproximação é aceitável, mas em domínios sensíveis à fotometria (photometric-sensitive) (algumas áreas de imagens médicas, imagens científicas), o tratamento correto de gama/espaço linear pode importar.

Lição prática: para conjuntos de dados típicos de web/fotos, o pré-processamento padrão (escalonamento + normalização por média/desvio padrão) é a norma. Para domínios especializados, valide as suposições sobre escalonamento de intensidade.

Espaços de cor

RGB é comum, mas às vezes outros espaços ajudam:

  • Escala de cinza (grayscale): reduz canais, útil para documentos/escaneamentos médicos
  • HSV/HSL: separa matiz e intensidade; pode ajudar heurísticas baseadas em cor
  • YCbCr: usado internamente por JPEG; às vezes relevante para artefatos de compressão

Redes profundas (deep nets) geralmente aprendem bem em RGB, mas o aumento de dados pode operar em outros espaços (por exemplo, variação de matiz).

Formatos de imagem e artefatos de compressão

Formatos comuns:

  • JPEG: compressão com perdas (lossy compression), introduz artefatos de blocos/anelamento (blocking/ringing artifacts)
  • PNG: sem perdas, suporta transparência (canal alfa (alpha channel))
  • TIFF: comum em imagens médicas/científicas, pode armazenar maior profundidade de bits (bit-depth)
  • WebP/HEIC: formatos modernos, nem sempre suportados de forma consistente nos fluxos de processamento

A compressão importa porque altera as estatísticas dos pixels. Se seu conjunto de treino é majoritariamente JPEG, mas as imagens em produção são PNG (ou vice-versa), a mudança de distribuição (distribution shift) pode afetar o desempenho. Algumas equipes adicionam intencionalmente aumento de compressão JPEG (JPEG compression augmentation) para melhorar a robustez.

Pré-processamento: Tornando as Entradas Consistentes

Pré-processamento é sobre converter imagens brutas em uma representação padronizada, da qual seu modelo consiga aprender de forma eficiente e consistente.

Decodificação e orientação (armadilhas de EXIF)

Muitas fotos contêm metadados de orientação EXIF. Alguns carregadores aplicam automaticamente; outros não. Se você ignorar a orientação EXIF, imagens “em pé” podem aparecer rotacionadas no treino ou na inferência.

Diretriz prática: garanta que sua etapa de decodificação sempre respeite a orientação EXIF ou sempre a remova após aplicá-la—mas seja consistente.

Estratégias de redimensionamento (e por que importam)

A maioria dos modelos precisa de tamanhos fixos de entrada. As escolhas de redimensionamento embutem suposições:

  1. Redimensionamento por deformação (warp resize) (esticar até o tamanho alvo)

    • Prós: mais simples
    • Contras: distorce a proporção; pode prejudicar tarefas sensíveis à geometria
  2. Redimensionar o menor lado + recorte (resize shortest side + crop) (comum em classificação)

    • Exemplo: redimensionar para que o menor lado seja 256, depois recorte aleatório 224×224
    • Prós: aumento de dados forte, preserva a proporção antes do recorte
    • Contras: pode recortar objetos importantes (às vezes bom, às vezes ruim)
  3. Letterbox/preenchimento para caber (letterbox/pad to fit) (comum em detecção)

    • Redimensionar preservando a proporção, depois preencher até uma forma fixa
    • Prós: caixas/máscaras permanecem geometricamente consistentes
    • Contras: o preenchimento introduz bordas de cor constante; é preciso tratar no pós-processamento

A escolha depende da tarefa e da arquitetura. Transformers de visão (vision transformers) e redes neurais convolucionais (convolutional neural networks, CNNs) frequentemente toleram distorções leves para classificação, mas detecção/segmentação exigem consistência geométrica cuidadosa.

Interpolação e antisserrilhamento (anti-aliasing)

A interpolação afeta detalhes finos:

  • Bilinear / Bicubic: comuns para imagens
  • Vizinho mais próximo (nearest): usado para máscaras/rótulos (segmentação), porque IDs de classe não devem ser interpolados

Ao reduzir bastante a resolução, habilite antisserrilhamento se disponível, especialmente para texturas de alta frequência (para reduzir moiré e aliasing).

Normalização: em nível de conjunto de dados vs por imagem

Esquemas comuns:

  • Padronização em nível de conjunto de dados (dataset-level standardization) (mais comum em modelos pré-treinados): média/desvio padrão fixos
  • Padronização por imagem (per-image standardization): subtrair a média de cada imagem, dividir pelo desvio padrão dela
    • Pode remover informação de iluminação; às vezes ajuda, às vezes atrapalha
  • Escalonamento min-max (min-max scaling) para [0, 1] ou [-1, 1]

Para aprendizado por transferência (transfer learning), corresponda à normalização esperada pelo modelo pré-treinado (por exemplo, ImageNet). Para treinar do zero, normalização em nível de conjunto de dados ainda é um padrão forte.

Requisitos de pré-processamento específicos por tarefa

Classificação

  • Recortes aleatórios com redimensionamento são padrão
  • Rótulos não mudam sob muitas transformações (flip, variação de cor)

Detecção de objetos

  • Transformações também devem atualizar caixas delimitadoras (bounding boxes)
  • Recortes podem remover objetos → você pode precisar de políticas como “manter caixas com área suficiente”
  • Preenchimento/letterbox requer mapeamento cuidadoso de volta às coordenadas originais

Segmentação

  • Máscaras devem usar interpolação de vizinho mais próximo
  • Alguns aumentos (desfoque, variação de cor) se aplicam apenas às imagens, não às máscaras

(Se você é novo nessas tarefas, veja Tarefas Centrais.)

Aumento de Dados: Aleatoriedade Controlada para Generalização

Aumento de dados é uma forma de regularização (regularization): ele expande a distribuição efetiva de treinamento (training distribution) aplicando transformações que idealmente preservam o rótulo enquanto expõem o modelo a variação realista.

Essa ideia é intimamente relacionada a invariâncias (invariances): por exemplo, um gato continua sendo um gato após uma pequena translação (translation). Mas nem todas as invariâncias são válidas—reconhecimento de texto não é invariante a inversão esquerda-direita, por exemplo.

Princípios para escolher aumentos

  1. Preservar rótulos (ou ajustar rótulos explicitamente)
    • Flip preserva rótulos para “gato vs cachorro”, mas não para “seta para esquerda vs seta para direita”
  2. Refletir as condições de produção (deployment)
    • Se as imagens em produção incluem desfoque de movimento, adicione aumento de desfoque
  3. Não exagerar no aumento
    • Distorção excessiva pode criar amostras irreais e piorar o desempenho
  4. Combinar com a geometria da tarefa
    • Detecção/segmentação exigem transformações consistentes para os rótulos

Aumentos geométricos comuns

  • Flip horizontal aleatório (padrão comum)
  • Recorte aleatório / recorte aleatório com redimensionamento
  • Rotação (ângulos pequenos geralmente OK; ângulos grandes podem ser irreais)
  • Translação, escala, cisalhamento (transformações afins)
  • Deformação de perspectiva (use com cuidado; pode alterar a geometria do objeto)

Transformações geométricas são particularmente poderosas porque mudam a configuração espacial, o que ajuda a prevenir sobreajuste (overfitting) à posição e ao enquadramento.

Aumentos fotométricos

  • Variação de brilho/contraste/saturação/matiz
  • Conversão para escala de cinza (às vezes)
  • Mudanças de temperatura de cor (mais especializado)

Eles ajudam com variações de iluminação, câmeras e balanço de branco.

Aumentos de ruído, desfoque e compressão

  • Ruído gaussiano / aproximações de ruído de sensor
  • Desfoque gaussiano / desfoque de movimento
  • Artefatos de compressão JPEG

Eles são úteis quando as imagens em produção são de baixa qualidade, comprimidas ou capturadas em movimento.

Aumentos no estilo oclusão

  • Cutout / Random Erasing: apagar uma região retangular
  • Incentiva robustez a oclusão e a informação ausente

Aumentos por mistura de amostras (sample-mixing augmentations) (fortes, muitas vezes eficazes)

  • MixUp: combinação convexa de duas imagens e rótulos
  • CutMix: colar um patch de uma imagem em outra; misturar rótulos pela área
  • Mosaic (comum em detecção no estilo YOLO): combinar várias imagens em uma única tela

Eles frequentemente melhoram robustez e calibração, mas alteram levemente o objetivo de treinamento (especialmente para classificação).

Aumento baseado em políticas

Abordagens como RandAugment e AutoAugment aplicam conjuntos aleatórios de transformações com magnitudes ajustadas. Na prática:

  • RandAugment é popular porque é simples e forte.
  • Elas podem ser benéficas para conjuntos de dados menores ou quando você precisa de mais robustez.

Treino vs validação/teste: mantenha a avaliação determinística

Uma regra padrão:

  • Treino: aumento estocástico on-the-fly
  • Validação/Teste: apenas pré-processamento determinístico (redimensionar/recorte central/normalizar)

Caso contrário, sua avaliação fica ruidosa e difícil de comparar. Para benchmarking de robustez (robustness benchmarking), você pode usar suítes específicas de corrupções, mas isso deve ser deliberado e documentado (veja Avaliação para Visão).

Fluxos de Trabalho Práticos de Dados em Visão Computacional

Particionamento de conjunto de dados e prevenção de vazamento

Uma “boa partição (split)” é tão importante quanto um bom modelo.

Armadilhas comuns:

  • Imagens quase duplicadas (sequências em rajada, cópias redimensionadas) acabam entre treino/teste → métricas infladas
  • Frames de vídeo particionados aleatoriamente → vazamento ao longo do tempo (use partições em nível de sequência (sequence-level splits))
  • Mesmo paciente/produto/cena entre partições → resultados otimistas demais

Boas práticas:

  • Particionar por identificador de grupo (group identifier) (ID de paciente, ID de vídeo, ID de sessão)
  • Remover duplicatas usando hashes perceptuais (pHash) ou similaridade por vetores de incorporação (embeddings)
  • Manter um arquivo de partição estável e versionado (train.txt, val.txt, test.txt)

Formatos de anotação e conversões (o que importa operacionalmente)

Você encontrará formatos como COCO, VOC, YOLO ou JSON/CSV customizado. As questões operacionais-chave não são o esquema JSON—são:

  • Convenções de coordenadas: (xmin, ymin, xmax, ymax) vs (x, y, w, h)
  • Normalização: pixels absolutos vs relativo ao tamanho da imagem
  • Origem: origem no canto superior esquerdo é típica, mas confirme
  • Regiões de multidão/ignorar: como são representadas afeta treino e métricas
  • Máscaras de instância vs semânticas: semânticas de rótulo diferentes

Ao converter formatos, escreva testes unitários (unit tests) em um punhado de imagens: visualize caixas/máscaras antes e depois da conversão.

Verificações de integridade de dados (baratas e com alto retorno)

Antes de treinar, vale a pena rodar:

  • Detecção de imagem corrompida (falhas de decodificação)
  • Outliers de tamanho (imagens minúsculas, proporções extremas)
  • Sanidade de rótulos:
    • Caixas vazias, larguras/alturas negativas
    • Caixas fora dos limites da imagem
    • Máscaras com dimensões erradas
  • Distribuição de classes: detectar desbalanceamento severo cedo
  • Amostragem de visualização: grade aleatória de imagens com rótulos desenhados

Essas verificações evitam treinos desperdiçados e comportamentos confusos do modelo.

Desbalanceamento de classes: aumento não é a única ferramenta

Se algumas classes são raras:

  • Reamostragem (re-sampling) (superamostrar classes raras)
  • Função de perda ponderada por classe (class-weighted loss) (por exemplo, entropia cruzada ponderada (weighted cross entropy), perda focal (focal loss))
  • Coleta direcionada (targeted collection) (geralmente a mais eficaz)
  • Aumento direcionado (targeted augmentation) (útil, mas pode causar sobreajuste se só repetir padrões)

Aumento ajuda, mas não consegue criar exemplos realmente novos para modos raros que você nunca capturou.

Pipelines de entrada eficientes

Gargalos frequentemente migram do cômputo na GPU (GPU compute) para o carregamento de dados (data loading). Melhorias práticas:

  • Aumento on-the-fly (economiza disco, mais variedade)
  • Use múltiplos workers e pré-busca (prefetching) (PyTorch num_workers, prefetch_factor; TF prefetch)
  • Faça cache de imagens decodificadas/redimensionadas quando a CPU é o gargalo (cuidado com armazenamento)
  • Considere decodificação/aumento acelerados por GPU (por exemplo, NVIDIA DALI) em treinamento em larga escala

Reprodutibilidade e versionamento do conjunto de dados

Para tornar experimentos comparáveis:

  • Versione conjuntos de dados (mesmo que seja apenas uma soma de verificação (checksum) + manifesto)
  • Armazene configs de pré-processamento/aumento nos logs de experimento
  • Fixe sementes aleatórias (random seeds) ao depurar (mas lembre-se de que determinismo total pode ser difícil com carregadores paralelos)

Exemplos Práticos

Exemplo 1: Pré-processamento + aumento para classificação em PyTorch

from torchvision import transforms
from PIL import Image

# Typical ImageNet-style pipeline
train_tfms = transforms.Compose([
    transforms.RandomResizedCrop(224, scale=(0.08, 1.0), ratio=(3/4, 4/3)),
    transforms.RandomHorizontalFlip(p=0.5),
    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.05),
    transforms.ToTensor(),  # converts HWC uint8 [0..255] -> CHW float [0..1]
    transforms.Normalize(mean=(0.485, 0.456, 0.406),
                         std=(0.229, 0.224, 0.225)),
])

val_tfms = transforms.Compose([
    transforms.Resize(256, interpolation=transforms.InterpolationMode.BICUBIC),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=(0.485, 0.456, 0.406),
                         std=(0.229, 0.224, 0.225)),
])

img = Image.open("example.jpg").convert("RGB")
x = train_tfms(img)  # tensor [3,224,224]

Notas:

  • ToTensor() faz o escalonamento para [0,1].
  • Validação é determinística (redimensionar + recorte central).
  • Se você usar um modelo pré-treinado, corresponda à normalização esperada por ele.

Exemplo 2: Aumento para detecção com caixas delimitadoras (Albumentations)

Detecção precisa de transformações conscientes do rótulo; Albumentations é popular porque atualiza as caixas para você.

import albumentations as A
import cv2

# Boxes in Pascal VOC format: [xmin, ymin, xmax, ymax]
train_aug = A.Compose(
    [
        A.HorizontalFlip(p=0.5),
        A.ShiftScaleRotate(shift_limit=0.05, scale_limit=0.1, rotate_limit=10,
                           border_mode=cv2.BORDER_CONSTANT, p=0.5),
        A.RandomBrightnessContrast(p=0.3),
    ],
    bbox_params=A.BboxParams(format="pascal_voc", label_fields=["labels"])
)

image = cv2.imread("img.jpg")              # BGR uint8
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

bboxes = [[50, 60, 200, 220]]              # example box
labels = [1]                                # class id

out = train_aug(image=image, bboxes=bboxes, labels=labels)
image_aug, bboxes_aug, labels_aug = out["image"], out["bboxes"], out["labels"]

Pontos-chave:

  • Confirme o formato das caixas (pascal_voc, coco, yolo, etc.).
  • Decida o que fazer quando caixas saem parcialmente do enquadramento (Albumentations tem opções).

Exemplo 3: Pipeline `tf.data` do TensorFlow (decodificar, redimensionar, aumentar)

import tensorflow as tf

IMG_SIZE = 224

def preprocess_train(example):
    img = tf.io.read_file(example["path"])
    img = tf.image.decode_jpeg(img, channels=3)              # uint8 [H,W,3]
    img = tf.image.convert_image_dtype(img, tf.float32)      # float32 [0,1]
    img = tf.image.resize(img, [256, 256], antialias=True)
    img = tf.image.random_crop(img, [IMG_SIZE, IMG_SIZE, 3])
    img = tf.image.random_flip_left_right(img)
    img = tf.image.random_brightness(img, max_delta=0.1)

    # ImageNet normalization
    mean = tf.constant([0.485, 0.456, 0.406], tf.float32)
    std  = tf.constant([0.229, 0.224, 0.225], tf.float32)
    img = (img - mean) / std

    return img, example["label"]

ds = ...  # dataset of dicts {path, label}
ds = ds.shuffle(10_000).map(preprocess_train, num_parallel_calls=tf.data.AUTOTUNE)
ds = ds.batch(64).prefetch(tf.data.AUTOTUNE)

Notas:

  • antialias=True ajuda ao reduzir a resolução.
  • Use pré-processamento determinístico para validação.

Armadilhas Comuns (e como evitá-las)

  • Incompatibilidade entre treino/validação: redimensionamento ou normalização diferentes entre partições podem dominar os resultados.
  • Ordem errada de canais: BGR vs RGB é uma falha silenciosa clássica.
  • Interpolar máscaras com bilinear: transforma IDs de classe em nonsense—use vizinho mais próximo.
  • Aumentos que quebram rótulos: flips para texto, rotações para classes “apenas em pé”, recortes pesados para objetos pequenos.
  • Vazamento via duplicatas: imagens quase idênticas entre partições inflacionam acurácia.
  • Tratamento inconsistente de proporção: especialmente prejudicial em detecção (erros de mapeamento de coordenadas).

Como os Fundamentos de Imagens se Conectam ao Resto de Visão

  • Pré-processamento/aumento fortes muitas vezes importam tanto quanto a arquitetura, especialmente quando os dados são limitados.
  • Para contexto no nível de tarefa e escolhas de modelo, veja Tarefas Centrais.
  • Para métricas e protocolos corretos (especialmente em detecção/segmentação), veja Avaliação para Visão.
  • Para dados temporais, as regras de aumento e vazamento mudam (correlação entre frames, desfoque de movimento), cobertas em Entendimento de Vídeo.
  • Para pipelines multimodais, normalização e redimensionamento de imagem devem corresponder ao codificador de visão usado em Multimodal (Modelos Visão-Linguagem).

Checklist Prático

  • Decodifique de forma consistente (orientação, RGB/BGR).
  • Defina uma estratégia de redimensionamento (deformar vs recortar vs letterbox) apropriada à tarefa.
  • Normalize exatamente como seu modelo espera.
  • Use aumento consciente do rótulo para detecção/segmentação.
  • Mantenha validação/teste determinísticos.
  • Previna vazamento com partições baseadas em grupos e remoção de duplicatas.
  • Construa pipelines de entrada rápidos e reprodutíveis com logging e versionamento do conjunto de dados.

Acertar esses “fundamentos de imagens” transforma o treino em visão computacional de uma experimentação frágil em um fluxo de trabalho de engenharia no qual você pode confiar.