jeysshon's picture
Update app.py
28becee verified
raw
history blame
8.25 kB
import gradio as gr
import numpy as np
import cv2
from tensorflow.keras.models import load_model
import tensorflow as tf
from tensorflow import keras
# Cargar el modelo entrenado
MODEL_PATH = 'modelo_isatron_jeysshonl.h5'
model = load_model(MODEL_PATH)
# Función para encontrar la última capa convolucional
def find_last_conv_layer(model):
"""Encuentra la última capa convolucional en el modelo"""
for layer in reversed(model.layers):
if 'conv' in layer.name.lower():
return layer.name
raise ValueError("No se encontró una capa convolucional en el modelo.")
# Obtener el nombre de la última capa convolucional
try:
last_conv_layer_name = find_last_conv_layer(model)
print(f"Última capa convolucional encontrada: {last_conv_layer_name}")
except ValueError as e:
print(f"Advertencia: {e}")
last_conv_layer_name = None
# Definir tamaño de imagen (tu modelo usa 224x224)
IMG_SIZE = 224
def load_and_preprocess_image(img):
"""Preprocesa la imagen para el modelo"""
# Convertir imagen de Gradio (PIL Image) a array numpy
img = np.array(img)
# Si la imagen es RGB, convertir a escala de grises si el modelo lo requiere
# Tu modelo parece usar RGB (224, 224, 3), así que mantenemos RGB
if len(img.shape) == 2: # Si es escala de grises
img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
# Redimensionar imagen al tamaño requerido
img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))
# Normalizar imagen
img = img / 255.0
# Expandir dimensiones para batch
img = np.expand_dims(img, axis=0)
return img
def make_gradcam_heatmap(img_array, model, last_conv_layer_name, pred_index=None):
"""Genera un mapa de calor Grad-CAM"""
if last_conv_layer_name is None:
return None
try:
# Crear un modelo que mapee la imagen de entrada a las activaciones
grad_model = keras.models.Model(
[model.inputs],
[model.get_layer(last_conv_layer_name).output, model.output]
)
# Calcular el gradiente de la clase predicha
with tf.GradientTape() as tape:
last_conv_layer_output, preds = grad_model(img_array)
if pred_index is None:
pred_index = np.argmax(preds[0])
class_channel = preds[:, pred_index]
# Calcular los gradientes
grads = tape.gradient(class_channel, last_conv_layer_output)
# Pooling global de los gradientes
pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))
# Multiplicar cada canal por su importancia
last_conv_layer_output = last_conv_layer_output[0]
heatmap = last_conv_layer_output @ pooled_grads[..., tf.newaxis]
heatmap = tf.squeeze(heatmap)
# Normalizar el mapa de calor entre 0 y 1
heatmap = tf.maximum(heatmap, 0) / tf.reduce_max(heatmap)
heatmap = heatmap.numpy()
return heatmap
except Exception as e:
print(f"Error generando Grad-CAM: {e}")
return None
def overlay_heatmap(heatmap, img, alpha=0.4):
"""Superpone el mapa de calor en la imagen original"""
# Redimensionar mapa de calor al tamaño de la imagen
heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))
# Convertir mapa de calor a RGB
heatmap = np.uint8(255 * heatmap)
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
# Asegurar que img esté en formato correcto
if len(img.shape) == 2: # Escala de grises
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
elif img.shape[2] == 3: # RGB
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
# Aplicar mapa de calor a la imagen original
overlayed_img = heatmap * alpha + img
overlayed_img = np.uint8(overlayed_img)
# Convertir de nuevo a RGB para Gradio
overlayed_img = cv2.cvtColor(overlayed_img, cv2.COLOR_BGR2RGB)
return overlayed_img
def image_classifier(img):
"""Función principal de clasificación con Grad-CAM"""
# Mantener la imagen original para superponer
orig_img = np.array(img)
# Preprocesar la imagen
img_array = load_and_preprocess_image(img)
# Realizar predicción
preds = model.predict(img_array, verbose=0)
# Tu modelo devuelve [Normal, Neumonía]
normal_prob = float(preds[0][0])
pneumonia_prob = float(preds[0][1])
# Determinar el índice de la clase predicha
pred_index = np.argmax(preds[0])
# Generar mapa de calor si es posible
if last_conv_layer_name:
heatmap = make_gradcam_heatmap(img_array, model, last_conv_layer_name, pred_index=pred_index)
if heatmap is not None:
overlayed_img = overlay_heatmap(heatmap, orig_img)
else:
overlayed_img = orig_img
else:
overlayed_img = orig_img
# Preparar resultado de predicción
prediction_result = {
'NORMAL': normal_prob,
'NEUMONÍA': pneumonia_prob
}
return overlayed_img, prediction_result
# Crear interfaz Gradio mejorada
demo = gr.Interface(
fn=image_classifier,
inputs=gr.Image(type="pil", label="Subir imagen de rayos X"),
outputs=[
gr.Image(type="numpy", label="Imagen con Mapa de Calor (Grad-CAM)"),
gr.Label(label="Predicción", num_top_classes=2)
],
title="<h1 style='text-align: center;'>IsaTron V2: Herramienta de Apoyo al Diagnóstico de Neumonía</h1>",
description="""
<div style='text-align: justify;'>
IsaTron es una herramienta de inteligencia artificial desarrollada con redes neuronales convolucionales (CNN)
para apoyar el diagnóstico de neumonía pediátrica a partir de imágenes de rayos X de tórax. La IA analiza las
imágenes y produce un mapa de calor Grad-CAM que resalta las áreas de mayor relevancia para la predicción del
modelo, lo cual ayuda a los profesionales de la salud a visualizar mejor las zonas potencialmente afectadas.
</div>
<br>
<div style='text-align: justify;'>
<strong>⚠️ Advertencia Importante:</strong> IsaTron está diseñado exclusivamente como una herramienta de apoyo
al diagnóstico y NO reemplaza una evaluación médica profesional. Es crucial que los resultados generados por
esta herramienta sean interpretados por personal de salud calificado. Esta herramienta no debe utilizarse para
tomar decisiones clínicas sin la supervisión de un médico especialista.
</div>
""",
examples=[
['1normal.jpeg'],
['image1_pneumonia_virus.jpeg'],
['image1_pneumonia_bacteria.jpeg'],
['image2_normal.jpeg'],
['image2_pneumonia_bacteria.jpeg'],
['image3_normal.jpeg'],
['image4_normal.jpeg']
],
article="""
<div style='text-align: justify;'>
<h3>Sobre IsaTron</h3>
<p>
Este proyecto utiliza tecnologías avanzadas de inteligencia artificial, incluyendo redes neuronales
convolucionales (CNN) y Grad-CAM (Gradient-weighted Class Activation Mapping), para mejorar la
interpretabilidad de los resultados. IsaTron ha sido entrenado con imágenes médicas de rayos X de tórax
y es capaz de predecir neumonía con un alto grado de confianza.
</p>
<p>
<strong>Grad-CAM</strong> permite visualizar qué regiones de la imagen son más importantes para la decisión
del modelo, proporcionando transparencia en el proceso de clasificación y ayudando a los profesionales
médicos a comprender mejor el razonamiento de la IA.
</p>
<p>
Los resultados obtenidos deben ser confirmados por un médico especialista para realizar un diagnóstico
clínico adecuado. Para más información sobre el proyecto, visite:
<a href="https://repositorio.unbosque.edu.co/handle/20.500.12495/9514" target="_blank">
Repositorio Institucional Universidad El Bosque
</a>
</p>
</div>
<br>
<div style='text-align: center;'>
<p><strong>IsaTron V2 - Desarrollado por Jeysshon Bustos</strong></p>
<p>Universidad El Bosque © 2022-2024</p>
</div>
""",
theme=gr.themes.Soft(),
allow_flagging="never"
)
# Ejecutar la interfaz
if __name__ == "__main__":
demo.launch(share=True)