SergioI1991 commited on
Commit
1b156ec
·
verified ·
1 Parent(s): 737d563

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -29
app.py CHANGED
@@ -41,21 +41,21 @@ def preprocess_image(img):
41
  def predecir(rx_image):
42
  """Realiza la predicción y formatea la salida HTML."""
43
  if model is None:
44
- return "<div style='color:#FF6B6B; text-align:center; padding-top:100px; font-weight: bold;'>Error: El modelo no se ha cargado.</div>"
45
 
46
  if rx_image is None:
47
- return "<div style='color:#FF6B6B; text-align:center; padding-top:100px; font-weight: bold;'>Por favor, sube una imagen RX para analizar.</div>"
48
 
49
  img_array = preprocess_image(rx_image)
50
  if img_array is None: # Si preprocess_image devuelve None por algún motivo
51
- return "<div style='color:#FF6B6B; text-align:center; padding-top:100px; font-weight: bold;'>Error: No se pudo procesar la imagen.</div>"
52
 
53
 
54
  try:
55
  preds = model.predict(img_array)
56
  except Exception as e:
57
  print(f"Error durante la predicción: {e}")
58
- return f"<div style='color:#FF6B6B; text-align:center; padding-top:100px; font-weight: bold;'>Error al realizar la predicción: {e}</div>"
59
 
60
  score = tf.nn.softmax(preds[0])
61
 
@@ -67,24 +67,23 @@ def predecir(rx_image):
67
  other_class = CLASS_NAMES[other_index]
68
  other_confidence = score[other_index] * 100
69
 
70
- # Colores para el borde y el texto del resultado
71
  color_borde = "#4CAF50" if predicted_class == "valido" else "#FF6B6B" # Verde para válido, Rojo para no válido
72
- color_texto_principal = "#2C3E50" # Azul oscuro para el texto principal
73
- color_texto_secundario = "#555555" # Gris oscuro para el texto secundario
74
 
75
  # HTML para el resultado con estilos mejorados
 
76
  resultado_texto = f"""
77
  <div class='result-box' style='
78
  border: 3px solid {color_borde};
79
  box-shadow: 0 6px 20px rgba(0,0,0,0.15); /* Sombra más pronunciada */
80
  '>
81
- <div style='color:{color_texto_principal}; font-size:42px; font-weight:bold;'>
82
  Resultado: <span style='color: {color_borde};'>{predicted_class.upper()}</span>
83
  </div>
84
- <div style='color:{color_texto_secundario}; font-size:30px; margin-top:15px;'>
85
  Confianza: <span style='font-weight:bold;'>{confidence:.2f}%</span>
86
  </div>
87
- <div style='color:{color_texto_secundario}; font-size:24px; margin-top:10px;'>
88
  (Probabilidad {other_class}: <span style='font-weight:bold;'>{other_confidence:.2f}%</span>)
89
  </div>
90
  </div>
@@ -94,33 +93,34 @@ def predecir(rx_image):
94
 
95
  # --- Interfaz de Gradio ---
96
  with gr.Blocks(theme=gr.themes.Soft(primary_hue=gr.themes.colors.emerald, secondary_hue=gr.themes.colors.slate)) as demo:
97
- # --- Estilos CSS personalizados ---
98
  gr.HTML(f"""
99
  <style>
100
  body {{
101
- background-color:#f8f9fa !important;
102
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
103
- color: #333;
104
  }}
105
  .gradio-container {{
106
  max-width: 1200px;
107
  margin: auto;
108
  padding: 20px;
109
- background-color: #ffffff;
110
  border-radius: 15px;
111
  box-shadow: 0 10px 30px rgba(0,0,0,0.1);
112
  }}
113
  h2 {{
114
- color: #2C3E50; /* Azul oscuro para el título */
115
- font-size: 2.8em; /* Tamaño más grande */
116
- font-weight: 700; /* Más negrita */
117
  text-align: center;
118
  margin-bottom: 30px;
119
  padding-bottom: 15px;
120
- border-bottom: 2px solid #ECF0F1;
121
  }}
 
 
122
  .gr-button.primary {{
123
- background-color: #28a745 !important; /* Verde principal */
124
  border-color: #28a745 !important;
125
  color: white !important;
126
  font-weight: bold;
@@ -136,7 +136,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue=gr.themes.colors.emerald, second
136
  box-shadow: 0 4px 10px rgba(0,0,0,0.2);
137
  }}
138
  .gr-button.secondary {{
139
- background-color: #6c757d !important; /* Gris secundario */
140
  border-color: #6c757d !important;
141
  color: white !important;
142
  font-weight: bold;
@@ -151,17 +151,18 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue=gr.themes.colors.emerald, second
151
  transform: translateY(-2px);
152
  box-shadow: 0 4px 10px rgba(0,0,0,0.2);
153
  }}
 
154
  .result-box {{
155
  font-size: 28px;
156
  text-align: center;
157
  padding: 50px;
158
  min-height: 380px;
159
  border-radius: 20px;
160
- background-color: #f0f4f7; /* Un fondo ligeramente azulado */
161
  display: flex;
162
  flex-direction: column;
163
  justify-content: center;
164
- color: #333;
165
  transition: all 0.3s ease;
166
  }}
