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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -54
app.py CHANGED
@@ -4,14 +4,13 @@ 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,87 +24,77 @@ color_map = {
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__":
 
4
  import numpy as np
5
  import os
6
 
7
+ # === Load model ===
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 root directory.")
11
  model = YOLO(model_path)
 
12
 
13
+ # Label dan warna sesuai urutan
14
  label_map = {
15
  0: "coral",
16
  1: "pipeline",
 
24
  3: (0, 0, 255) # blue
25
  }
26
 
27
+ def predict_segmentation(image: Image.Image):
 
 
 
28
  image = image.convert("RGB")
29
  results = model.predict(image, conf=0.25, iou=0.5)
30
  result = results[0]
31
 
32
  if result.masks is None or len(result.boxes) == 0:
33
+ draw = ImageDraw.Draw(image)
34
+ font = ImageFont.load_default()
 
 
 
 
 
 
 
35
  draw.text((10, 10), "No detection", fill="red", font=font)
36
+ return image
37
 
38
+ # Convert to NumPy for blending mask
39
  image_np = np.array(image).copy()
 
 
 
 
 
40
 
41
  masks = result.masks.data.cpu().numpy()
42
+ boxes = result.boxes.xyxy.cpu().numpy().astype(int)
43
  scores = result.boxes.conf.cpu().numpy()
44
  class_ids = result.boxes.cls.cpu().numpy().astype(int)
45
 
46
+ # Draw masks
47
  for i, mask in enumerate(masks):
48
  class_id = class_ids[i]
 
49
  color = color_map.get(class_id, (255, 255, 255))
 
 
 
 
 
 
 
 
 
50
  for c in range(3):
51
+ image_np[:, :, c] = np.where(
52
+ mask > 0.5,
53
+ image_np[:, :, c] * 0.5 + color[c] * 0.5,
54
+ image_np[:, :, c]
55
+ )
56
+
57
+ # Convert back to PIL for drawing box/label
58
+ image_masked = Image.fromarray(image_np.astype(np.uint8))
59
+ draw = ImageDraw.Draw(image_masked)
60
+ try:
61
+ font = ImageFont.truetype("arial.ttf", 20)
62
+ except:
63
+ font = ImageFont.load_default()
64
 
65
+ for i, box in enumerate(boxes):
66
+ class_id = class_ids[i]
67
+ label = label_map.get(class_id, str(class_id))
68
+ color = color_map.get(class_id, (255, 255, 255))
69
+ score = scores[i]
70
  draw.rectangle(box.tolist(), outline=color, width=3)
71
+ text = f"{label}: {score:.2f}"
72
+ draw.text((box[0], box[1] - 10), text, fill="white", font=font)
 
 
73
 
74
+ # Add legend at bottom
75
+ legend_height = 50
76
+ legend = Image.new("RGB", (image_masked.width, legend_height), (255, 255, 255))
77
  draw_legend = ImageDraw.Draw(legend)
78
  x = 10
79
  for cid, label in label_map.items():
80
+ draw_legend.rectangle([x, 15, x + 20, 35], fill=color_map[cid])
81
+ draw_legend.text((x + 25, 15), label, fill="black", font=font)
82
+ x += 130
83
 
84
+ # Combine image + legend
85
+ combined = Image.new("RGB", (image_masked.width, image_masked.height + legend_height))
86
+ combined.paste(image_masked, (0, 0))
87
+ combined.paste(legend, (0, image_masked.height))
88
 
89
  return combined
90
 
91
+ # === Gradio interface ===
92
  iface = gr.Interface(
93
+ fn=predict_segmentation,
94
  inputs=gr.Image(type="pil"),
95
  outputs=gr.Image(type="pil"),
96
  title="YOLOv8 Segmentasi Sonar",
97
+ description="Upload citra sonar. Hasil segmentasi akan menampilkan mask, bounding box, label, dan confidence score."
98
  )
99
 
100
  if __name__ == "__main__":