Kesheratmex commited on
Commit
5d8f144
·
1 Parent(s): 1fe3c0d

**Add GPT image analysis and Markdown output for AI insights**

Browse files
Files changed (1) hide show
  1. app.py +112 -6
app.py CHANGED
@@ -240,6 +240,95 @@ def _extract_video(d):
240
  def _extract_path(d):
241
  return (d.get("path") if isinstance(d, dict) else d)
242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
 
244
 
245
  def _check_token(token: str):
@@ -899,6 +988,9 @@ with gr.Blocks(
899
  output_video = gr.Video(label="Vídeo anotado", visible=False)
900
  output_image = gr.Image(label="Imagen anotada", visible=False)
901
 
 
 
 
902
  # Hidden JSON components for API chaining
903
  json_video = gr.JSON(visible=False)
904
  json_image = gr.JSON(visible=False)
@@ -906,19 +998,33 @@ with gr.Blocks(
906
  # Functions to show/hide outputs based on active tab and update content
907
  def _update_video_output(json_result):
908
  if json_result and json_result.get("video"):
909
- return gr.Video(value=json_result["video"], visible=True), gr.Image(visible=False)
910
- return gr.Video(visible=False), gr.Image(visible=False)
911
 
912
  def _update_image_output(json_result):
913
  if json_result and json_result.get("path"):
914
- return gr.Video(visible=False), gr.Image(value=json_result["path"], visible=True)
915
- return gr.Video(visible=False), gr.Image(visible=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
916
 
917
  # Wire up the detection events with proper output visibility
918
  ev_video = btn_detect.click(fn=infer_media, inputs=video_input, outputs=json_video, api_name="infer_media")
919
- ev_video.then(_update_video_output, inputs=json_video, outputs=[output_video, output_image])
920
  ev_image = btn_detect.click(fn=infer_media, inputs=image_input, outputs=json_image, api_name="infer_media_1")
921
- ev_image.then(_update_image_output, inputs=json_image, outputs=[output_video, output_image])
922
 
923
  # Wire the gate
924
  btn_enter.click(fn=_check_token, inputs=[gate_token], outputs=[gate_group, app_group, gate_status])
 
240
  def _extract_path(d):
241
  return (d.get("path") if isinstance(d, dict) else d)
242
 
243
+ def analyze_image_with_gpt(image_path, detections_summary=""):
244
+ """
245
+ Analiza una imagen directamente con GPT para obtener observaciones adicionales
246
+ que el modelo YOLO podría haber perdido.
247
+ """
248
+ try:
249
+ GPTClass = _load_gptoss_wrapper()
250
+ if not GPTClass:
251
+ return "Análisis de IA no disponible (GPT wrapper no configurado)"
252
+
253
+ # Obtener características visuales básicas de la imagen
254
+ visual_features = compute_visual_features(image_path, [])
255
+
256
+ # Construir descripción visual básica
257
+ visual_desc = ""
258
+ if visual_features:
259
+ brightness = visual_features.get("brightness", 0)
260
+ contrast = visual_features.get("contrast", 0)
261
+ blur = visual_features.get("blur", 0)
262
+ dominant_rgb = visual_features.get("dominant_rgb", [])
263
+
264
+ bright_desc = "brillante" if brightness > 130 else ("tenue" if brightness < 80 else "moderadamente iluminada")
265
+ contrast_desc = "alto contraste" if contrast > 60 else ("bajo contraste" if contrast < 30 else "contraste moderado")
266
+ blur_desc = "borrosa" if blur < 100 else "nítida"
267
+
268
+ visual_desc = f"La imagen aparece {bright_desc}, con {contrast_desc}, y está {blur_desc}."
269
+ if dominant_rgb:
270
+ visual_desc += f" Color dominante aproximado: RGB{dominant_rgb}."
271
+
272
+ # Construir prompt en español para análisis visual directo
273
+ prompt = f"""Eres un experto en inspección de palas de aerogeneradores. Analiza esta imagen de una pala de aerogenerador y proporciona un análisis detallado en español.
274
+
275
+ INFORMACIÓN TÉCNICA DE LA IMAGEN:
276
+ {visual_desc}
277
+
278
+ DETECCIONES AUTOMÁTICAS DEL MODELO YOLO:
279
+ {detections_summary if detections_summary else "No se detectaron defectos automáticamente"}
280
+
281
+ INSTRUCCIONES PARA TU ANÁLISIS:
282
+ 1. Describe lo que observas en la superficie de la pala (color, textura, condiciones generales)
283
+ 2. Identifica cualquier anomalía, defecto o área de preocupación que puedas ver visualmente
284
+ 3. Menciona específicamente si observas algo que el modelo automático YOLO podría haber perdido
285
+ 4. Evalúa el estado general de la pala (excelente, bueno, regular, malo, crítico)
286
+ 5. Proporciona recomendaciones específicas de mantenimiento
287
+
288
+ ÁREAS ESPECÍFICAS A REVISAR:
289
+ - Borde de ataque (leading edge)
290
+ - Borde de salida (trailing edge)
291
+ - Superficie de la pala
292
+ - Uniones y conexiones
293
+ - Grietas, erosión, decoloración
294
+ - Daños por rayos, impactos de aves
295
+ - Acumulación de suciedad o hielo
296
+
297
+ IMPORTANTE:
298
+ - Responde SOLO en español
299
+ - Sé específico sobre ubicaciones y tipos de defectos
300
+ - Si no ves defectos obvios, menciona las características positivas
301
+ - Compara tus observaciones con las detecciones automáticas
302
+
303
+ Formato de respuesta:
304
+ ## 🔍 Análisis Visual Detallado
305
+
306
+ **Estado General:** [tu evaluación del estado]
307
+
308
+ **Observaciones Principales:**
309
+ [describe lo que ves en la superficie, colores, texturas]
310
+
311
+ **Defectos o Anomalías Detectadas:**
312
+ [cualquier problema que observes, incluso si YOLO no lo detectó]
313
+
314
+ **Comparación con Detección Automática:**
315
+ [comenta sobre las detecciones YOLO vs lo que tú observas]
316
+
317
+ **Recomendaciones:**
318
+ [acciones específicas recomendadas]
319
+ """
320
+
321
+ model_id = os.getenv("MODEL_ID", "gpt-oss-120")
322
+ wrapper = GPTClass(model=model_id)
323
+
324
+ # Generar análisis
325
+ analysis = wrapper.generate(prompt, max_tokens=1000, temperature=0.2)
326
+
327
+ return analysis
328
+
329
+ except Exception as e:
330
+ return f"Error en el análisis de IA: {str(e)}"
331
+
332
 
333
 
334
  def _check_token(token: str):
 
988
  output_video = gr.Video(label="Vídeo anotado", visible=False)
989
  output_image = gr.Image(label="Imagen anotada", visible=False)
990
 
991
+ # Analysis text below the image
992
+ analysis_text = gr.Markdown(label="Análisis de IA", visible=False)
993
+
994
  # Hidden JSON components for API chaining
995
  json_video = gr.JSON(visible=False)
996
  json_image = gr.JSON(visible=False)
 
998
  # Functions to show/hide outputs based on active tab and update content
999
  def _update_video_output(json_result):
1000
  if json_result and json_result.get("video"):
1001
+ return gr.Video(value=json_result["video"], visible=True), gr.Image(visible=False), gr.Markdown(visible=False)
1002
+ return gr.Video(visible=False), gr.Image(visible=False), gr.Markdown(visible=False)
1003
 
1004
  def _update_image_output(json_result):
1005
  if json_result and json_result.get("path"):
1006
+ # Generar resumen de detecciones para el análisis GPT
1007
+ classes = json_result.get("classes", {})
1008
+ if classes:
1009
+ detections_summary = "Detecciones automáticas: " + ", ".join([f"{k}: {v}" for k, v in classes.items()])
1010
+ else:
1011
+ detections_summary = "No se detectaron defectos automáticamente"
1012
+
1013
+ # Obtener análisis de GPT
1014
+ analysis = analyze_image_with_gpt(json_result["path"], detections_summary)
1015
+
1016
+ return (
1017
+ gr.Video(visible=False),
1018
+ gr.Image(value=json_result["path"], visible=True),
1019
+ gr.Markdown(value=analysis, visible=True)
1020
+ )
1021
+ return gr.Video(visible=False), gr.Image(visible=False), gr.Markdown(visible=False)
1022
 
1023
  # Wire up the detection events with proper output visibility
1024
  ev_video = btn_detect.click(fn=infer_media, inputs=video_input, outputs=json_video, api_name="infer_media")
1025
+ ev_video.then(_update_video_output, inputs=json_video, outputs=[output_video, output_image, analysis_text])
1026
  ev_image = btn_detect.click(fn=infer_media, inputs=image_input, outputs=json_image, api_name="infer_media_1")
1027
+ ev_image.then(_update_image_output, inputs=json_image, outputs=[output_video, output_image, analysis_text])
1028
 
1029
  # Wire the gate
1030
  btn_enter.click(fn=_check_token, inputs=[gate_token], outputs=[gate_group, app_group, gate_status])