File size: 5,226 Bytes
886e412
 
 
 
 
e48dd40
 
 
 
86d32c9
886e412
e48dd40
 
 
 
 
 
 
 
 
 
886e412
e48dd40
886e412
 
 
 
e48dd40
886e412
e48dd40
886e412
e48dd40
886e412
e48dd40
886e412
e48dd40
886e412
 
 
e48dd40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
886e412
 
e48dd40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ca79521
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e48dd40
 
ca79521
 
 
 
 
 
 
 
 
e48dd40
 
 
886e412
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import gradio as gr
import numpy as np
import cv2
from keras.models import load_model

import tensorflow as tf
from tensorflow import keras

# Cargar el modelo entrenado
model1 = load_model('./isatron_v3.h5')

# Función para encontrar la última capa convolucional
def find_last_conv_layer(model):
    for layer in reversed(model.layers):
        if 'conv' in layer.name:
            return layer.name
    raise ValueError("No se encontró una capa convolucional en el modelo.")

# Obtener el nombre de la última capa convolucional
last_conv_layer_name = find_last_conv_layer(model1)
print("Última capa convolucional:", last_conv_layer_name)

# Definir tamaño de imagen y etiquetas
img_size1 = 150
labels = ['PNEUMONIA', 'NORMAL']

def load_and_preprocess_image1(img):
    # Convertir imagen de Gradio (PIL Image) a array numpy
    img = np.array(img)
    # Convertir de RGB a escala de grises
    img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    # Redimensionar imagen al tamaño requerido
    img = cv2.resize(img, (img_size1, img_size1))
    # Reformatear imagen para entrada del modelo
    img = img.reshape(-1, img_size1, img_size1, 1)
    # Normalizar imagen
    img = img / 255.0
    return img

def make_gradcam_heatmap(img_array, model, last_conv_layer_name, pred_index=None):
    # Crear un modelo que mapee la imagen de entrada a las activaciones
    # de la última capa convolucional y las predicciones
    grad_model = keras.models.Model(
        [model.inputs], [model.get_layer(last_conv_layer_name).output, model.output]
    )

    # Calcular el gradiente de la clase predicha con respecto a las activaciones
    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

def overlay_heatmap(heatmap, img, alpha=0.4):
    # 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)
    # Convertir imagen a BGR
    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
    overlayed_img = cv2.cvtColor(overlayed_img, cv2.COLOR_BGR2RGB)
    return overlayed_img

def image_classifier1(img):
    # Mantener la imagen original para superponer
    orig_img = np.array(img)
    # Preprocesar la imagen
    img_array = load_and_preprocess_image1(img)
    # Realizar predicción usando model1
    preds = model1.predict(img_array)
    prediction = preds[0][0]  # Suponiendo que el modelo devuelve una probabilidad
    # Determinar el índice de la clase predicha
    pred_index = int(prediction > 0.5)
    # Generar mapa de calor
    heatmap = make_gradcam_heatmap(img_array, model1, last_conv_layer_name, pred_index=pred_index)
    # Superponer mapa de calor en la imagen original
    overlayed_img = overlay_heatmap(heatmap, orig_img)
    # Retornar la imagen superpuesta y los porcentajes de predicción
    prediction_percentage = {'PNEUMONIA': float(prediction), 'NORMAL': float(1 - prediction)}
    return overlayed_img, prediction_percentage

# Definir CSS personalizado
custom_css = """
body {
    background-color: #e6f2ff;
}

h1 {
    color: #003366;
    text-align: center;
}

.gradio-container {
    font-family: 'Arial', sans-serif;
    max-width: 800px;
    margin: auto;
    padding: 20px;
    background-color: #ffffff;
    border-radius: 10px;
}

.footer {
    text-align: center;
    margin-top: 20px;
    color: #003366;
    font-size: 14px;
}

label {
    font-weight: bold;
    color: #003366;
}

button {
    background-color: #0059b3;
    color: white;
    border: none;
    padding: 10px 20px;
    cursor: pointer;
}

button:hover {
    background-color: #004080;
}
"""

# Crear interfaz Gradio con CSS personalizado y pie de página
demo_model1 = gr.Interface(
    fn=image_classifier1,
    inputs=gr.Image(type="pil", label="Sube una imagen de radiografía"),
    outputs=[
        gr.Image(type="numpy", label="Imagen con Mapa de Calor"),
        gr.Label(num_top_classes=2, label="Resultados de Predicción")
    ],
    title="IsaTron V2 con Mapa de Calor",
    description="Esta aplicación detecta neumonía a partir de imágenes de radiografías de tórax.",
    article="<div class='footer'>Jeysshon 2024</div>",
    css=custom_css
)

# Ejecutar la interfaz
if __name__ == "__main__":
    demo_model1.launch(share=True)