qonitasal commited on
Commit
e9f695f
·
verified ·
1 Parent(s): 1f0f7e8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -38
app.py CHANGED
@@ -1,17 +1,17 @@
1
  import gradio as gr
2
- from PIL import Image, ImageFont, ImageDraw
3
  from ultralytics import YOLO
4
  import numpy as np
5
  import os
6
- import cv2
7
 
8
- # === Load model ===
9
  model_path = "best.pt"
10
  if not os.path.exists(model_path):
11
- raise FileNotFoundError("❌ File model best.pt tidak ditemukan.")
12
  model = YOLO(model_path)
 
13
 
14
- # Label dan warna
15
  label_map = {
16
  0: "coral",
17
  1: "pipeline",
@@ -25,65 +25,87 @@ color_map = {
25
  3: (0, 0, 255) # blue
26
  }
27
 
28
- def predict_segmentation(image_pil):
29
- image_pil = image_pil.convert("RGB")
30
- image_np = np.array(image_pil)
31
- results = model.predict(image_pil, conf=0.25, iou=0.5)
 
 
32
  result = results[0]
33
 
34
- # Jika tidak ada deteksi sama sekali
35
- if result.boxes is None or len(result.boxes) == 0 or result.masks is None:
36
- image_np = np.array(image_pil)
37
- overlay = image_np.copy()
38
- cv2.putText(overlay, "No detection found", (30, 50), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 255), 3)
39
- return Image.fromarray(overlay)
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
  masks = result.masks.data.cpu().numpy()
42
  boxes = result.boxes.xyxy.cpu().numpy()
43
  scores = result.boxes.conf.cpu().numpy()
44
  class_ids = result.boxes.cls.cpu().numpy().astype(int)
45
 
46
- overlay = image_np.copy()
47
-
48
  for i, mask in enumerate(masks):
49
  class_id = class_ids[i]
 
50
  color = color_map.get(class_id, (255, 255, 255))
51
  score = scores[i]
52
  box = boxes[i].astype(int)
53
- label = label_map.get(class_id, str(class_id))
54
 
55
- # Warnai area mask (semi-transparent)
 
 
 
 
 
56
  for c in range(3):
57
- overlay[:, :, c] = np.where(mask > 0, overlay[:, :, c] * 0.5 + color[c] * 0.5, overlay[:, :, c])
 
58
 
