Demonstrações interativas da aula de aplicações de CNN em visão computacional
Quatro visualizações que acompanham os slides: a arquitetura da VGG16 camada a camada, com a contagem de parâmetros Kh·Kw·Cin·Cout mostrando onde os ~138M de pesos se concentram; as métricas de localização IoU = (A ∩ B)/(A ∪ B) e Dice = 2·(A ∩ B)/(Area(A) + Area(B)) com caixas arrastáveis; a supressão de não máximos (NMS) usada pelos detectores de objetos, com limiares de confiança e de IoU ajustáveis; e a segmentação semântica, comparando a ideia ingênua de janela deslizante com a predição densa de um encoder-decoder. Notação dos slides: caixa y = (x, y, h, w) em coordenadas normalizadas, com (0, 0) no canto superior esquerdo e (1, 1) no inferior direito.
A VGG16 transforma um tensor (224, 224, 3) em um vetor de 1000 classes combinando convoluções 3×3 com ReLU (mantêm a dimensão espacial), max pooling 2×2 com stride 2 (reduz largura e altura pela metade) e três camadas densas no fim. Cada camada convolucional tem Kh·Kw·Cin·Cout pesos (ignorando o bias, como nos slides) e cada densa tem nin·nout. Percorra as camadas e observe o gráfico de barras: a distribuição dos parâmetros entre convoluções e densas é tudo menos uniforme.
Pirâmide de tensores da VGG16 (a camada atual fica destacada; clique numa camada para selecioná-la)
Parâmetros por camada treinável, em milhões
💡 Avance até conv1_2 e compare com conv1_1: o número de pesos salta de 1.728 para 36.864 só porque Cin passou de 3 para 64. Depois vá até fc1: uma única camada densa concentra 102,8M de parâmetros, mais que todas as 13 convoluções somadas (~14,7M). É por isso que, ao reaproveitar a VGG como backbone, costuma-se descartar as densas e treinar uma cabeça nova.
Na aula, a bounding box é modelada como regressão multivariada do vetor y = (x, y, h, w), com 4 saídas sigmoide e custo MSE. Para avaliar a qualidade da caixa prevista B contra o ground truth A usamos IoU = (A ∩ B)/(A ∪ B) e Dice = 2·(A ∩ B)/(Area(A) + Area(B)), ambas com valor ideal 1. Arraste as caixas pelo corpo para movê-las e pelo quadradinho do canto inferior direito para redimensioná-las: as duas métricas e o MSE entre os vetores são recalculados ao vivo.
Imagem em coordenadas normalizadas: ground truth A, predição B e interseção A ∩ B (arraste para mover, canto para redimensionar)
Dice em função do IoU: para a mesma sobreposição, Dice = 2·IoU/(1 + IoU) ≥ IoU
💡 Reproduza o exemplo numérico dos slides: deixe as duas caixas com a mesma área e interseção igual à metade dela, e confira IoU ≈ 0,333 contra Dice = 0,5. Depois sobreponha B perfeitamente em A (as duas métricas vão a 1) e afaste B até a interseção zerar. Note no gráfico à direita que o Dice é sempre maior ou igual ao IoU, com igualdade apenas em 0 e 1: o IoU penaliza mais a mesma sobreposição. Note também que um MSE pequeno entre os vetores não garante IoU alto quando as caixas são pequenas.
Na detecção de objetos a imagem pode conter vários objetos e não sabemos quantos de antemão. Detectores como YOLO e SSD produzem dezenas de caixas candidatas, cada uma com uma classe e uma pontuação de confiança, e várias delas cobrem o mesmo objeto. A non-maximum suppression (NMS) resolve a redundância: descartam-se as caixas com confiança abaixo do limiar τ, ordenam-se as restantes por confiança e, para cada caixa mantida, suprimem-se as caixas da mesma classe com IoU acima do limiar de sobreposição. O DETR, visto no fim da aula, elimina essa etapa ao prever diretamente um conjunto de caixas.
Antes do NMS: caixas candidatas com confiança ≥ τ (o número é a confiança)
Depois do NMS: caixas mantidas (sólidas) e ground truth (tracejado)
💡 Com τ = 0,50 e IoU do NMS em 0,50, sobra tipicamente uma caixa por objeto. Suba o IoU do NMS para 0,9 e veja duplicatas sobrevivendo (a precisão cai); desça para 0,1 e a supressão fica agressiva demais quando dois objetos se encostam. Agora zere τ: entram falsos positivos de baixa confiança que o NMS não remove, pois têm pouca sobreposição com as caixas boas. A precisão e a revocação no painel usam o critério usual de acerto, IoU ≥ 0,5 com um ground truth da mesma classe.
Segmentação semântica é classificação em nível de pixel: cada pixel recebe uma classe. A primeira ideia, ingênua, recorta um patch em torno de cada pixel e roda a CNN para classificar o pixel central, repetindo para a imagem inteira: são milhares de forwards redundantes, pois patches vizinhos compartilham quase todo o conteúdo. A arquitetura encoder-decoder resolve isso em um único forward: o encoder reduz a dimensão espacial com convoluções e pooling, e o decoder a expande de volta com unpooling e convoluções transpostas, produzindo a máscara inteira de uma vez. As abas comparam ainda segmentação semântica (todas as pessoas com a mesma cor) com segmentação de instâncias (cada pessoa com uma cor distinta).
Imagem de entrada (o quadrado laranja é o patch da janela deslizante)
Máscara de saída: uma classe por pixel
💡 Rode a janela deslizante em 32×32 e conte: 1.024 forwards para uma máscara minúscula. Suba a resolução para 64×64 e o custo quadruplica para 4.096, enquanto o encoder-decoder continua custando 1 forward em qualquer resolução (para 224×224 a ideia ingênua exigiria 50.176 forwards). Troque para a aba Instâncias e compare com a figura dos slides: na segmentação semântica os cinco objetos da classe pessoa formam uma única região de cor, na segmentação de instâncias cada pessoa recebe a sua.