qonitasal commited on
Commit
008b8be
·
verified ·
1 Parent(s): 9047d1b

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -0
app.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+
4
+ import gradio as gr
5
+ from PIL import Image, ImageDraw, ImageFont
6
+ from ultralytics import YOLO
7
+ import numpy as np
8
+ import os
9
+
10
+ # === Load model safely ===
11
+ try:
12
+ model_path = "best.pt"
13
+ if not os.path.exists(model_path):
14
+ raise FileNotFoundError(f"❌ File {model_path} not found. Upload best.pt to root directory.")
15
+ model = YOLO(model_path)
16
+ print("✅ Model loaded successfully!")
17
+ except Exception as e:
18
+ print("❌ Failed to load YOLO model:", e)
19
+ model = None
20
+
21
+ # Mapping label (4 classes)
22
+ label_map = {
23
+ 0: "coral",
24
+ 1: "pipeline",
25
+ 2: "ripple marks",
26
+ 3: "shipwreck"
27
+ }
28
+
29
+ # Warna RGB untuk setiap class
30
+ color_map = {
31
+ 0: (0, 255, 0), # hijau - coral
32
+ 1: (255, 0, 0), # merah - pipeline
33
+ 2: (255, 255, 0), # kuning - ripple marks
34
+ 3: (0, 0, 255) # biru - shipwreck
35
+ }
36
+
37
+ def predict_segmentation_with_legend(image):
38
+ if model is None:
39
+ return Image.new("RGB", image.size, color=(255, 255, 255))
40
+
41
+ image = image.convert("RGB")
42
+ results = model.predict(image, conf=0.25, iou=0.5)
43
+ result = results[0]
44
+
45
+ print("🔍 DETECTIONS:", result.boxes)
46
+ print("🎭 MASKS:", result.masks)
47
+
48
+ if result.masks is None:
49
+ print("⚠️ No masks detected.")
50
+ return image
51
+
52
+ image_np = np.array(image).copy()
53
+ draw = ImageDraw.Draw(image)
54
+
55
+ try:
56
+ font = ImageFont.truetype("arial.ttf", 24)
57
+ except:
58
+ font = ImageFont.load_default()
59
+
60
+ masks = result.masks.data.cpu().numpy()
61
+ boxes = result.boxes.xyxy.cpu().numpy()
62
+ scores = result.boxes.conf.cpu().numpy()
63
+ class_ids = result.boxes.cls.cpu().numpy().astype(int)
64
+
65
+ for i, mask in enumerate(masks):
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, 0))
69
+ score = scores[i]
70
+ box = boxes[i].astype(int)
71
+
72
+ # Blend mask ke image
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
+ # Gambar bounding box dan label
79
+ draw.rectangle(box.tolist(), outline=color, width=3)
80
+ draw.text((box[0], box[1] - 10), f"{label}: {score:.2f}", fill="white", font=font)
81
+
82
+ # Convert kembali ke PIL image
83
+ final_image = Image.fromarray(image_np.astype(np.uint8))
84
+
85
+ # Legend
86
+ legend_height = 50
87
+ legend = Image.new("RGB", (final_image.width, legend_height), (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 += 150
94
+
95
+ combined = Image.new("RGB", (final_image.width, final_image.height + legend_height))
96
+ combined.paste(final_image, (0, 0))
97
+ combined.paste(legend, (0, final_image.height))
98
+
99
+ return combined
100
+
101
+ # === Gradio Interface ===
102
+ iface = gr.Interface(
103
+ fn=predict_segmentation_with_legend,
104
+ inputs=gr.Image(type="pil"),
105
+ outputs=gr.Image(type="pil"),
106
+ title="YOLOv8 Segmentasi (4 Kelas: Coral, Pipeline, Ripple Marks, Shipwreck)",
107
+ description="Upload citra sonar. Hasil segmentasi akan ditampilkan dengan mask, bounding box, skor, dan legenda warna."
108
+ )
109
+
110
+ if __name__ == "__main__":
111
+ iface.launch()