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 | Fundamentos de IA: investigando algoritmos e abordagens de machine learning

"""
CLASSIFICACAO DE OBJETOS COM MobileNetV2
Codigo pratico e otimizado para identificar objetos em imagens
"""

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import tensorflow as tf
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input, decode_predictions
import urllib.request

1. CARREGAR MODELO

print("Carregando MobileNetV2...")
modelo = MobileNetV2(weights='imagenet')
print("Pronto!\n")

2. PROCESSAR IMAGEM

def processar_imagem(caminho, tamanho=(224, 224)):
"""Pre-processa imagem para o modelo"""
if caminho.startswith('http'):
img = Image.open(urllib.request.urlopen(caminho))
else:
img = Image.open(caminho)

if img.mode != 'RGB':
    img = img.convert('RGB')

original = img.copy()
img = img.resize(tamanho)
arr = np.array(img)
arr = np.expand_dims(arr, axis=0)
arr = preprocess_input(arr)

return arr, original

3. CLASSIFICAR

def classificar(caminho):
"""Classifica objeto na imagem"""
arr, original = processar_imagem(caminho)
predicoes = modelo.predict(arr, verbose=0)
resultado = decode_predictions(predicoes, top=5)[0]

print("RESULTADOS:")
print("-" * 40)
for i, (id_classe, nome, conf) in enumerate(resultado, 1):
    print(f"{i}. {nome.upper()}: {conf*100:.2f}%")
print("-" * 40)

# Visualizar
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))

ax1.imshow(original)
ax1.set_title("Imagem Original")
ax1.axis('off')

nomes = [r[1].replace('_', ' ').title() for r in resultado]
confs = [r[2]*100 for r in resultado]
cores = ['#2ecc71', '#3498db', '#9b59b6', '#e74c3c', '#f39c12']

barras = ax2.barh(nomes, confs, color=cores[:len(nomes)])
ax2.set_xlabel('Confianca (%)')
ax2.set_title('Top 5 Predicoes')
ax2.set_xlim(0, 100)

for barra, conf in zip(barras, confs):
    ax2.text(conf+1, barra.get_y()+barra.get_height()/2,
            f'{conf:.1f}%', va='center')

plt.tight_layout()
plt.show()

4. EXEMPLOS

if name == "main":
print("="*40)
print("CLASSIFICACAO COM MobileNetV2")
print("="*40 + "\n")

# Exemplo 1: Gato
print("Exemplo 1: Identificando um gato...")
url_gato = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"
classificar(url_gato)

# Exemplo 2: Cachorro
print("\nExemplo 2: Identificando um cachorro...")
url_dog = "https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/YellowLabradorLooking_new.jpg/1200px-YellowLabradorLooking_new.jpg"
classificar(url_dog)

print("\n" + "="*40)
print("USAR COM SUAS IMAGENS:")
print("="*40)
print("""
# Arquivo local
classificar('caminho/imagem.jpg')

# URL da internet
classificar('https://exemplo.com/imagem.jpg')
""")

print("""
CLASSES RECONHECIDAS: 1000+ objetos
- Animais: gatos, caes, aves, etc
- Veiiculos: carros, bicicletas, etc
- Alimentos: pizzas, frutas, etc
- Objetos: moveis, eletronicos, etc
- Cenas: praia, montanha, etc

CARACTERISTICAS:
- Tamanho: 53 MB
- Velocidade: Muito rapido (~100ms)
- Precisao: 71% top-1, 90% top-5
- Ideal: Dispositivos moveis
""")

::

2 respostas

SAÍDA

Carregando MobileNetV2...
Pronto!

========================================
CLASSIFICACAO COM MobileNetV2

Exemplo 1: Identificando um gato...

HTTPError Traceback (most recent call last)
/tmp/ipykernel_33014/1312825473.py in <cell line: 0>()
81 print("Exemplo 1: Identificando um gato...")
82 url_gato = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"
---> 83 classificar(url_gato)
84
85 # Exemplo 2: Cachorro

7 frames/tmp/ipykernel_33014/1312825473.py in classificar(caminho)
39 def classificar(caminho):
40 """Classifica objeto na imagem"""
---> 41 arr, original = processar_imagem(caminho)
42 predicoes = modelo.predict(arr, verbose=0)
43 resultado = decode_predictions(predicoes, top=5)[0]

/tmp/ipykernel_33014/1312825473.py in processar_imagem(caminho, tamanho)
21 """Pre-processa imagem para o modelo"""
22 if caminho.startswith('http'):
---> 23 img = Image.open(urllib.request.urlopen(caminho))
24 else:
25 img = Image.open(caminho)

/usr/lib/python3.12/urllib/request.py in urlopen(url, data, timeout, cafile, capath, cadefault, context)
213 else:
214 opener = _opener
--> 215 return opener.open(url, data, timeout)
216
217 def install_opener(opener):

/usr/lib/python3.12/urllib/request.py in open(self, fullurl, data, timeout)
519 for processor in self.process_response.get(protocol, []):
520 meth = getattr(processor, meth_name)
--> 521 response = meth(req, response)
522
523 return response

/usr/lib/python3.12/urllib/request.py in http_response(self, request, response)
628 # request was successfully received, understood, and accepted.
629 if not (200 <= code < 300):
--> 630 response = self.parent.error(
631 'http', request, response, code, msg, hdrs)
632

/usr/lib/python3.12/urllib/request.py in error(self, proto, *args)
557 if http_err:
558 args = (dict, 'default', 'http_error_default') + orig_args
--> 559 return self._call_chain(*args)
560
561 # XXX probably also want an abstract factory that knows when it makes

/usr/lib/python3.12/urllib/request.py in _call_chain(self, chain, kind, meth_name, *args)
490 for handler in handlers:
491 func = getattr(handler, meth_name)
--> 492 result = func(*args)
493 if result is not None:
494 return result

/usr/lib/python3.12/urllib/request.py in http_error_default(self, req, fp, code, msg, hdrs)
637 class HTTPDefaultErrorHandler(BaseHandler):
638 def http_error_default(self, req, fp, code, msg, hdrs):
--> 639 raise HTTPError(req.full_url, code, msg, hdrs, fp)
640
641 class HTTPRedirectHandler(BaseHandler):

HTTPError: HTTP Error 403: Forbidden

solução!

Oii Estudante, tudo bem?

Obrigada por compartilhar o projeto aqui no fórum! Usar o MobileNetV2 com imagens da internet é uma boa forma de testar rapidamente, e a visualização com o gráfico de barras horizontais ficou bem organizada.

O erro HTTP Error 403: Forbidden não é um bug no seu código. O servidor do Wikimedia bloqueou a requisição porque o urllib não envia um cabeçalho User-Agent, e muitos servidores interpretam isso como acesso automatizado indesejado. Você pode resolver adicionando um User-Agent na requisição:

def processar_imagem(caminho, tamanho=(224, 224)):
    if caminho.startswith('http'):
        req = urllib.request.Request(
            caminho,
            headers={'User-Agent': 'Mozilla/5.0'}
        )
        img = Image.open(urllib.request.urlopen(req))
    else:
        img = Image.open(caminho)
    # ... resto do código

Só isso já resolve o 403 na maioria dos casos. Uma alternativa, se quiser evitar dependência de URLs externas, é baixar as imagens localmente e usar o caminho de arquivo direto.

Conte com a Alura para evoluir seus estudos. Em caso de dúvidas, fico à disposição.

Bons estudos!

Sucesso

Imagem da comunidade