Detecção em Tempo Real com ResNet18 via Câmera: Experiência com GPU na Nuvem a Custo Baixo

Por que utilizar GPU na nuvem para testar o ResNet18?

Ao desenvolver sistemas inteligentes como portarias, muitos enfrentam limitações de desempenho em placas como Raspberry Pi, onde o ResNet18 pode operar a apenas 2-3 FPS, tornando a detecção inviável. GPUs na nuvem oferecem uma alternativa acessível, permitindo taxas de quadros acima de 20 FPS sem configuração complexa, com cobrança por uso e desligamento imediato.

Dica: Modelos como ResNet18 exigem poder computacional sginificativo; testar na nuvem antes de invetsir em hardware dedicado como Jetson reduz riscos financeiros.

Implantação rápida do ambiente em 5 minutos

Seleção de imagem pré-configurada

Utilize plataformas de computação em nuvem que ofereçam imagens com PyTorch 1.8+, torchvision, OpenCV e pesos do ResNet18 pré-carregados.

Inicialização da instância GPU

Escolha uma especificação básica de GPU (ex.: T4) e acesse via terminal web após a ativação.

Verificação do ambiente

Execute os seguintes comandos para confirmar a disponibilidade:

python -c "import torch; print(torch.cuda.is_available())"
python -c "import cv2; print(cv2.__version__)"

Desenvolvimento do script de detecção em tempo real

Crie um arquivo detecao.py com o código abaixo:

import cv2
import torch
import torchvision.transforms as transf
from torchvision.models import resnet18

# Configuração do modelo
rede = resnet18(pretrained=True).eval().cuda()
rotulos = open('rotulos_imagenet.txt').read().splitlines()  # Baixe conforme instrução

# Processamento do fluxo de vídeo
camera = cv2.VideoCapture(0)
transformacao = transf.Compose([
    transf.ToPILImage(),
    transf.Resize(256),
    transf.CenterCrop(224),
    transf.ToTensor(),
    transf.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

while True:
    sucesso, quadro = camera.read()
    if not sucesso:
        break

    # Pré-processamento e inferência
    tensor_entrada = transformacao(quadro).unsqueeze(0).cuda()
    with torch.no_grad():
        saida = rede(tensor_entrada)

    # Resultado
    _, predicao = torch.max(saida, 1)
    classe = rotulos[predicao.item()]
    cv2.putText(quadro, f"Classe: {classe}", (10,30), 
                cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2)

    cv2.imshow('ResNet18 Detecao', quadro)
    if cv2.waitKey(1) == 27:  # Tecla ESC para sair
        break

camera.release()
cv2.destroyAllWindows()

Baixe o arquivo de rótulos do ImageNet:

wget https://raw.githubusercontent.com/anishathalye/imagenet-simple-labels/master/imagenet-simple-labels.txt -O rotulos_imagenet.txt

Técnicas de otimização de parâmetros

Ajuste de resolução

Modifique transf.Resize(256) para valores entre 224-320: valores menores aumentam a velocidade mas reduzem precisão.

Melhoria de taxa de quadros

Adicione cálculo de FPS no laço principle:

import time
tempo_anterior = time.time()

while True:
    # ...código existente...
    tempo_atual = time.time()
    fps = 1/(tempo_atual - tempo_anterior)
    tempo_anterior = tempo_atual
    cv2.putText(quadro, f"FPS: {fps:.1f}", (10,70), 
                cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2)

Processamento com múltiplas threads

Separe captura e inferência usando threading:

from threading import Thread
import queue

fila_quadros = queue.Queue(maxsize=1)
fila_resultados = queue.Queue(maxsize=1)

def captura_thread():
    while True:
        sucesso, quadro = camera.read()
        if fila_quadros.empty():
            fila_quadros.put(quadro)

def inferencia_thread():
    while True:
        quadro = fila_quadros.get()
        # ...código de inferência...
        fila_resultados.put((quadro, classe))

Thread(target=captura_thread, daemon=True).start()
Thread(target=inferencia_thread, daemon=True).start()

while True:
    quadro, classe = fila_resultados.get()
    # ...código de exibição...

Problemas comuns e soluções

Inacesso à câmera

Servidores na nuvem não possuem câmeras físicas. Alternativas: usar câmeras IP (como smartphones) ou carregar arquivos de vídeo modificando camera = cv2.VideoCapture('teste.mp4').

Precisão insatisfatória

O ResNet18 é treinado para classificação ImageNet. Para melhorar: realize fine-tuning com seu dataset ou utilize modelos como SSD/YOLO para detecção.

Memória GPU limitada

Em GPUs com menos de 4GB, adicione torch.cuda.empty_cache() após inferências ou reduza o tamanho do batch (já é 1 neste caso).

Tags: ResNet18 Pytorch OpenCV GPU em nuvem detecção em tempo real

Publicado em 6-2 17:50 por Thomas