Ronny56 commited on
Commit
4470ab3
·
verified ·
1 Parent(s): 01b9d5b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +99 -59
app.py CHANGED
@@ -1,75 +1,110 @@
1
  import gradio as gr
2
- from ultralytics import YOLO
3
  import numpy as np
4
  import cv2
5
 
6
- # Carica il modello locale (già caricato nei Files)
7
- print("Caricamento modello...")
8
- model = YOLO('best.pt')
9
- print("Modello caricato con successo!")
10
 
11
- def detect_balloons(image, confidence):
 
 
 
 
 
12
  if image is None:
13
  return None, {"error": "Nessuna immagine"}
14
 
15
- print(f"Rilevamento con confidenza: {confidence}")
16
 
17
- # Detection - rileva SOLO balloon
18
- results = model(image, conf=confidence, verbose=False)
19
 
20
  output = {
21
  'num_balloons': 0,
22
  'detections': []
23
  }
24
 
25
- # Controlla se ci sono detection
26
- if results[0].boxes is not None and len(results[0].boxes) > 0:
27
- output['num_balloons'] = len(results[0].boxes)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- print(f"Trovati {len(results[0].boxes)} balloon")
 
 
 
 
 
 
 
 
 
30
 
31
- for i in range(len(results[0].boxes)):
32
- box = results[0].boxes.xyxy[i].cpu().numpy().tolist()
33
- conf = float(results[0].boxes.conf[i].cpu().numpy())
34
 
35
- detection_data = {
36
- 'box': {
37
- 'x1': int(box[0]),
38
- 'y1': int(box[1]),
39
- 'x2': int(box[2]),
40
- 'y2': int(box[3])
41
- },
42
- 'confidence': round(conf, 3)
43
- }
44
 
45
- # Aggiungi mask se disponibile (segmentation)
46
- if hasattr(results[0], 'masks') and results[0].masks is not None:
47
- try:
48
- mask = results[0].masks.data[i].cpu().numpy()
49
- h, w = image.shape[:2]
50
- mask_resized = cv2.resize(mask, (w, h))
51
- # Converti in lista di coordinate dei pixel bianchi (più leggero del full array)
52
- white_pixels = np.argwhere(mask_resized > 0.5).tolist()
53
- detection_data['mask_pixels'] = white_pixels[:1000] # Limita a 1000 pixel per performance
54
- detection_data['has_mask'] = True
55
- except:
56
- detection_data['has_mask'] = False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  else:
58
  detection_data['has_mask'] = False
59
-
60
- output['detections'].append(detection_data)
61
- else:
62
- print("Nessun balloon rilevato - prova ad abbassare la confidenza")
63
-
64
- # Disegna i risultati
65
- annotated = results[0].plot()
66
 
 
67
  return annotated, output
68
 
69
  # Interface Gradio
70
- with gr.Blocks(title="Balloon Detection") as demo:
71
- gr.Markdown("# 🎈 Rilevamento Balloon nei Fumetti")
72
- gr.Markdown("**Modello addestrato specificamente su balloon di fumetti** (manga, webtoon, western comics)")
73
 
74
  with gr.Row():
75
  with gr.Column():
@@ -77,28 +112,33 @@ with gr.Blocks(title="Balloon Detection") as demo:
77
  confidence = gr.Slider(
78
  minimum=0.1,
79
  maximum=1.0,
80
- value=0.25, # Più basso per rilevare più balloon
81
  step=0.05,
82
- label="🎯 Confidenza (più basso = più sensibile)"
83
  )
84
- detect_btn = gr.Button("🔍 Rileva Balloon", variant="primary", size="lg")
85
 
86
  with gr.Column():
87
- output_image = gr.Image(label="✅ Risultato")
88
- output_json = gr.JSON(label="📊 Dati API")
89
 
90
  gr.Markdown("""
91
- ### 💡 Suggerimenti:
92
- - Se **non rileva balloon**: abbassa la confidenza a 0.15-0.20
93
- - Se **rileva troppe cose**: alza la confidenza a 0.4-0.5
94
- - Il modello è addestrato su 8000 immagini di fumetti vari
 
 
 
 
 
95
  """)
96
 
97
- detect_btn.click(
98
- fn=detect_balloons,
99
  inputs=[input_image, confidence],
100
  outputs=[output_image, output_json]
101
  )
102
 
103
- print("App avviata!")
104
  demo.launch()
 
1
  import gradio as gr
2
+ from ultralytics import YOLO, SAM
3
  import numpy as np
4
  import cv2
5
 
6
+ # Carica modello detection per trovare balloon
7
+ detector = YOLO('best.pt')
 
 
8
 
9
+ # Carica SAM per segmentazione precisa
10
+ print("Caricamento SAM per segmentazione precisa...")
11
+ segmenter = SAM('sam_b.pt') # SAM base (più leggero)
12
+ print("Modelli caricati!")
13
+
14
+ def detect_and_segment_balloons(image, confidence):
15
  if image is None:
16
  return None, {"error": "Nessuna immagine"}
17
 
18
+ print(f"1. Rilevamento balloon con confidenza: {confidence}")
19
 
20
+ # Step 1: Rileva balloon con YOLO
21
+ detection_results = detector(image, conf=confidence, verbose=False)
22
 
