Fluxo Óptico

O que é fluxo óptico?

Fluxo óptico (optical flow) é a tarefa de estimar o movimento aparente por pixel entre dois quadros consecutivos de um vídeo. A saída é tipicamente um campo vetorial 2D denso:

[ \mathbf{u}(x, y) = (u(x,y), v(x,y)) ]

em que (u) e (v) são os deslocamentos horizontal e vertical que mapeiam um pixel no quadro (I_t) para sua localização correspondente no quadro (I_{t+1}). O fluxo óptico é “aparente” porque é inferido a partir de mudanças de intensidade da imagem, e não diretamente a partir do movimento 3D real. Movimento da câmera, movimento de objetos e variação de profundidade contribuem para o fluxo observado.

O fluxo óptico é um primitivo central em compreensão de vídeo (video understanding): uma vez que você consegue estimar movimento, pode dar suporte a tarefas posteriores como Rastreamento de Objetos, estabilização de vídeo, segmentação temporal, interpolação de quadros e reconhecimento de ações.

Intuição: correspondência como “para onde foi este pixel?”

Dado dois quadros (I_t) e (I_{t+1}), o fluxo óptico pergunta:

Para cada pixel em ((x,y)) em (I_t), onde está o pixel correspondente em (I_{t+1})?

Se o vetor de fluxo em ((x,y)) é ((u,v)), então a correspondência é aproximadamente:

[ I_t(x,y) \leftrightarrow I_{t+1}(x + u, y + v) ]

Esse mapeamento permite deformar (warping) um quadro no outro, um bloco de construção comum tanto em abordagens clássicas quanto profundas.

Fundamentos teóricos

Constância de brilho

A suposição inicial mais comum é a constância de brilho (brightness constancy):

[ I(x,y,t) \approx I(x+u, y+v, t+1) ]

Ou seja, a intensidade de um ponto permanece (aproximadamente) constante enquanto ele se move. Isso nem sempre é verdade — mudanças de iluminação, especularidades, sombras e desfoque de movimento violam essa hipótese —, mas é uma aproximação útil.

A equação de restrição do fluxo óptico (OFCE)

Assumindo movimento pequeno, podemos linearizar usando uma expansão de Taylor de primeira ordem:

[ I(x+u, y+v, t+1) \approx I(x,y,t) + I_x u + I_y v + I_t ]

A constância de brilho implica:

[ I_x u + I_y v + I_t = 0 ]

Esta é a equação de restrição do fluxo óptico (optical flow constraint equation, OFCE). Ela fornece uma equação para duas incógnitas ((u,v)), então o problema é indeterminado sem restrições adicionais.

O problema da abertura

Em regiões com pouca textura (por exemplo, uma borda reta), o movimento é ambíguo: muitas vezes você só consegue estimar o movimento perpendicular à borda, e não ao longo dela. Esse é o problema da abertura (aperture problem) e motiva adicionar regularização espacial ou usar vizinhanças maiores.

Suavidade espacial / regularização

Uma suposição comum é que o fluxo varia suavemente no espaço, exceto em fronteiras de movimento:

  • Pixels vizinhos frequentemente se movem de forma similar (mesma superfície do objeto).
  • Descontinuidades de fluxo ocorrem em bordas de objetos ou descontinuidades de profundidade.

Métodos clássicos formalizam isso como um problema de otimização com um termo de dados (data term) (casamento entre quadros) e um termo de suavidade (smoothness term) (regularização do fluxo).

Métodos clássicos de fluxo óptico

Lucas–Kanade: fluxo local, esparso (ou semidenso)

Lucas–Kanade (LK) assume que o fluxo é constante em uma pequena janela ao redor de cada pixel. Em uma vizinhança (\Omega), empilhamos as restrições:

[ I_x u + I_y v = -I_t ]

e resolvemos um problema de mínimos quadrados (least squares):

