marrtinagg commited on
Commit
a9c0198
1 Parent(s): 4f8e957

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -42
app.py CHANGED
@@ -65,9 +65,21 @@ def preprocess_and_predict(img_input):
65
  classes = ["Benign", "Malignant"]
66
  pred_idx = np.argmax(probs)
67
  pred_label = classes[pred_idx]
68
- result_text = f"Predicci贸n: {pred_label} ({probs[pred_idx]*100:.2f}%)"
69
-
70
- # === M茅tricas geom茅tricas en formato tabla ===
 
 
 
 
 
 
 
 
 
 
 
 
71
  area = calcular_area(mask)
72
  perim = calcular_perimetro(mask)
73
  circ = calcular_circularidad(mask)
@@ -92,7 +104,7 @@ def preprocess_and_predict(img_input):
92
  heatmap_color = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
93
  overlay = cv2.addWeighted(raw_resized.astype("uint8"), 0.6, heatmap_color, 0.4, 0)
94
 
95
- return mask, lesion_rgb, result_text, metrics_data, overlay
96
 
97
 
98
  # === Interfaz con estilo ===
@@ -100,70 +112,82 @@ with gr.Blocks(css="""
100
  body, .gradio-container {
101
  font-family: 'Inter', sans-serif;
102
  background: #ffffff !important;
 
103
  }
104
  h1, h2 { font-weight: 600; color: #111827; margin-bottom: 0.5rem; }
105
- .section { background: white; border-radius: 0.75rem; padding: 1.5rem; margin: 1rem auto;
106
- box-shadow: 0 1px 4px rgba(0,0,0,0.05); max-width: 800px; }
 
 
 
 
 
 
107
  .gradio-container { max-width: 900px; margin: auto; }
108
  img { border-radius: 0.5rem; }
109
- #analyze-btn {
110
  display: block;
111
- margin: 1rem auto;
112
- width: 150px;
113
- background-color: #374151;
114
- color: white;
115
  font-weight: bold;
116
  }
117
- #metrics-table {
118
- max-width: 320px;
119
- margin: 1rem auto;
120
- }
121
- .expl-text {
122
- color: #4B5563;
123
- font-size: 0.95rem;
124
- margin-bottom: 1rem;
125
- }
126
  """) as demo:
127
 
128
  # === T铆tulo e introducci贸n ===
129
  gr.HTML("""
130
  <section style="text-align:center; padding: 2rem;">
131
  <h1>DermaScan - Clasificaci贸n de Lesiones</h1>
132
- <p style="color:#374151; font-size:1.05rem; max-width: 700px; margin:auto;">
133
- El melanoma es uno de los c谩nceres de piel m谩s agresivos.
134
- Este sistema utiliza <b>Inteligencia Artificial</b> para apoyar el diagn贸stico,
135
- mostrando resultados de clasificaci贸n, zonas relevantes (Grad-CAM)
136
- y m茅tricas geom茅tricas basadas en el criterio ABCDE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  </p>
138
  </section>
139
  """)
140
 
 
 
141
  # === Subir imagen ===
142
  with gr.Column(elem_classes="section"):
143
  gr.HTML("<h2>Subir imagen</h2>")
144
- gr.HTML('<p class="expl-text">Sube una imagen dermatosc贸pica de la lesi贸n para analizarla.</p>')
145
  img_input = gr.Image(type="pil", label="Imagen de la lesi贸n", elem_id="upload-img")
146
- run_btn = gr.Button("Analizar", elem_id="analyze-btn")
147
 
148
  # === Segmentaci贸n ===
149
  with gr.Column(elem_classes="section"):
150
  gr.HTML("<h2>Preprocesamiento y Segmentaci贸n</h2>")
151
  gr.HTML("""
152
- <p class="expl-text">
153
- En este paso se realizan varias operaciones:
154
- <br>- Conversi贸n de canales de color.<br>
155
- - Eliminaci贸n de pelos.<br>
156
- - Segmentaci贸n de la lesi贸n.<br>
157
- </p>
158
  """)
159
  img_mask = gr.Image(type="numpy", label="M谩scara Binaria", elem_id="mask-img")
160
  img_segmented = gr.Image(type="numpy", label="Lesi贸n Segmentada", elem_id="seg-img")
161
 
162
  # === Grad-CAM ===
163
  with gr.Column(elem_classes="section"):