23
  output = {
24
  'num_balloons': 0,
25
  'detections': []
26
  }
27
 
28
+ if detection_results[0].boxes is None or len(detection_results[0].boxes) == 0:
29
+ print("Nessun balloon rilevato")
30
+ return image, output
31
+
32
+ output['num_balloons'] = len(detection_results[0].boxes)
33
+ print(f"2. Trovati {output['num_balloons']} balloon")
34
+
35
+ # Prepara immagine per visualizzazione
36
+ annotated = image.copy()
37
+
38
+ # Step 2: Per ogni balloon, usa SAM per segmentazione precisa
39
+ for i in range(len(detection_results[0].boxes)):
40
+ box = detection_results[0].boxes.xyxy[i].cpu().numpy()
41
+ conf = float(detection_results[0].boxes.conf[i].cpu().numpy())
42
+
43
+ print(f"3. Segmentazione balloon {i+1}...")
44
+
45
+ # Usa SAM con il bounding box come prompt
46
+ seg_results = segmenter(image, bboxes=[box])
47
 
48
+ detection_data = {
49
+ 'balloon_id': i + 1,
50
+ 'box': {
51
+ 'x1': int(box[0]),
52
+ 'y1': int(box[1]),
53
+ 'x2': int(box[2]),
54
+ 'y2': int(box[3])
55
+ },
56
+ 'confidence': round(conf, 3)
57
+ }
58
 
59
+ # Estrai la mask precisa da SAM
60
+ if seg_results[0].masks is not None:
61
+ mask = seg_results[0].masks.data[0].cpu().numpy()
62
 
63
+ # Ridimensiona mask alle dimensioni originali
64
+ h, w = image.shape[:2]
65
+ mask_resized = cv2.resize(mask, (w, h))
 
 
 
 
 
 
66
 
67
+ # Converti in mask binaria
68
+ mask_binary = (mask_resized > 0.5).astype(np.uint8)
69
+
70
+ # Trova contorno del balloon (come bacchetta magica)
71
+ contours, _ = cv2.findContours(mask_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
72
+
73
+ if len(contours) > 0:
74
+ # Prendi il contorno più grande
75
+ largest_contour = max(contours, key=cv2.contourArea)
76
+
77
+ # Converti contorno in lista di punti (poligono)
78
+ polygon = largest_contour.reshape(-1, 2).tolist()
79
+ detection_data['polygon'] = polygon
80
+ detection_data['num_points'] = len(polygon)
81
+
82
+ # Mask come array 2D (0/255) - QUESTO È COME LA BACCHETTA MAGICA
83
+ mask_uint8 = (mask_binary * 255).astype(np.uint8)
84
+ detection_data['mask'] = mask_uint8.tolist()
85
+
86
+ # Disegna contorno sull'immagine
87
+ cv2.drawContours(annotated, [largest_contour], -1, (0, 255, 0), 2)
88
+
89
+ # Aggiungi numero balloon
90
+ x, y = int(box[0]), int(box[1]) - 10
91
+ cv2.putText(annotated, f"B{i+1}", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
92
+
93
+ detection_data['has_mask'] = True
94
  else:
95
  detection_data['has_mask'] = False
96
+ else:
97
+ detection_data['has_mask'] = False
98
+
99
+ output['detections'].append(detection_data)
 
 
 
100
 
101
+ print(f"4. Completato! {output['num_balloons']} balloon segmentati")
102
  return annotated, output
103
 
104
  # Interface Gradio
105
+ with gr.Blocks(title="Balloon Segmentation") as demo:
106
+ gr.Markdown("# 🎈 Segmentazione Precisa Balloon (come Bacchetta Magica)")
107
+ gr.Markdown("**Rileva balloon e crea mask precise pixel-per-pixel**")
108
 
109
  with gr.Row():
110
  with gr.Column():
 
112
  confidence = gr.Slider(
113
  minimum=0.1,
114
  maximum=1.0,
115
+ value=0.25,
116
  step=0.05,
117
+ label="🎯 Confidenza"
118
  )
119
+ segment_btn = gr.Button("✂️ Segmenta Balloon", variant="primary", size="lg")
120
 
121
  with gr.Column():
122
+ output_image = gr.Image(label="✅ Balloon Segmentati (contorni verdi)")
123
+ output_json = gr.JSON(label="📊 Dati con Mask Precise")
124
 
125
  gr.Markdown("""
126
+ ### 📖 Formato Output:
127
+ - **mask**: Array 2D (0/255) - usa come selezione (come bacchetta magica!)
128
+ - **polygon**: Lista punti [x, y] del contorno
129
+ - **box**: Rettangolo {x1, y1, x2, y2}
130
+
131
+ ### 🎯 Come Usare nella Tua App:
132
+ La **mask** è identica alla selezione della bacchetta magica:
133
+ - Pixel 255 = dentro il balloon (selezionato)
134
+ - Pixel 0 = fuori (non selezionato)
135
  """)
136
 
137
+ segment_btn.click(
138
+ fn=detect_and_segment_balloons,
139
  inputs=[input_image, confidence],
140
  outputs=[output_image, output_json]
141
  )
142
 
143
+ print("App di segmentazione avviata!")
144
  demo.launch()