[ \min_{u,v} \sum_{(x,y)\in \Omega} (I_x u + I_y v + I_t)^2 ]

Propriedades-chave

  • Funciona melhor em cantos (corners) / regiões com textura em que os gradientes variam em ambas as direções.
  • Frequentemente usado para rastrear um conjunto de pontos de característica (feature points) (fluxo esparso), por exemplo, cantos de Shi–Tomasi.
  • Eficiente e amplamente usado em pipelines de rastreamento.

Nota prática: LK é fundamental para muitos rastreadores e pode ser usado como um modelo de movimento dentro de sistemas de Rastreamento de Objetos (por exemplo, para propagar caixas ou pontos-chave).

Horn–Schunck: fluxo global, denso

Horn–Schunck (HS) produz fluxo denso ao combinar:

  • um termo de dados de constância de brilho, e
  • um termo de suavidade global que penaliza gradientes do fluxo.

Uma energia HS comum é:

[ E(u,v)=\iint (I_x u + I_y v + I_t)^2 ,dx,dy ;+; \alpha^2 \iint (|\nabla u|^2 + |\nabla v|^2),dx,dy ]

em que (\alpha) controla a força da suavidade.

Propriedades-chave

  • Produz fluxo denso em toda parte, inclusive em áreas com pouca textura (graças à suavidade).
  • Pode suavizar em excesso através de fronteiras de movimento (uma fraqueza conhecida).
  • Motiva muitas formulações variacionais (variational) posteriores com penalizações mais robustas.

Métodos variacionais e penalizações robustas

Muitas abordagens “clássicas” modernas generalizam HS usando:

  • termos de dados robustos (por exemplo, perda de Charbonnier ou Huber) para outliers e mudança de iluminação,
  • suavidade robusta para preservar fronteiras de movimento (regularização sensível a bordas),
  • multiescala (pyramids) para lidar com grandes deslocamentos,
  • iterações de deformação (warping) para refinar estimativas.

Um baseline clássico amplamente usado na prática é o fluxo óptico TV-L1 (TV-L1 optical flow), que usa um regularizador de variação total (total-variation) e um termo de dados no estilo (L_1) para robustez.

Do grosseiro ao fino (pirâmides de imagens)

Movimentos grandes quebram a suposição de “movimento pequeno” na OFCE. Um truque padrão é:

  1. construir uma pirâmide de imagens (versões subamostradas),
  2. estimar o fluxo em resolução grosseira,
  3. reamostrar o fluxo e refinar em escalas mais finas com deformação.

Isso melhora o alcance de captura, mas pode ter dificuldade com estruturas finas ou objetos pequenos e rápidos que desaparecem em escalas grosseiras.

Fluxo óptico profundo moderno

Abordagens de aprendizado profundo (deep learning) substituem a otimização projetada manualmente por correspondência e refinamento aprendidos. A maioria dos modelos ainda reflete ideias clássicas (casamento + regularização), mas implementadas com redes neurais (neural networks).

Ideias-chave usadas por modelos profundos

  • Codificadores de características (feature encoders): aprendem representações robustas a mudanças de iluminação e desfoque (frequentemente Redes Neurais Convolucionais).
  • Volumes de custo (cost volumes) / correlação (correlation): comparam explicitamente características entre quadros para deslocamentos candidatos.
  • Refinamento iterativo (iterative refinement): atualiza repetidamente o fluxo (espírito similar à otimização baseada em deformação).
  • Regularização aprendida (learned regularization): usa contexto para propagar e “afiar” o fluxo, preservando bordas.
  • Raciocínio sobre oclusão (occlusion reasoning): infere onde o casamento é impossível (desoclusões (disocclusions)).

Modelos representativos (visão geral)

Família FlowNet

Os primeiros modelos profundos de fluxo óptico (FlowNet/FlowNet2) mostraram que uma rede ponta a ponta poderia prever fluxo. Esses modelos introduziram camadas de correlação e decodificação multiescala, mas muitas vezes precisavam de grandes conjuntos de treinamento e tinham dificuldade de generalização em comparação com métodos posteriores.

