Estimativa de Profundidade Monocular com o Modelo MiDaS: Princípios e Implementação

Introdução à Estimativa de Profundidade a partir de uma Única Imagem

No campo da visão computacional, a estimativa de profundidade monocular é uma tarefa que infere a distância de cada pixel em relação à câmera usando apenas uma única imagem 2D. Essa capacidade é fundamental para sistemas como veículos autônomos, realidade aumentada e reconstrução 3D.

O modelo MiDaS (Mixed Data Set), desenvolvido pelo Intel ISL, utiliza uma estratégia de treinamento em dados diversificados para criar um estimador de profundidade com forte capacidade de generalização. Ele combina mais de 10 conjuntos de dados diferentes, alinhando anotações de profundidade relativa e absoluta por meio de um mecanismo de normalização de escala.

Arquitetura e Mecanismo Principal

O MiDaS emprega uma estrutura encoder-decoder, com duas variações principais de backbone: o ResNet50 para alta precisão e o MiDaS_small, uma versão otimizada para dispositivos com restrição de recursos, como CPUs. O decoder utiliza convoluções transpostas e conexões de salto (skip connections) para fundir características de múltiplas escalas, preservando detalhes espaciais nas bordas dos objetos.

O fluxo de processamento consiste em:

  1. Pré-processamento e normalização da imagem de entrada.
  2. Extração de características em múltiplos níveis pelo encoder.
  3. Reconstrução progressiva e fusão de características no decoder.
  4. Geração do mapa de profundidade final.

Para visualização, o mapa de profundidade em tons de cinza é frequentemente convertdio em um mapa térmico pseudo-cor usando uma paleta como a Inferno do OpenCV. Nessa representação, tons quentes (vermelho/amarelo) indicam proximidade, enquanto tons frios (azul/violeta) indicam objetos distantes.

Implementação Prática com Interface Web em CPU

A seguinte implementação demonstra como integrar o modelo MiDaS_small em uma aplicação web leve, construída com PyTorch e Streamlit. A solução é projetada para execução estável em CPU, sem necessidade de tokens de autenticação.

Configuração do Ambiente e Carregamanto do Modelo

O modelo é carregado diretamente do repositório oficial via torch.hub, garantindo uma configuração simples. A função estimate_depth orquestra todo o pipeline de inferência.

import torch
import cv2
import numpy as np
import streamlit as st
from PIL import Image

# Função para carregar o modelo, com cache para melhor desempenho
@st.cache_resource
def inicializar_modelo():
    rede = torch.hub.load("intel-isl/MiDaS", "MiDaS_small")
    rede.eval()
    return rede

# Função principal para estimar a profundidade
def estimar_profundidade(imagem_pil):
    modelo = inicializar_modelo()
    # Obtém a transformação específica para o modelo small
    transformador = torch.hub.load("intel-isl/MiDaS", "transforms").small_transform

    # Aplica transformações e adiciona dimensão do batch
    tensor_entrada = transformador(imagem_pil).unsqueeze(0)

    # Realiza a inferência
    with torch.no_grad():
        predicao = modelo(tensor_entrada)

    # Pós-processamento: redimensiona e normaliza os valores para [0, 1]
    mapa_bruto = predicao[0].cpu().numpy()
    mapa_redimensionado = cv2.resize(mapa_bruto, (imagem_pil.width, imagem_pil.height))
    mapa_normalizado = (mapa_redimensionado - mapa_redimensionado.min()) / (mapa_redimensionado.max() - mapa_redimensionado.min())

    # Converte para mapa de cores térmico
    mapa_colorido = cv2.applyColorMap(
        (mapa_normalizado * 255).astype(np.uint8),
        cv2.COLORMAP_INFERNO
    )

    return mapa_colorido

Desenvolvimento da Interface do Usuário

A interface é construída com Streamlit para oferecer upload de imagem, visualização do resultado e opção de download.

import io

st.title("Estimativa de Profundidade com IA")
uploaded_file = st.file_uploader("Selecione uma imagem", type=["jpg", "jpeg", "png"])

if uploaded_file is not None:
    imagem_original = Image.open(uploaded_file).convert("RGB")
    st.image(imagem_original, caption="Imagem Original", use_column_width=True)

    with st.spinner("Calculando a profundidade..."):
        mapa_profundidade = estimar_profundidade(imagem_original)

    st.image(mapa_profundidade, caption="Mapa de Profundidade (quente=perto, frio=longe)", use_column_width=True)

    # Prepara a imagem para download
    imagem_resultado = Image.fromarray(cv2.cvtColor(mapa_profundidade, cv2.COLOR_BGR2RGB))
    buffer_saida = io.BytesIO()
    imagem_resultado.save(buffer_saida, format="PNG")

    st.download_button(
        label="Download do Mapa de Profundidade",
        data=buffer_saida.getvalue(),
        file_name="mapa_profundidade.png",
        mime="image/png"
    )

Otimizações para Ambiente de Produção

Para melhorar o desempenho em CPU em um cenário de deploy, recomenda-se:

  • Limitar a resolução de entrada: Redimensionar automaticamente imagens grandes (ex: máximo 640px no lado maior) para reduzir o consumo de memória e acelerar a inferência.
  • Uso de cache eficiente: O decorador @st.cache_resource evita recarregar o modelo a cada requisição.
  • Processamento por lotes (batch): Para alta concorrência, considerar servidores com Gunicorn em modo multi-processo.
  • Formato dos dados: Garantir que a imagem de entrada PIL seja convertida para RGB antes do processamento para evitar erros na aplicação do mapa de cores.

A adoção de frameworks de inferência otimizados como ONNX Runtime ou a quantização do modelo (FP16/INT8) representam passos subsequentes para aumentar a velocidade, especialmente se houver disponibilidade de hardware acelerado como GPUs.

Tags: MiDaS Monocular Depth Estimation computer vision Pytorch Streamlit

Publicado em 6-12 04:21 por Thomas