Commit
路
7370ee6
1
Parent(s):
85e0246
Actualizar app.py
Browse files
app.py
CHANGED
|
@@ -125,59 +125,71 @@ h1, h2 { font-weight: 600; color: #111827; margin-bottom: 0.5rem; }
|
|
| 125 |
}
|
| 126 |
.gradio-container { max-width: 900px; margin: auto; }
|
| 127 |
img { border-radius: 0.5rem; }
|
| 128 |
-
|
|
|
|
|
|
|
| 129 |
display: block;
|
| 130 |
-
margin:
|
| 131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
font-weight: bold;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
}
|
| 134 |
""") as demo:
|
| 135 |
|
| 136 |
# === T铆tulo e introducci贸n ===
|
| 137 |
gr.HTML("""
|
| 138 |
<section style="text-align:center; padding: 2rem;">
|
| 139 |
-
<h1>DermaScan - Clasificaci贸n de
|
| 140 |
<!-- Caption breve -->
|
| 141 |
<p style="color:#6b7280; font-size:1rem; font-style:italic; margin-top:0.5rem;">
|
| 142 |
-
|
| 143 |
</p>
|
| 144 |
</section>
|
| 145 |
|
| 146 |
<!-- Texto introductorio alineado a la izquierda -->
|
| 147 |
<section style="text-align:justify; padding: 1.5rem; max-width: 800px; margin:auto; line-height:1.6;">
|
| 148 |
<p style="color:#111827; font-size:1.05rem;">
|
| 149 |
-
El melanoma es un c谩ncer de piel agresivo que se origina en los melanocitos.
|
| 150 |
Aunque poco frecuente, es el m谩s peligroso por su capacidad de generar met谩stasis si no se detecta a tiempo.
|
| 151 |
</p>
|
| 152 |
<p style="color:#111827; font-size:1.05rem; margin-top:1rem;">
|
| 153 |
-
En esta aplicaci贸n hemos implementado una red neuronal convolucional (CNN)
|
| 154 |
para estimar la probabilidad de que una lesi贸n sea benigna o maligna.
|
| 155 |
</p>
|
| 156 |
<p style="color:#111827; font-size:1.05rem; margin-top:1rem;">
|
| 157 |
-
Adem谩s, incorporamos t茅cnicas de interpretabilidad como Grad-CAM
|
| 158 |
que sirven como apoyo en la exploraci贸n m茅dica.
|
| 159 |
</p>
|
| 160 |
</section>
|
| 161 |
""")
|
| 162 |
|
| 163 |
-
|
| 164 |
-
|
| 165 |
# === Subir imagen ===
|
| 166 |
with gr.Column(elem_classes="section"):
|
| 167 |
gr.HTML("<h2>Subir imagen</h2>")
|
| 168 |
-
gr.HTML("<p style='color:#111827;'>Sube una imagen
|
| 169 |
img_input = gr.Image(type="pil", label="Imagen de la lesi贸n", elem_id="upload-img")
|
| 170 |
-
run_btn = gr.Button("Analizar", scale=0)
|
| 171 |
|
| 172 |
# === Segmentaci贸n ===
|
| 173 |
with gr.Column(elem_classes="section"):
|
| 174 |
gr.HTML("<h2>Preprocesamiento y Segmentaci贸n</h2>")
|
| 175 |
gr.HTML("""
|
| 176 |
-
<p style='color:#111827;'>En este
|
| 177 |
<ul style='color:#111827;'>
|
| 178 |
-
<li style="color:#111827; font-weight:bold;">Conversi贸n de canales de color.</li>
|
| 179 |
-
<li style="color:#111827; font-weight:bold;">Eliminaci贸n de pelos.</li>
|
| 180 |
-
<li style="color:#111827; font-weight:bold;">Segmentaci贸n
|
| 181 |
</ul>
|
| 182 |
""")
|
| 183 |
img_mask = gr.Image(type="numpy", label="M谩scara Binaria", elem_id="mask-img")
|
|
@@ -188,21 +200,86 @@ button, .gr-button {
|
|
| 188 |
gr.HTML("<h2>Grad-CAM</h2>")
|
| 189 |
gr.HTML("""
|
| 190 |
<p style='color:#111827;'>
|
| 191 |
-
El
|
| 192 |
-
|
| 193 |
</p>
|
| 194 |
""")
|
| 195 |
gradcam_img = gr.Image(type="numpy", label="Mapa de activaci贸n", elem_id="gradcam-img")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
|
| 197 |
-
|
| 198 |
with gr.Column(elem_classes="section"):
|
| 199 |
gr.HTML("<h2>Resultados del modelo</h2>")
|
| 200 |
result_text = gr.HTML()
|
| 201 |
result_bar = gr.HTML()
|
| 202 |
|
|
|
|
| 203 |
gr.HTML("""
|
| 204 |
-
<
|
| 205 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 206 |
""")
|
| 207 |
metrics_table = gr.Dataframe(
|
| 208 |
headers=["M茅trica", "Valor"],
|
|
@@ -214,6 +291,7 @@ button, .gr-button {
|
|
| 214 |
col_count=(2, "fixed")
|
| 215 |
)
|
| 216 |
|
|
|
|
| 217 |
# === Aviso final ===
|
| 218 |
gr.HTML("""
|
| 219 |
<section style="text-align:center; padding: 1rem; margin-top: 2rem;">
|
|
|
|
| 125 |
}
|
| 126 |
.gradio-container { max-width: 900px; margin: auto; }
|
| 127 |
img { border-radius: 0.5rem; }
|
| 128 |
+
|
| 129 |
+
/* === Bot贸n Analizar personalizado === */
|
| 130 |
+
#analyze-btn {
|
| 131 |
display: block;
|
| 132 |
+
margin: 1.5rem auto;
|
| 133 |
+
width: 90%;
|
| 134 |
+
padding: 0.75rem 1rem;
|
| 135 |
+
background-color: #f97316;
|
| 136 |
+
color: #7c2d12;
|
| 137 |
+
border: 2px solid #f97316;
|
| 138 |
+
border-radius: 0.75rem;
|
| 139 |
font-weight: bold;
|
| 140 |
+
font-size: 1rem;
|
| 141 |
+
cursor: pointer;
|
| 142 |
+
transition: background 0.3s ease, color 0.3s ease;
|
| 143 |
+
}
|
| 144 |
+
#analyze-btn:hover {
|
| 145 |
+
background-color: #ea580c;
|
| 146 |
+
color: white;
|
| 147 |
}
|
| 148 |
""") as demo:
|
| 149 |
|
| 150 |
# === T铆tulo e introducci贸n ===
|
| 151 |
gr.HTML("""
|
| 152 |
<section style="text-align:center; padding: 2rem;">
|
| 153 |
+
<h1>DermaScan - Clasificaci贸n de Melanomas</h1>
|
| 154 |
<!-- Caption breve -->
|
| 155 |
<p style="color:#6b7280; font-size:1rem; font-style:italic; margin-top:0.5rem;">
|
| 156 |
+
Una herramienta de apoyo basada en IA para la detecci贸n temprana de c谩ncer de piel.
|
| 157 |
</p>
|
| 158 |
</section>
|
| 159 |
|
| 160 |
<!-- Texto introductorio alineado a la izquierda -->
|
| 161 |
<section style="text-align:justify; padding: 1.5rem; max-width: 800px; margin:auto; line-height:1.6;">
|
| 162 |
<p style="color:#111827; font-size:1.05rem;">
|
| 163 |
+
<span style='font-weight:bold; color:#000000;'>El melanoma es un c谩ncer de piel agresivo</span> que se origina en los melanocitos.
|
| 164 |
Aunque poco frecuente, es el m谩s peligroso por su capacidad de generar met谩stasis si no se detecta a tiempo.
|
| 165 |
</p>
|
| 166 |
<p style="color:#111827; font-size:1.05rem; margin-top:1rem;">
|
| 167 |
+
En esta aplicaci贸n hemos implementado una <span style='font-weight:bold; color:#000000;'>red neuronal convolucional (CNN)</span> entrenada con im谩genes dermatosc贸picas
|
| 168 |
para estimar la probabilidad de que una lesi贸n sea benigna o maligna.
|
| 169 |
</p>
|
| 170 |
<p style="color:#111827; font-size:1.05rem; margin-top:1rem;">
|
| 171 |
+
Adem谩s, incorporamos t茅cnicas de interpretabilidad como <span style='font-weight:bold; color:#000000;'>Grad-CAM </span> y <span style='font-weight:bold; color:#000000;'>m茅tricas geom茅tricas </span> basadas en el criterio cl铆nico ABCDE,
|
| 172 |
que sirven como apoyo en la exploraci贸n m茅dica.
|
| 173 |
</p>
|
| 174 |
</section>
|
| 175 |
""")
|
| 176 |
|
|
|
|
|
|
|
| 177 |
# === Subir imagen ===
|
| 178 |
with gr.Column(elem_classes="section"):
|
| 179 |
gr.HTML("<h2>Subir imagen</h2>")
|
| 180 |
+
gr.HTML("<p style='color:#111827;'>Sube una imagen clara de tu lunar Aseg煤rate de que est茅 bien iluminada y centrada.</p>")
|
| 181 |
img_input = gr.Image(type="pil", label="Imagen de la lesi贸n", elem_id="upload-img")
|
| 182 |
+
run_btn = gr.Button("Analizar", elem_id="analyze-btn", scale=0)
|
| 183 |
|
| 184 |
# === Segmentaci贸n ===
|
| 185 |
with gr.Column(elem_classes="section"):
|
| 186 |
gr.HTML("<h2>Preprocesamiento y Segmentaci贸n</h2>")
|
| 187 |
gr.HTML("""
|
| 188 |
+
<p style='color:#111827;'>En este apartado ver谩s c贸mo preparamos tu imagen para que la red neuronal se concentre en la lesi贸n:</p>
|
| 189 |
<ul style='color:#111827;'>
|
| 190 |
+
<li style="color:#111827; font-weight:bold;">Conversi贸n de canales de color a HSV.</li>
|
| 191 |
+
<li style="color:#111827; font-weight:bold;">Eliminaci贸n de pelos y bordes para reducir ruido.</li>
|
| 192 |
+
<li style="color:#111827; font-weight:bold;">Segmentaci贸n del lunar.</li>
|
| 193 |
</ul>
|
| 194 |
""")
|
| 195 |
img_mask = gr.Image(type="numpy", label="M谩scara Binaria", elem_id="mask-img")
|
|
|
|
| 200 |
gr.HTML("<h2>Grad-CAM</h2>")
|
| 201 |
gr.HTML("""
|
| 202 |
<p style='color:#111827;'>
|
| 203 |
+
El Grad-CAM resalta las zonas en las que la red neuronal ha puesto mayor atenci贸n para clasificar la lesi贸n.
|
| 204 |
+
Los colores c谩lidos indican mayor relevancia: rojo y amarillo muestran las 谩reas m谩s importantes.
|
| 205 |
</p>
|
| 206 |
""")
|
| 207 |
gradcam_img = gr.Image(type="numpy", label="Mapa de activaci贸n", elem_id="gradcam-img")
|
| 208 |
+
gr.HTML("""
|
| 209 |
+
<div style="display:flex; justify-content:center; margin-top:10px; gap:2rem;">
|
| 210 |
+
<div style="display:flex; align-items:center; gap:0.5rem;">
|
| 211 |
+
<div style="width:16px; height:16px; border-radius:50%; background:blue;"></div>
|
| 212 |
+
<span style="color:#111827;">Baja relevancia</span>
|
| 213 |
+
</div>
|
| 214 |
+
<div style="display:flex; align-items:center; gap:0.5rem;">
|
| 215 |
+
<div style="width:16px; height:16px; border-radius:50%; background:gold;"></div>
|
| 216 |
+
<span style="color:#111827;">Media relevancia</span>
|
| 217 |
+
</div>
|
| 218 |
+
<div style="display:flex; align-items:center; gap:0.5rem;">
|
| 219 |
+
<div style="width:16px; height:16px; border-radius:50%; background:red;"></div>
|
| 220 |
+
<span style="color:#111827;">Alta relevancia</span>
|
| 221 |
+
</div>
|
| 222 |
+
</div>
|
| 223 |
+
""")
|
| 224 |
|
| 225 |
+
# === Resultados ===
|
| 226 |
with gr.Column(elem_classes="section"):
|
| 227 |
gr.HTML("<h2>Resultados del modelo</h2>")
|
| 228 |
result_text = gr.HTML()
|
| 229 |
result_bar = gr.HTML()
|
| 230 |
|
| 231 |
+
# === Cuadro amarillo estilo ABCDE ===
|
| 232 |
gr.HTML("""
|
| 233 |
+
<div style="background-color:#FFFBEB; border-radius:10px; padding:1.5rem; margin:1rem 0;
|
| 234 |
+
border:1px solid #FDE68A;">
|
| 235 |
+
<h3 style="color:#111827; font-weight:600; margin-bottom:1rem;">Criterio ABCDE del melanoma</h3>
|
| 236 |
+
<div style="display:flex; justify-content:space-around; text-align:center; margin-bottom:1rem;">
|
| 237 |
+
<div>
|
| 238 |
+
<div style="background:#FDE68A; border-radius:50%; width:36px; height:36px;
|
| 239 |
+
display:flex; align-items:center; justify-content:center; font-weight:bold; color:#92400E; margin:auto;">
|
| 240 |
+
A
|
| 241 |
+
</div>
|
| 242 |
+
<p style="margin-top:0.5rem; font-size:0.9rem; color:#111827;">Asimetr铆a</p>
|
| 243 |
+
</div>
|
| 244 |
+
<div>
|
| 245 |
+
<div style="background:#FDE68A; border-radius:50%; width:36px; height:36px;
|
| 246 |
+
display:flex; align-items:center; justify-content:center; font-weight:bold; color:#92400E; margin:auto;">
|
| 247 |
+
B
|
| 248 |
+
</div>
|
| 249 |
+
<p style="margin-top:0.5rem; font-size:0.9rem; color:#111827;">Bordes irregulares</p>
|
| 250 |
+
</div>
|
| 251 |
+
<div>
|
| 252 |
+
<div style="background:#FDE68A; border-radius:50%; width:36px; height:36px;
|
| 253 |
+
display:flex; align-items:center; justify-content:center; font-weight:bold; color:#92400E; margin:auto;">
|
| 254 |
+
C
|
| 255 |
+
</div>
|
| 256 |
+
<p style="margin-top:0.5rem; font-size:0.9rem; color:#111827;">Color variado</p>
|
| 257 |
+
</div>
|
| 258 |
+
<div>
|
| 259 |
+
<div style="background:#FDE68A; border-radius:50%; width:36px; height:36px;
|
| 260 |
+
display:flex; align-items:center; justify-content:center; font-weight:bold; color:#92400E; margin:auto;">
|
| 261 |
+
D
|
| 262 |
+
</div>
|
| 263 |
+
<p style="margin-top:0.5rem; font-size:0.9rem; color:#111827;">Di谩metro > 6mm</p>
|
| 264 |
+
</div>
|
| 265 |
+
<div>
|
| 266 |
+
<div style="background:#FDE68A; border-radius:50%; width:36px; height:36px;
|
| 267 |
+
display:flex; align-items:center; justify-content:center; font-weight:bold; color:#92400E; margin:auto;">
|
| 268 |
+
E
|
| 269 |
+
</div>
|
| 270 |
+
<p style="margin-top:0.5rem; font-size:0.9rem; color:#111827;">Evoluci贸n</p>
|
| 271 |
+
</div>
|
| 272 |
+
</div>
|
| 273 |
+
<p style="color:#374151; font-size:0.9rem; text-align:center;">
|
| 274 |
+
Estas caracter铆sticas aumentan la probabilidad de melanoma.
|
| 275 |
+
Consulte a un dermat贸logo si observa alguna.
|
| 276 |
+
</p>
|
| 277 |
+
</div>
|
| 278 |
+
""")
|
| 279 |
+
|
| 280 |
+
# === Tabla de m茅tricas debajo ===
|
| 281 |
+
gr.HTML("""
|
| 282 |
+
<p style='color:#111827;'>M茅tricas lunar para consultar en casos</p>
|
| 283 |
""")
|
| 284 |
metrics_table = gr.Dataframe(
|
| 285 |
headers=["M茅trica", "Valor"],
|
|
|
|
| 291 |
col_count=(2, "fixed")
|
| 292 |
)
|
| 293 |
|
| 294 |
+
|
| 295 |
# === Aviso final ===
|
| 296 |
gr.HTML("""
|
| 297 |
<section style="text-align:center; padding: 1rem; margin-top: 2rem;">
|