PWC-Net

PWC-Net é influente porque incorpora estrutura clássica:

  • processamento em Pirâmide,
  • Warping (deformação) de características pelo fluxo atual,
  • casamento via Cost volume (volume de custo).

Isso trouxe alta precisão com menos parâmetros e estabeleceu um template seguido por muitos sucessores.

RAFT (Recurrent All-Pairs Field Transforms)

RAFT tornou-se um marco por precisão e robustez. Suas ideias centrais:

  • Computar correlações all-pairs entre mapas de características (um grande volume de custo).
  • Usar um operador de atualização recorrente/iterativo para refinar o fluxo ao longo de muitas etapas.
  • Manter um estado oculto codificando contexto e regularização.

O refinamento iterativo no estilo RAFT é conceitualmente semelhante a executar um otimizador, mas o otimizador é aprendido.

Variantes baseadas em Transformer / correspondência global

Alguns modelos mais novos usam mecanismos semelhantes a atenção ou correspondência global (frequentemente inspirados na Arquitetura Transformer) para raciocinar sobre correspondências de longo alcance, o que pode ajudar com texturas repetitivas e grandes deslocamentos.

Sinais de treinamento: supervisionado e auto-supervisionado

Treinamento supervisionado (supervised training) usa fluxo ground-truth (a partir de dados sintéticos como FlyingChairs/FlyingThings3D ou sensores especializados). Ground-truth real de fluxo denso é difícil de obter, então a generalização de sintético para real é um tema central.

Treinamento auto-supervisionado (fotométrico) (self-supervised (photometric) training) usa consistência via deformação:

[ \mathcal{L}{photo} = \sum{x,y} \rho\left(I_t(x,y) - I_{t+1}(x+u, y+v)\right) ]

com penalidade robusta (\rho(\cdot)), além de regularizadores e máscaras de oclusão. Isso espelha de perto objetivos clássicos, mas usa uma rede para prever o fluxo e frequentemente aprende melhores priors.

Métodos auto-supervisionados conectam fluxo óptico a deformação diferenciável (differentiable warping) e aprendizado de representações (representation learning), uma ferramenta comum em Aprendizado Auto-Supervisionado para vídeo.

Avaliação e conjuntos de dados comuns

A precisão do fluxo óptico é tipicamente medida por:

  • EPE (erro de ponto final) (End-Point Error): distância Euclidiana entre vetores de fluxo preditos e verdadeiros.
  • Fl-all / taxa de outliers (outlier rate): porcentagem de pixels com erro grande (limiar específico do conjunto de dados).

Benchmarks comuns incluem Sintel e KITTI (entre outros), cada um com propriedades diferentes (efeitos cinematográficos vs. cenas de direção, desfoque de movimento, oclusões, superfícies refletivas).

Computação prática (o que pode dar errado?)

O fluxo óptico parece enganosamente simples de chamar a partir de uma biblioteca, mas os resultados dependem fortemente das condições:

  • Mudança de iluminação / cintilação: quebra a constância de brilho.
  • Desfoque de movimento (motion blur): “borra” gradientes, prejudicando a correspondência.
  • Oclusões / desoclusões: não existe correspondência correta para alguns pixels.
  • Texturas repetitivas: muitas correspondências plausíveis.
  • Regiões sem textura: problema da abertura; suavidade domina.
  • Obturador rolante (rolling shutter) / movimento não rígido (non-rigid motion): viola modelos simples de movimento.
  • Grande deslocamento: exige pirâmides ou casamento forte.

Em sistemas de produção, você frequentemente combina fluxo com:

  • medidas de confiança/incerteza,
  • verificações de consistência para frente–para trás (detecta oclusões),
  • agregação robusta ao longo do tempo (suavização temporal).