59
- # Gambar bounding box dan label
60
- cv2.rectangle(overlay, (box[0], box[1]), (box[2], box[3]), color, 2)
61
- text = f"{label} {score:.2f}"
62
- cv2.putText(overlay, text, (box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
63
 
64
- # Tambahkan legend
65
- legend_height = 60
66
- h, w, _ = overlay.shape
67
- combined = np.ones((h + legend_height, w, 3), dtype=np.uint8) * 255
68
- combined[:h] = overlay
69
 
70
- # Legend
 
 
71
  x = 10
72
  for cid, label in label_map.items():
73
- color = color_map[cid]
74
- cv2.rectangle(combined, (x, h + 10), (x + 20, h + 30), color, -1)
75
- cv2.putText(combined, label, (x + 30, h + 27), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 0), 1)
76
- x += 150
 
 
 
 
77
 
78
- return Image.fromarray(combined)
79
 
80
- # Gradio app
81
  iface = gr.Interface(
82
- fn=predict_segmentation,
83
  inputs=gr.Image(type="pil"),
84
  outputs=gr.Image(type="pil"),
85
  title="YOLOv8 Segmentasi Sonar",
86
- description="Upload citra Side Scan Sonar. Jika terdeteksi objek, akan ditampilkan mask, box, dan confidence. Jika tidak, akan muncul pesan."
87
  )
88
 
89
  if __name__ == "__main__":
 
1
  import gradio as gr
2
+ from PIL import Image, ImageDraw, ImageFont
3
  from ultralytics import YOLO
4
  import numpy as np
5
  import os
 
6
 
7
+ # ===== Load model safely =====
8
  model_path = "best.pt"
9
  if not os.path.exists(model_path):
10
+ raise FileNotFoundError(f"❌ File '{model_path}' not found. Upload best.pt to the root directory.")
11
  model = YOLO(model_path)
12
+ print("✅ Model loaded successfully!")
13
 
14
+ # ===== Label and Color Maps (sesuai urutan data.yaml) =====
15
  label_map = {
16
  0: "coral",
17
  1: "pipeline",
 
25
  3: (0, 0, 255) # blue
26
  }
27
 
28
+ def predict_segmentation_with_legend(image):
29
+ if model is None:
30
+ return Image.new("RGB", image.size, color=(255, 255, 255))
31
+
32
+ image = image.convert("RGB")
33
+ results = model.predict(image, conf=0.25, iou=0.5)
34
  result = results[0]
35
 
36
+ if result.masks is None or len(result.boxes) == 0:
37
+ # No detection
38
+ print("⚠️ No detection.")
39
+ image_np = np.array(image)
40
+ final_image = Image.fromarray(image_np)
41
+ draw = ImageDraw.Draw(final_image)
42
+ try:
43
+ font = ImageFont.truetype("arial.ttf", 24)
44
+ except:
45
+ font = ImageFont.load_default()
46
+ draw.text((10, 10), "No detection", fill="red", font=font)
47
+ return final_image
48
+
49
+ image_np = np.array(image).copy()
50
+ draw = ImageDraw.Draw(image)
51
+ try:
52
+ font = ImageFont.truetype("arial.ttf", 24)
53
+ except:
54
+ font = ImageFont.load_default()
55
 
56
  masks = result.masks.data.cpu().numpy()
57
  boxes = result.boxes.xyxy.cpu().numpy()
58
  scores = result.boxes.conf.cpu().numpy()
59
  class_ids = result.boxes.cls.cpu().numpy().astype(int)
60
 
 
 
61
  for i, mask in enumerate(masks):
62
  class_id = class_ids[i]
63
+ label = label_map.get(class_id, f"class_{class_id}")
64
  color = color_map.get(class_id, (255, 255, 255))
65
  score = scores[i]
66
  box = boxes[i].astype(int)
 
67
 
68
+ # Safety checks
69
+ if len(box) != 4 or mask.shape != image_np.shape[:2]:
70
+ continue
71
+
72
+ # Blend mask
73
+ color_mask = np.zeros_like(image_np)
74
  for c in range(3):
75
+ color_mask[:, :, c] = mask * color[c]
76
+ image_np = np.where(color_mask > 0, image_np * 0.5 + color_mask * 0.5, image_np)
77
 
78
+ # Draw box and label
79
+ draw = ImageDraw.Draw(Image.fromarray(image_np))
80
+ draw.rectangle(box.tolist(), outline=color, width=3)
81
+ draw.text((box[0], box[1] - 10), f"{label}: {score:.2f}", fill="white", font=font)
82
 
83
+ # Convert final image
84
+ final_image = Image.fromarray(image_np.astype(np.uint8))
 
 
 
85
 
86
+ # Create legend
87
+ legend = Image.new("RGB", (400, 50), (255, 255, 255))
88
+ draw_legend = ImageDraw.Draw(legend)
89
  x = 10
90
  for cid, label in label_map.items():
91
+ draw_legend.rectangle([x, 10, x+20, 30], fill=color_map[cid])
92
+ draw_legend.text((x + 25, 10), label, fill="black", font=font)
93
+ x += 120
94
+
95
+ # Combine image and legend
96
+ combined = Image.new("RGB", (final_image.width, final_image.height + 50))
97
+ combined.paste(final_image, (0, 0))
98
+ combined.paste(legend, (10, final_image.height))
99
 
100
+ return combined
101
 
102
+ # === Gradio Interface ===
103
  iface = gr.Interface(
104
+ fn=predict_segmentation_with_legend,
105
  inputs=gr.Image(type="pil"),
106
  outputs=gr.Image(type="pil"),
107
  title="YOLOv8 Segmentasi Sonar",
108
+ description="Upload citra Side Scan Sonar. Hasil segmentasi ditampilkan dengan mask warna, bounding box, confidence score, dan legenda."
109
  )
110
 
111
  if __name__ == "__main__":