164
- gr.HTML("<h2>Grad-CAM (ZoomNet)</h2>")
165
  gr.HTML("""
166
- <p class="expl-text">
167
  El mapa de calor muestra las zonas con mayor relevancia para el modelo
168
  al determinar si la lesi贸n es benigna o maligna.
169
  </p>
@@ -173,27 +197,37 @@ img { border-radius: 0.5rem; }
173
  # === Resultados ===
174
  with gr.Column(elem_classes="section"):
175
  gr.HTML("<h2>Resultados del modelo</h2>")
176
- result_text = gr.Textbox(label="Clasificaci贸n", max_lines=1, interactive=False)
 
177
 
178
  gr.HTML("""
179
- <p class="expl-text">
180
- M茅tricas geom茅tricas basadas en el criterio <b>ABCDE</b>:
181
- 煤tiles para analizar lesiones en casos dudosos.
182
- </p>
183
  """)
184
  metrics_table = gr.Dataframe(
185
  headers=["M茅trica", "Valor"],
186
  datatype=["str", "number"],
187
  interactive=False,
188
  label="M茅tricas calculadas",
189
- elem_id="metrics-table"
 
 
190
  )
191
 
 
 
 
 
 
 
 
 
 
192
  # === Conexi贸n bot贸n -> funci贸n ===
193
  run_btn.click(
194
  fn=preprocess_and_predict,
195
  inputs=[img_input],
196
- outputs=[img_mask, img_segmented, result_text, metrics_table, gradcam_img]
197
  )
198
 
199
  # === Lanzar en tema claro ===
 
65
  classes = ["Benign", "Malignant"]
66
  pred_idx = np.argmax(probs)
67
  pred_label = classes[pred_idx]
68
+ prob_percent = int(probs[pred_idx] * 100)
69
+
70
+ # Color din谩mico para la barra
71
+ color = "green" if pred_label == "Benign" else "red"
72
+ result_text_html = f"<h3 style='color:{color}; font-weight:bold;'>Predicci贸n: {pred_label}</h3>"
73
+ result_bar_html = f"""
74
+ <div style='width:100%; background:#eee; border-radius:8px;'>
75
+ <div style='width:{prob_percent}%; background:{color}; padding:6px;
76
+ border-radius:8px; color:white; text-align:center; font-weight:bold;'>
77
+ {prob_percent}%
78
+ </div>
79
+ </div>
80
+ """
81
+
82
+ # === M茅tricas geom茅tricas ===
83
  area = calcular_area(mask)
84
  perim = calcular_perimetro(mask)
85
  circ = calcular_circularidad(mask)
 
104
  heatmap_color = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
105
  overlay = cv2.addWeighted(raw_resized.astype("uint8"), 0.6, heatmap_color, 0.4, 0)
106
 
107
+ return mask, lesion_rgb, result_text_html, result_bar_html, metrics_data, overlay
108
 
109
 
110
  # === Interfaz con estilo ===
 
112
  body, .gradio-container {
113
  font-family: 'Inter', sans-serif;
114
  background: #ffffff !important;
115
+ font-weight: bold !important;
116
  }
117
  h1, h2 { font-weight: 600; color: #111827; margin-bottom: 0.5rem; }
118
+ .section {
119
+ background: #f9fafb; /* gris muy claro */
120
+ border-radius: 0.75rem;
121
+ padding: 1.5rem;
122
+ margin: 1.5rem auto;
123
+ box-shadow: 0 1px 3px rgba(0,0,0,0.08);
124
+ max-width: 900px;
125
+ }
126
  .gradio-container { max-width: 900px; margin: auto; }
127
  img { border-radius: 0.5rem; }
128
+ button, .gr-button {
129
  display: block;
130
+ margin: 1rem auto;
131
+ border: 2px solid #374151;
 
 
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 Lesiones</h1>
140
+ <!-- Caption breve -->
141
+ <p style="color:#6b7280; font-size:1rem; font-style:italic; margin-top:0.5rem;">
142
+ Detecci贸n asistida por IA para apoyar el diagn贸stico temprano del melanoma
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) entrenada con im谩genes dermatosc贸picas
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 y m茅tricas geom茅tricas basadas en el criterio cl铆nico ABCDE,
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 dermatosc贸pica de la lesi贸n para analizarla.</p>")
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 paso se realizan varias operaciones:</p>
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 de la lesi贸n.</li>
181
+ </ul>
182
  """)
183
  img_mask = gr.Image(type="numpy", label="M谩scara Binaria", elem_id="mask-img")
184
  img_segmented = gr.Image(type="numpy", label="Lesi贸n Segmentada", elem_id="seg-img")
185
 
186
  # === Grad-CAM ===
187
  with gr.Column(elem_classes="section"):
188
+ gr.HTML("<h2>Grad-CAM</h2>")
189
  gr.HTML("""
190
+ <p style='color:#111827;'>
191
  El mapa de calor muestra las zonas con mayor relevancia para el modelo
192
  al determinar si la lesi贸n es benigna o maligna.
193
  </p>
 
197
  # === Resultados ===
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
+ <p style='color:#111827;'>M茅tricas geom茅tricas basadas en el criterio ABCDE:
205
+ 煤tiles para analizar lesiones en casos dudosos.</p>
 
 
206
  """)
207
  metrics_table = gr.Dataframe(
208
  headers=["M茅trica", "Valor"],
209
  datatype=["str", "number"],
210
  interactive=False,
211
  label="M茅tricas calculadas",
212
+ wrap=True,
213
+ row_count=(5, "fixed"),
214
+ col_count=(2, "fixed")
215
  )
216
 
217
+ # === Aviso final ===
218
+ gr.HTML("""
219
+ <section style="text-align:center; padding: 1rem; margin-top: 2rem;">
220
+ <p style="color:#b91c1c; font-weight:bold; font-size:1rem;">
221
+ Este sistema es solo de apoyo y nunca sustituye la valoraci贸n de un experto m茅dico.
222
+ </p>
223
+ </section>
224
+ """)
225
+
226
  # === Conexi贸n bot贸n -> funci贸n ===
227
  run_btn.click(
228
  fn=preprocess_and_predict,
229
  inputs=[img_input],
230
+ outputs=[img_mask, img_segmented, result_text, result_bar, metrics_table, gradcam_img]
231
  )
232
 
233
  # === Lanzar en tema claro ===