Exemplo: computando e visualizando fluxo com OpenCV (Farnebäck)

A seguir, um exemplo mínimo usando um método clássico denso (não aprendizado profundo). É útil para prototipagem e para tarefas como estabilização ou estimativa grosseira de movimento.

import cv2
import numpy as np

cap = cv2.VideoCapture("video.mp4")
ret, prev = cap.read()
prev_gray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)

hsv = np.zeros_like(prev)
hsv[..., 1] = 255  # full saturation for visualization

while True:
    ret, frame = cap.read()
    if not ret:
        break

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    flow = cv2.calcOpticalFlowFarneback(
        prev_gray, gray, None,
        pyr_scale=0.5, levels=3, winsize=15,
        iterations=3, poly_n=5, poly_sigma=1.2, flags=0
    )

    mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
    hsv[..., 0] = ang * 180 / np.pi / 2  # hue = direction
    hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)

    vis = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
    cv2.imshow("flow visualization", vis)

    if cv2.waitKey(1) & 0xFF == 27:
        break

    prev_gray = gray

cap.release()
cv2.destroyAllWindows()

Notas

  • Farnebäck é rápido e fácil, mas não é estado da arte.
  • Para fluxo clássico mais robusto, o OpenCV também oferece TV-L1 e outras variantes dependendo da build.

Como o fluxo óptico é usado na prática

1) Rastreamento de objetos e propagação de movimento

O fluxo óptico pode apoiar Rastreamento de Objetos ao:

  • propagar caixas/máscaras de objetos para frente no tempo,
  • conectar detecções entre quadros,
  • estabilizar correspondências de curto prazo quando detecções estão ausentes.

Exemplo: se você tem uma máscara de segmentação (M_t), pode deformá-la para o próximo quadro usando o fluxo para obter uma estimativa inicial (M_{t+1}), e então refinar com um modelo de segmentação.

O fluxo também é usado para rastrear pontos-chave (keypoints) (fluxo esparso no estilo LK), comum em realidade aumentada e robótica.

2) Estabilização de vídeo e estimativa de movimento da câmera

Um vídeo estabilizado tenta remover tremores indesejados da câmera. Um pipeline típico de estabilização:

  1. computar fluxo esparso ou denso entre quadros,
  2. estimar de forma robusta um modelo de movimento global (por exemplo, homografia (homography) ou afim (affine)) usando RANSAC (RANSAC),
  3. suavizar a trajetória da câmera,
  4. deformar quadros para compensar.

O fluxo óptico fornece correspondências que direcionam a estimação do modelo de movimento. Fluxo denso ajuda quando há poucos pontos de característica confiáveis, mas objetos em movimento podem contaminar o movimento global, a menos que isso seja tratado de forma robusta.

3) Reconhecimento de ações e compreensão de vídeo

Movimento é uma pista-chave para ações (“acenar”, “arremessar”, “correr”). Historicamente, o fluxo óptico foi usado para construir modelos de dois fluxos (two-stream) (RGB + fluxo) para reconhecimento de ações:

  • uma rede processa aparência (RGB),
  • outra processa movimento (campos de fluxo empilhados).

Mesmo conforme transformers de vídeo modernos aprendem movimento implicitamente, o fluxo continua útil:

  • como uma representação explícita de movimento,
  • para objetivos de pré-treinamento,
  • para interpretabilidade e diagnóstico de falhas.

Isso se conecta naturalmente a um aprendizado mais amplo de representações de vídeo em Redes Neurais e modelagem temporal.

4) Interpolação de quadros e geração de vídeo

Para sintetizar quadros intermediários entre (I_t) e (I_{t+1}), você pode:

  • estimar fluxo para frente/para trás,
  • deformar quadros em direção ao tempo intermediário,
  • combinar com pesos que considerem oclusão.

Modelos profundos de interpolação frequentemente usam fluxo internamente (explicitamente ou implicitamente) porque ele impõe coerência temporal e reduz artefatos de ghosting.