167
  .result-box:hover {{
@@ -170,20 +171,26 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue=gr.themes.colors.emerald, second
170
  }}
171
  .gr-image {{
172
  border-radius: 12px;
173
- border: 1px solid #ddd;
174
  box-shadow: 0 2px 10px rgba(0,0,0,0.08);
175
  }}
176
  .gr-label {{
177
  font-weight: 600;
178
- color: #34495E;
179
  font-size: 1.2em;
180
  margin-bottom: 8px;
181
  }}
 
 
 
 
 
 
182
  </style>
183
  """)
184
 
185
  gr.Markdown("## Clasificador RX LAB 🦷 V1(529NV-348V) TFG Marta B.")
186
- gr.Markdown("<p style='text-align:center; font-size:1.1em; color:#555;'>Sube una imagen para clasificarla como válida o no válida.</p>")
187
 
188
  # Mensaje de carga del modelo
189
  gr.Textbox(value=model_load_message, interactive=False, container=False,
@@ -194,23 +201,27 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue=gr.themes.colors.emerald, second
194
  visible=True if "Cargando" in model_load_message or "Error" in model_load_message else False,
195
  )
196
 
 
 
 
197
  with gr.Row(variant="panel", scale=1):
198
  with gr.Column(scale=1, min_width=400):
199
  gr.Markdown("### Sube tu Radiografía")
200
  rx_input = gr.Image(type="numpy", label="Imagen de Radiografía Dental", show_label=True, height=450)
201
 
202
  with gr.Row():
203
- boton_limpiar = gr.Button("Limpiar", variant="secondary", size="lg", icon="🗑️")
204
- boton_analizar = gr.Button("Analizar RX", variant="primary", size="lg", icon="🔍")
205
 
206
  with gr.Column(scale=1, min_width=400):
207
  gr.Markdown("### Resultado del Análisis")
208
- resultado = gr.HTML(label="Análisis de Radiografía", show_label=True, value="<div class='result-box'><div style='color:#555; font-size:24px;'>Esperando imagen...</div></div>")
209
 
210
  # --- Conexiones de Eventos ---
211
  boton_analizar.click(fn=predecir, inputs=rx_input, outputs=resultado)
212
- boton_limpiar.click(lambda: (None, "<div class='result-box'><div style='color:#555; font-size:24px;'>Esperando imagen...</div></div>"), inputs=[], outputs=[rx_input, resultado])
213
 
214
  # --- Lanzar la App ---
215
  if __name__ == "__main__":
216
  demo.launch(share=False)
 
 
41
  def predecir(rx_image):
42
  """Realiza la predicción y formatea la salida HTML."""
43
  if model is None:
44
+ return "<div class='result-box' style='color:#FF6B6B; font-weight: bold;'>Error: El modelo no se ha cargado.</div>"
45
 
46
  if rx_image is None:
47
+ return "<div class='result-box' style='color:#FF6B6B; font-weight: bold;'>Por favor, sube una imagen RX para analizar.</div>"
48
 
49
  img_array = preprocess_image(rx_image)
50
  if img_array is None: # Si preprocess_image devuelve None por algún motivo
51
+ return "<div class='result-box' style='color:#FF6B6B; font-weight: bold;'>Error: No se pudo procesar la imagen.</div>"
52
 
53
 
54
  try:
55
  preds = model.predict(img_array)
56
  except Exception as e:
57
  print(f"Error durante la predicción: {e}")
58
+ return f"<div class='result-box' style='color:#FF6B6B; font-weight: bold;'>Error al realizar la predicción: {e}</div>"
59
 
60
  score = tf.nn.softmax(preds[0])
61
 
 
67
  other_class = CLASS_NAMES[other_index]
68
  other_confidence = score[other_index] * 100
69
 
70
+ # Colores para el borde. El color del texto se heredará del CSS.
71
  color_borde = "#4CAF50" if predicted_class == "valido" else "#FF6B6B" # Verde para válido, Rojo para no válido
 
 
72
 
73
  # HTML para el resultado con estilos mejorados
74
+ # Eliminamos los 'style' de color de texto para que se hereden de la clase 'result-box'
75
  resultado_texto = f"""
76
  <div class='result-box' style='
77
  border: 3px solid {color_borde};
78
  box-shadow: 0 6px 20px rgba(0,0,0,0.15); /* Sombra más pronunciada */
79
  '>
80
+ <div style='font-size:42px; font-weight:bold;'>
81
  Resultado: <span style='color: {color_borde};'>{predicted_class.upper()}</span>
82
  </div>
83
+ <div style='font-size:30px; margin-top:15px;'>
84
  Confianza: <span style='font-weight:bold;'>{confidence:.2f}%</span>
85
  </div>
86
+ <div style='font-size:24px; margin-top:10px;'>
87
  (Probabilidad {other_class}: <span style='font-weight:bold;'>{other_confidence:.2f}%</span>)
