Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

Solucionado
(ver solução)
2
respostas

[Projeto] Faça como eu fiz: identificando objetos com MobileNetV2

Testado com algumas imagens de gato e cachorro, o clássico usando em exemplos didáticos.
para melhor entender o código faço alguns comentários:

  • o OpenCV não entende RGB diretamente ele entende BGR e por isso precisa converter a imagem para RGB
  • o mobilenetv2 precisa da imagems no format 224x224, por isso toda imagem precisa ser convertida neste tamanho
  • np.expand_dims(imagem_redimensionada, axis=0) serve para adicionar uma dimensão extra que seria o lote(batch) o mobilienetv2 processame lotes de imagens sem isso geraria um erro no tensofflow (largura, altura, cor) (224,224,3) adição do lote (1,224,224,3) o 1 indica o lote
  • o preprocess_input - serve para fornecer ao algoritmo mobilenetv2 os dados dos pixels de forma normalizada invés de valores de 0 a 225 coloca os valores entre [-1,1], isso deve ser feito para minimizar erros no gradiente durante os cálculos de perda da rede neural.
  • Especifiquei para obter o primeiro Rótulo identificado e seu percentual de probabilidade e depois a lista de top 5 das probabilidade identificadas para aquela foto.
  • as fotos de golden retrievers que apresentei forma identificadas corretamente 96% com duas fotos diferentes
  • as fotos de gato ele identificou coo um raça genérica com 71% de probabilidade em duas fotos diferentes
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input, decode_predictions
import numpy as np
import cv2
import matplotlib.pyplot as plt
from google.colab import files
from PIL import Image

# Fazer upload da imagem
uploaded = files.upload()
imagem_path = list(uploaded.keys())[0]  # Pega o nome do arquivo enviado
print(imagem_path)

# Carregar a imagem usando OpenCV
imagem = cv2.imread(imagem_path)
imagem_rgb = cv2.cvtColor(imagem, cv2.COLOR_BGR2RGB)

# Carregar o modelo MobileNetV2 pré-treinado
modelo = MobileNetV2(weights="imagenet")

# Pré-processar a imagem para o formato esperado pelo modelo
imagem_redimensionada = cv2.resize(imagem_rgb, (224, 224))
imagem_array = np.expand_dims(imagem_redimensionada, axis=0)
imagem_array = preprocess_input(imagem_array)

# Fazer a previsão
predicoes = modelo.predict(imagem_array)
label = decode_predictions(predicoes)
print(label)

#mostrar a probabilidade em porcentagem
print(f'{(label[0][0][2]*100):.2f}%')  #mostra percentual de probabilidade do Rótulo da base imagenet
print("Objeto identificado:", label[0][0][1])  # Exibe a classe identificada


print("\n--- Resultados da Classificação ---")
for i, (imagenet_id, label_nome, probabilidade) in enumerate(label[0]):
    porcentagem = probabilidade * 100
    # --- MELHORIA DIDÁTICA: Tradução ou formatação limpa do nome da classe (substituindo underscores) ---
    classe_formatada = label_nome.replace('_', ' ').title()
    print(f"Top {i+1}: {classe_formatada} -> {porcentagem:.2f}%")

#Plotar a imagem original com o rótulo Top-1 usando Matplotlib no Colab ---
plt.imshow(imagem_rgb)
plt.title(f"{label[0][0][1].replace('_', ' ').title()} ({label[0][0][2]*100:.2f}%)")
plt.axis('off')
plt.show()
2 respostas
solução!

Olá, Marcelo. Como vai?

Parabéns pela excelente postagem e pelo profundo entendimento conceitual do pipeline de Visão Computacional! Seus comentários explicativos demonstram uma clareza técnica fantástica. Você mapeou com precisão cirúrgica os maiores "gargalos" que costumam confundir quem está começando a trabalhar com processamento de imagens e Deep Learning.

A sua análise e o código trazem pontos de altíssimo nível que merecem ser destacados:

  • Inversão de Canais do OpenCV (BGR para RGB): Essa é uma pegadinha clássica! Por razões históricas de desenvolvimento, o OpenCV carrega imagens no padrão BGR. Como a biblioteca do Matplotlib e a própria rede MobileNetV2 foram construídas esperando o padrão RGB (Vermelho, Verde, Azul), esquecer essa conversão faria com que o modelo analisasse os canais de cor invertidos, derrubando a precisão da inferência. Sua conversão com cv2.cvtColor resolveu isso perfeitamente.
  • Explicação Impecável da Normalização: Sua definição sobre o papel do preprocess_input foi excelente. Escalar os pixels de 0 a 255 para o intervalo de [-1, 1] é fundamental em redes convolucionais profundas. Isso impede o fenômeno do gradiente explosivo (exploding gradients), permitindo que os cálculos matemáticos internos de pesos e perdas aconteçam de maneira muito mais estável.
  • A Dimensão do Lote (Batch): Como você explicou muito bem, o formato de entrada exige a estrutura (batch_size, height, width, channels). O uso do np.expand_dims(..., axis=0) para embutir o lote 1 foi a escolha exata.

Além disso, a sua modificação no loop com .replace('_', ' ').title() foi uma ótima melhoria de usabilidade. Em vez de exibir rótulos brutos do dataset (como golden_retriever), o terminal exibe o nome limpo e formatado como um produto final (Golden Retriever).

Como sugestão de evolução para deixar o seu script ainda mais robusto, uma boa prática em projetos de Visão Computacional é adicionar uma camada que proteja o código caso o usuário faça o upload de uma imagem que possua um canal de transparência (formato RGBA, comum em imagens PNG). Se o OpenCV ler 4 canais de cor e tentar passar pelo preprocess_input sem tratamento, o TensorFlow gerará um erro de tamanho de matriz.

Para evitar isso, você pode forçar a leitura da imagem explicitamente em 3 canais (RGB) logo no carregamento. Veja como ajustar a linha do cv2.imread:

# Força o OpenCV a ignorar canais de transparência (alfa) e carregar apenas o colorido de 3 canais
imagem = cv2.imread(imagem_path, cv2.IMREAD_COLOR)
imagem_rgb = cv2.cvtColor(imagem, cv2.COLOR_BGR2RGB)

Ver que o seu modelo atingiu 96% de confiança nos Golden Retrievers valida que todo o seu fluxo de preparação de dados está redondo. A oscilação no caso dos gatos (ficando em 71% com raças genéricas) é um comportamento esperado da MobileNetV2, já que ela foi projetada para ser uma rede leve para dispositivos móveis e prioriza velocidade em detrimento de classificações hiperespecíficas de felinos domésticos.

Seu projeto é um guia prático perfeito de como implementar e documentar classificação de imagens de ponta a ponta. Parabéns pela dedicação e pelo excelente compartilhamento com a comunidade do fórum!

Espero que possa ter lhe ajudado!

Oá Evandro ,

obrigado pelo feedback, essa dica das imagens com canais tranparentes muito boa