5) Segmentação, fronteiras de movimento e movimento em camadas

Descontinuidades de fluxo frequentemente se alinham com bordas de objetos. Isso é útil para:

  • segmentação de movimento (separar objetos que se movem de forma independente),
  • refinar máscaras de instância ao longo do tempo,
  • construir representações em camadas (movimento do fundo vs. primeiro plano).

6) Robótica: egomovimento, VO/SLAM e detecção de obstáculos

Embora SLAM/odometria visual acabem estimando movimento 3D, o fluxo óptico fornece uma medida 2D que se correlaciona fortemente com:

  • tempo até contato (time-to-contact) (aproximação),
  • movimento de obstáculos relativo à câmera,
  • rotação/translação da câmera (sob suposições sobre profundidade).

Para campos completos de movimento 3D, veja ideias relacionadas como fluxo de cena (scene flow) (fluxo 3D), que estende fluxo óptico com profundidade.

Padrões de implementação e boas práticas

Consistência para frente–para trás para oclusões

Um teste comum de confiabilidade:

  1. computar o fluxo para frente (F_{t\to t+1}),
  2. computar o fluxo para trás (F_{t+1\to t}),
  3. verificar se deformar para frente e depois para trás retorna ao início.

Grande inconsistência indica oclusão ou mismatch; você pode reduzir o peso desses pixels em perdas ou aplicações.

Detalhes de deformação e amostragem

Ao deformar imagens ou características usando fluxo:

  • use amostragem bilinear (bilinear sampling),
  • tenha cuidado com convenções de coordenadas (coordinate conventions) (centros de pixel, escala),
  • trate coordenadas fora dos limites (out-of-bounds) (mascare-as).

Escolhendo entre fluxo clássico e profundo

  • Fluxo clássico (classical flow) (TV-L1, Farnebäck, LK):
    • Prós: sem dados de treinamento, tempo de execução previsível, implantação fácil.
    • Contras: pior em movimento grande, oclusões, iluminação complexa.
  • Fluxo profundo (deep flow) (no estilo RAFT):
    • Prós: alta precisão, robustez forte, lida melhor com casos desafiadores.
    • Contras: computação mais pesada, tamanho do modelo, potencial mudança de domínio (domain shift), exige framework/ambiente de execução.

Uma abordagem pragmática é começar com um baseline clássico para validar o pipeline e, em seguida, migrar para fluxo profundo se a precisão importar.

Limitações e equívocos comuns

  • Fluxo não é velocidade 3D real. É movimento 2D no plano da imagem; o mesmo movimento 3D pode produzir fluxos diferentes dependendo da profundidade e dos intrínsecos da câmera (camera intrinsics).
  • Pixels ocluídos não têm correspondências válidas. Qualquer estimativa ali é efetivamente um palpite.
  • “Constância de brilho” é frequentemente violada. Bons métodos dependem de características e perdas robustas, em vez de casar intensidades brutas.
  • Fluxo denso pode parecer suave e ainda estar errado. Priors de suavidade podem “alucinar” movimento em regiões sem textura; estimativa de confiança importa.

Relação com tópicos próximos

Resumo

Fluxo óptico estima um campo de deslocamento denso por pixel entre quadros consecutivos. Métodos clássicos derivam da constância de brilho e adicionam restrições como constância local (Lucas–Kanade) ou suavidade global (Horn–Schunck), frequentemente implementadas com pirâmides e penalizações robustas. Modelos profundos modernos aprendem casamento e regularização, frequentemente usando volumes de custo e refinamento iterativo, alcançando forte desempenho em condições reais desafiadoras.

Na prática, fluxo óptico é menos um fim em si mesmo e mais um primitivo de movimento que viabiliza rastreamento, estabilização, segmentação temporal, interpolação e compreensão de ações/vídeo — tornando-o um conceito fundamental em sistemas de visão computacional que operam ao longo do tempo.