88
  </div>
89
  </div>
 
93
 
94
  # --- Interfaz de Gradio ---
95
  with gr.Blocks(theme=gr.themes.Soft(primary_hue=gr.themes.colors.emerald, secondary_hue=gr.themes.colors.slate)) as demo:
96
+ # --- Estilos CSS personalizados (Adaptados a Dark Mode) ---
97
  gr.HTML(f"""
98
  <style>
99
  body {{
100
+ /* Se elimina el background-color y color fijos */
101
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 
102
  }}
103
  .gradio-container {{
104
  max-width: 1200px;
105
  margin: auto;
106
  padding: 20px;
107
+ background-color: var(--background-fill-primary); /* Variable de Gradio para fondo */
108
  border-radius: 15px;
109
  box-shadow: 0 10px 30px rgba(0,0,0,0.1);
110
  }}
111
  h2 {{
112
+ color: var(--text-color-primary); /* Variable de Gradio para texto */
113
+ font-size: 2.8em;
114
+ font-weight: 700;
115
  text-align: center;
116
  margin-bottom: 30px;
117
  padding-bottom: 15px;
118
+ border-bottom: 2px solid var(--border-color-accent); /* Variable de Gradio para bordes */
119
  }}
120
+
121
+ /* Estilos de botones (se mantienen, ya que definen su propio color y fondo) */
122
  .gr-button.primary {{
123
+ background-color: #28a745 !important;
124
  border-color: #28a745 !important;
125
  color: white !important;
126
  font-weight: bold;
 
136
  box-shadow: 0 4px 10px rgba(0,0,0,0.2);
137
  }}
138
  .gr-button.secondary {{
139
+ background-color: #6c757d !important;
140
  border-color: #6c757d !important;
141
  color: white !important;
142
  font-weight: bold;
 
151
  transform: translateY(-2px);
152
  box-shadow: 0 4px 10px rgba(0,0,0,0.2);
153
  }}
154
+
155
  .result-box {{
156
  font-size: 28px;
157
  text-align: center;
158
  padding: 50px;
159
  min-height: 380px;
160
  border-radius: 20px;
161
+ background-color: var(--background-fill-secondary); /* Variable de Gradio */
162
  display: flex;
163
  flex-direction: column;
164
  justify-content: center;
165
+ color: var(--text-color-primary); /* Variable de Gradio */
166
  transition: all 0.3s ease;
167
  }}
168
  .result-box:hover {{
 
171
  }}
172
  .gr-image {{
173
  border-radius: 12px;
174
+ border: 1px solid var(--border-color-primary); /* Variable de Gradio */
175
  box-shadow: 0 2px 10px rgba(0,0,0,0.08);
176
  }}
177
  .gr-label {{
178
  font-weight: 600;
179
+ color: var(--text-color-secondary); /* Variable de Gradio */
180
  font-size: 1.2em;
181
  margin-bottom: 8px;
182
  }}
183
+ /* Clase para el subtítulo */
184
+ .subtitle {{
185
+ text-align:center;
186
+ font-size:1.1em;
187
+ color: var(--text-color-secondary); /* Variable de Gradio */
188
+ }}
189
  </style>
190
  """)
191
 
192
  gr.Markdown("## Clasificador RX LAB 🦷 V1(529NV-348V) TFG Marta B.")
193
+ gr.Markdown("<p class='subtitle'>Sube una imagen de una radiografía dental para clasificarla como válida o no válida.</p>")
194
 
195
  # Mensaje de carga del modelo
196
  gr.Textbox(value=model_load_message, interactive=False, container=False,
 
201
  visible=True if "Cargando" in model_load_message or "Error" in model_load_message else False,
202
  )
203
 
204
+ # Texto de estado inicial para la caja de resultados
205
+ initial_result_html = f"<div class='result-box'><div style='font-size:24px; color: var(--text-color-secondary);'>Esperando imagen...</div></div>"
206
+
207
  with gr.Row(variant="panel", scale=1):
208
  with gr.Column(scale=1, min_width=400):
209
  gr.Markdown("### Sube tu Radiografía")
210
  rx_input = gr.Image(type="numpy", label="Imagen de Radiografía Dental", show_label=True, height=450)
211
 
212
  with gr.Row():
213
+ boton_limpiar = gr.Button("Limpiar", variant="secondary", size="lg", )
214
+ boton_analizar = gr.Button("Analizar RX", variant="primary", size="lg",)
215
 
216
  with gr.Column(scale=1, min_width=400):
217
  gr.Markdown("### Resultado del Análisis")
218
+ resultado = gr.HTML(label="Análisis de Radiografía", show_label=True, value=initial_result_html)
219
 
220
  # --- Conexiones de Eventos ---
221
  boton_analizar.click(fn=predecir, inputs=rx_input, outputs=resultado)
222
+ boton_limpiar.click(lambda: (None, initial_result_html), inputs=[], outputs=[rx_input, resultado])
223
 
224
  # --- Lanzar la App ---
225
  if __name__ == "__main__":
226
  demo.launch(share=False)
227
+