joaopaulofcc

Untitled

Nov 19th, 2025
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.79 KB | None | 0 0
  1. """
  2. =========================================================================================
  3.                        TREINADOR DE REDE NEURAL (CNN) - OCR
  4. =========================================================================================
  5. ARQUIVO DE ATIVIDADE: PREENCHA AS LACUNAS (TODO)
  6. -----------------------------------------------------------------------------------------
  7. Este script já possui:
  8. 1. O carregamento das imagens da pasta 'dataset_limpo'.
  9. 2. O pré-processamento (normalização, redimensionamento).
  10. 3. A geração automática de relatórios e gráficos no final.
  11.  
  12. SUA MISSÃO:
  13. Você é o arquiteto do cérebro da IA. Você deve projetar as camadas (criar_modelo_cnn)
  14. e iniciar o treinamento (.fit). Siga os comentários marcados com 'TODO'.
  15. =========================================================================================
  16. """
  17.  
  18. import os
  19. import cv2
  20. import numpy as np
  21. import matplotlib.pyplot as plt
  22. import seaborn as sns
  23. from sklearn.model_selection import train_test_split
  24. from sklearn.metrics import confusion_matrix
  25. from tensorflow.keras.utils import to_categorical
  26. from tensorflow.keras.models import Sequential
  27. from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
  28. from tensorflow.keras.preprocessing.image import ImageDataGenerator
  29. from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau
  30.  
  31. # --- CONFIGURAÇÕES GLOBAIS ---
  32. PASTA_DATASET = "dataset_limpo"
  33. PASTA_RELATORIO = "relatorio_final"
  34. TAMANHO_IMAGEM = (128, 128)
  35. NUM_CLASSES = 12 # A-F e 0-5
  36. CLASSES_NOMES = ['A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3', '4', '5']
  37.  
  38. os.makedirs(PASTA_RELATORIO, exist_ok=True)
  39.  
  40. # ==============================================================================
  41. # 1. PREPARAÇÃO DOS DADOS (JÁ IMPLEMENTADO - NÃO MEXER)
  42. # ==============================================================================
  43. def processar_imagem(caminho_imagem):
  44.     img = cv2.imread(caminho_imagem, cv2.IMREAD_GRAYSCALE)
  45.     if img is None: return None
  46.     img = cv2.resize(img, TAMANHO_IMAGEM, interpolation=cv2.INTER_AREA)
  47.     img = img / 255.0 # Normalização
  48.     img = 1.0 - img   # Inversão
  49.     return img
  50.  
  51. def carregar_dados():
  52.     print("\n--- 1. CARREGANDO IMAGENS ---")
  53.     X_data = []
  54.     Y_data = []
  55.     mapa_rotulos = {name: i for i, name in enumerate(CLASSES_NOMES)}
  56.  
  57.     for rotulo_nome, rotulo_idx in mapa_rotulos.items():
  58.         pasta_caractere = os.path.join(PASTA_DATASET, rotulo_nome)
  59.         if not os.path.isdir(pasta_caractere): continue
  60.        
  61.         arquivos = [f for f in os.listdir(pasta_caractere) if f.lower().endswith(('png', 'jpg', 'jpeg'))]
  62.         print(f"-> Lendo classe '{rotulo_nome}': {len(arquivos)} imagens.")
  63.        
  64.         for nome_arquivo in arquivos:
  65.             caminho = os.path.join(pasta_caractere, nome_arquivo)
  66.             matriz = processar_imagem(caminho)
  67.             if matriz is not None:
  68.                 X_data.append(matriz)
  69.                 Y_data.append(rotulo_idx)
  70.  
  71.     X_data = np.array(X_data)
  72.     Y_data = np.array(Y_data)
  73.     X_data = np.expand_dims(X_data, axis=-1) # Adiciona canal de cor (1)
  74.     Y_data_one_hot = to_categorical(Y_data, num_classes=NUM_CLASSES)
  75.    
  76.     return train_test_split(X_data, Y_data_one_hot, test_size=0.2, random_state=42)
  77.  
  78. # ==============================================================================
  79. # 2. ARQUITETURA DA REDE (SUA MISSÃO: COMPLETAR O CÓDIGO)
  80. # ==============================================================================
  81. def criar_modelo_cnn():
  82.     # Inicializa um modelo sequencial (uma pilha de camadas)
  83.     model = Sequential()
  84.  
  85.     print("--- 2. CONSTRUINDO O CÉREBRO DA IA ---")
  86.  
  87.     # --- TODO 1: DEFINA AS CAMADAS (O CÉREBRO) ---
  88.     # Uma CNN funciona como um funil: Começa vendo detalhes (bordas) e termina vendo conceitos (letras).
  89.    
  90.     # PASSO A: Camada de Entrada (A Visão)
  91.     # Adicione uma camada Conv2D.
  92.     # ATENÇÃO: Só a primeira camada precisa do argumento 'input_shape'.
  93.     # Nossas imagens são (128, 128, 1).
  94.     # Exemplo: model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(128, 128, 1)))
  95.    
  96.     # model.add(...) # <--- Descomente e preencha ou copie o exemplo acima
  97.  
  98.     # PASSO B: Camada de Resumo (Pooling)
  99.     # Adicione um MaxPooling2D para reduzir o tamanho da imagem pela metade.
  100.     # Isso torna o processamento mais rápido.
  101.     # model.add(MaxPooling2D((2, 2)))
  102.  
  103.     # PASSO C: Mais camadas de processamento (Repetição)
  104.     # Adicione mais um bloco Conv2D + MaxPooling2D.
  105.     # DICA: Aumente o número de filtros (ex: de 32 para 64) para a IA ver detalhes mais complexos.
  106.     # model.add(...) # Conv2D com 64 filtros
  107.     # model.add(...) # MaxPooling2D
  108.  
  109.     # PASSO D: A Tradução (Flatten)
  110.     # As camadas Conv2D são 3D (altura, largura, filtros).
  111.     # As camadas de decisão (Dense) são 1D (lista de números).
  112.     # Precisamos "achatar" a imagem. Pesquise sobre a camada 'Flatten'.
  113.     # model.add(...)
  114.  
  115.     # PASSO E: O Raciocínio (Dense)
  116.     # Adicione uma camada Dense com 128 neurônios e ativação 'relu'.
  117.     # Adicione um Dropout(0.5) para evitar que a IA "decore" a prova.
  118.     # model.add(...)
  119.     # model.add(...)
  120.  
  121.     # PASSO F: A Resposta Final (Saída)
  122.     # A última camada DEVE ter o mesmo número de neurônios que as classes (12).
  123.     # A ativação DEVE ser 'softmax' (para dar a % de probabilidade de cada letra).
  124.     # USE A VARIÁVEL 'NUM_CLASSES' AQUI, NÃO DIGITE '12' DIRETAMENTE.
  125.     # model.add(...)
  126.  
  127.    
  128.     # --- TODO 2: COMPILE O MODELO (AS REGRAS DO JOGO) ---
  129.     # Precisamos dizer como a IA deve aprender.
  130.     # Pesquise: "keras compile categorical crossentropy adam"
  131.    
  132.     # Preencha os parâmetros abaixo:
  133.     # optimizer= ? (Sugestão: 'adam')
  134.     # loss= ?      (Sugestão: 'categorical_crossentropy' -> pois temos várias categorias)
  135.     # metrics= ?   (Sugestão: ['accuracy'])
  136.    
  137.     # model.compile(optimizer=..., loss=..., metrics=...)
  138.    
  139.     return model
  140.  
  141. # ==============================================================================
  142. # 3. RELATÓRIOS E GRÁFICOS (JÁ IMPLEMENTADO)
  143. # ==============================================================================
  144. def salvar_graficos_historico(history):
  145.     acc = history.history['accuracy']
  146.     val_acc = history.history['val_accuracy']
  147.     loss = history.history['loss']
  148.     val_loss = history.history['val_loss']
  149.     epochs_range = range(len(acc))
  150.  
  151.     plt.figure(figsize=(14, 5))
  152.     plt.subplot(1, 2, 1)
  153.     plt.plot(epochs_range, acc, label='Treino (Estudo)')
  154.     plt.plot(epochs_range, val_acc, label='Validação (Prova)')
  155.     plt.legend(loc='lower right')
  156.     plt.title('Acurácia')
  157.     plt.grid(True)
  158.  
  159.     plt.subplot(1, 2, 2)
  160.     plt.plot(epochs_range, loss, label='Treino')
  161.     plt.plot(epochs_range, val_loss, label='Validação')
  162.     plt.legend(loc='upper right')
  163.     plt.title('Loss (Erro)')
  164.     plt.grid(True)
  165.    
  166.     caminho = os.path.join(PASTA_RELATORIO, "grafico_evolucao.png")
  167.     plt.savefig(caminho)
  168.     print(f"[Relatório] Gráfico salvo em: {caminho}")
  169.  
  170. def salvar_matriz_confusao(model, X_test, Y_test):
  171.     Y_pred_probs = model.predict(X_test)
  172.     Y_pred = np.argmax(Y_pred_probs, axis=1)
  173.     Y_true = np.argmax(Y_test, axis=1)
  174.     cm = confusion_matrix(Y_true, Y_pred)
  175.    
  176.     plt.figure(figsize=(10, 8))
  177.     sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=CLASSES_NOMES, yticklabels=CLASSES_NOMES)
  178.     plt.xlabel('IA Previu')
  179.     plt.ylabel('Real')
  180.     plt.title('Matriz de Confusão')
  181.    
  182.     caminho = os.path.join(PASTA_RELATORIO, "matriz_confusao.png")
  183.     plt.savefig(caminho)
  184.     print(f"[Relatório] Matriz salva em: {caminho}")
  185.  
  186. def salvar_previsoes_visuais(model, X_test, Y_test):
  187.     indices = np.random.choice(len(X_test), 15, replace=False)
  188.     plt.figure(figsize=(15, 8))
  189.     plt.suptitle("Teste Visual (Verde=Acerto, Vermelho=Erro)", fontsize=16)
  190.    
  191.     for i, idx in enumerate(indices):
  192.         img = X_test[idx]
  193.         label_real = CLASSES_NOMES[np.argmax(Y_test[idx])]
  194.         pred_probs = model.predict(np.expand_dims(img, axis=0), verbose=0)
  195.         pred_label = CLASSES_NOMES[np.argmax(pred_probs)]
  196.         conf = np.max(pred_probs) * 100
  197.         cor = 'green' if label_real == pred_label else 'red'
  198.        
  199.         plt.subplot(3, 5, i + 1)
  200.         plt.imshow(img.squeeze(), cmap='gray')
  201.         plt.axis('off')
  202.         plt.title(f"Real: {label_real}\nIA: {pred_label} ({conf:.1f}%)", color=cor, fontsize=10, fontweight='bold')
  203.        
  204.     plt.tight_layout()
  205.     caminho = os.path.join(PASTA_RELATORIO, "exemplos_visuais.png")
  206.     plt.savefig(caminho)
  207.     print(f"[Relatório] Exemplos salvos em: {caminho}")
  208.  
  209. def salvar_resumo_texto(score_loss, score_acc):
  210.     caminho = os.path.join(PASTA_RELATORIO, "resumo_metricas.txt")
  211.     with open(caminho, "w") as f:
  212.         f.write(f"Acurácia Final: {score_acc*100:.2f}%\nPerda Final: {score_loss:.4f}\n")
  213.     print(f"[Relatório] Resumo salvo em: {caminho}")
  214.  
  215. # ==============================================================================
  216. # 4. EXECUÇÃO PRINCIPAL
  217. # ==============================================================================
  218. if __name__ == "__main__":
  219.     # 1. Carregar Dados
  220.     X_train, X_test, Y_train, Y_test = carregar_dados()
  221.     print(f"\n[Status] Dataset carregado. Treino: {X_train.shape}, Teste: {X_test.shape}")
  222.  
  223.     # 2. Criar Modelo
  224.     modelo = criar_modelo_cnn()
  225.    
  226.     # Validação pedagógica (Checagem de erro)
  227.     if not hasattr(modelo, 'optimizer') or modelo.optimizer is None:
  228.         print("\n[ERRO FATAL] O modelo não foi compilado!")
  229.         print("Vá até a função 'criar_modelo_cnn' e complete o TODO 2 (model.compile).")
  230.         exit()
  231.  
  232.     try:
  233.         modelo.summary()
  234.     except ValueError:
  235.         print("\n[ERRO FATAL] O modelo não tem camadas!")
  236.         print("Vá até a função 'criar_modelo_cnn' e complete o TODO 1 (model.add).")
  237.         exit()
  238.  
  239.     # 3. Data Augmentation
  240.     print("\n--- 3. CONFIGURANDO DATA AUGMENTATION ---")
  241.     datagen = ImageDataGenerator(
  242.         rotation_range=15, width_shift_range=0.1, height_shift_range=0.1,
  243.         zoom_range=0.15, shear_range=0.1, fill_mode='nearest'
  244.     )
  245.  
  246.     callbacks = [
  247.         EarlyStopping(patience=5, monitor='val_loss', restore_best_weights=True),
  248.         ReduceLROnPlateau(patience=3, factor=0.5, monitor='val_loss')
  249.     ]
  250.  
  251.     # --- TODO 3: INICIAR O TREINAMENTO (DAR PLAY) ---
  252.     print("\n--- 4. INICIANDO TREINAMENTO ---")
  253.     # Aqui conectamos tudo: imagens (datagen), respostas (Y_train) e regras (callbacks).
  254.    
  255.     # Preencha os argumentos da função .fit():
  256.     # historico = modelo.fit(
  257.     #     datagen.flow(X_train, Y_train, batch_size=32), # Onde estão as imagens de treino?
  258.     #     epochs= ?,                      # Quantas vezes a IA vai ler o dataset? (Tente 40)
  259.     #     validation_data=(?, ?),         # Onde estão os dados de prova? (X_test, Y_test)
  260.     #     callbacks=callbacks             # Regras de parada
  261.     # )
  262.    
  263.     # historico = modelo.fit(...)
  264.    
  265.    
  266.     # --- 5. SALVAMENTO E RELATÓRIO ---
  267.     if 'historico' in locals():
  268.         print("\n--- 5. GERANDO RELATÓRIO FINAL ---")
  269.         caminho_modelo = os.path.join(PASTA_RELATORIO, 'modelo_ocr_v1.h5')
  270.         modelo.save(caminho_modelo)
  271.         print(f"[Sucesso] Modelo salvo em: {caminho_modelo}")
  272.  
  273.         loss, acc = modelo.evaluate(X_test, Y_test, verbose=0)
  274.         salvar_resumo_texto(loss, acc)
  275.         salvar_graficos_historico(historico)
  276.         salvar_matriz_confusao(modelo, X_test, Y_test)
  277.         salvar_previsoes_visuais(modelo, X_test, Y_test)
  278.        
  279.         print(f"\n[FIM] Tudo pronto! Verifique a pasta '{PASTA_RELATORIO}'")
  280.     else:
  281.         print("\n[ERRO] A variável 'historico' não existe.")
  282.         print("Você esqueceu de implementar o 'modelo.fit' no TODO 3?")
Add Comment
Please, Sign In to add comment