YOLOv8m / app.py
qonitasal's picture
Update app.py
1f0179c verified
import gradio as gr
from PIL import Image, ImageDraw, ImageFont
from ultralytics import YOLO
import numpy as np
import os
# === Load Model ===
try:
model_path = "best.pt"
if not os.path.exists(model_path):
raise FileNotFoundError(f"❌ File {model_path} tidak ditemukan. Upload 'best.pt' ke root.")
model = YOLO(model_path)
print("βœ… Model loaded successfully!")
except Exception as e:
print("❌ Gagal load model:", e)
model = None
# === Peta Label dan Warna ===
label_map = {
0: "coral or rock",
1: "pipeline",
2: "ripple marks",
3: "shipwreck"
}
color_map = {
0: (0, 255, 0), # Hijau
1: (255, 0, 0), # Merah
2: (255, 165, 0), # Oranye
3: (0, 0, 255) # Biru
}
# === Fungsi Prediksi dan Visualisasi ===
def predict_segmentation_with_legend(image):
try:
if model is None:
print("❌ Model belum dimuat.")
return image
image = image.convert("RGB")
print("πŸ“₯ Gambar diterima:", image.size)
results = model.predict(image, conf=0.0, iou=0.5)
result = results[0]
masks = result.masks.data.cpu().numpy() if result.masks else []
boxes = result.boxes.xyxy.cpu().numpy() if result.boxes else []
scores = result.boxes.conf.cpu().numpy() if result.boxes else []
class_ids = result.boxes.cls.cpu().numpy().astype(int) if result.boxes else []
image_np = np.array(image).copy()
try:
font = ImageFont.truetype("DejaVuSans.ttf", 18)
except:
font = ImageFont.load_default()
CONFIDENCE_THRESHOLD = 0.5
if len(boxes) == 0:
draw = ImageDraw.Draw(image)
draw.text((10, 10), "No detections", fill="red", font=font)
return image
# Ambil index dengan skor tertinggi atau di atas threshold
indices_to_use = [i for i, s in enumerate(scores) if s >= CONFIDENCE_THRESHOLD]
if len(indices_to_use) == 0:
indices_to_use = [int(np.argmax(scores))]
# === MASKING ===
for i in indices_to_use:
mask = masks[i]
class_id = class_ids[i]
color = color_map.get(class_id, (255, 255, 0))
mask_pil = Image.fromarray((mask * 255).astype(np.uint8))
mask_resized = mask_pil.resize((image_np.shape[1], image_np.shape[0]), resample=Image.BILINEAR)
mask_resized = np.array(mask_resized) / 255.0
color_mask = np.zeros_like(image_np)
for c in range(3):
color_mask[:, :, c] = mask_resized * color[c]
image_np = np.where(mask_resized[..., None] > 0.5,
image_np * 0.5 + color_mask * 0.5, image_np)
final_image = Image.fromarray(image_np.astype(np.uint8)).convert("RGBA")
overlay = Image.new("RGBA", final_image.size, (255, 255, 255, 0))
draw_overlay = ImageDraw.Draw(overlay)
# === Gambar box dan label ===
for i in indices_to_use:
box = boxes[i].astype(int).tolist()
score = scores[i]
class_id = class_ids[i]
label = label_map.get(class_id, str(class_id))
color = color_map.get(class_id, (255, 255, 0))
text_color = "white"
draw_overlay.rectangle(box, outline=color + (255,), width=2)
# Teks dan background transparan
label_text = label
score_text = f"Conf: {score:.2f}"
label_size = draw_overlay.textbbox((0, 0), label_text, font=font)
score_size = draw_overlay.textbbox((0, 0), score_text, font=font)
text_x = max(box[0], 0)
text_y = max(box[1] - (label_size[3] + score_size[3] + 8), 0)
draw_overlay.rectangle(
[text_x - 2, text_y - 2,
text_x + max(label_size[2], score_size[2]) + 4,
text_y + label_size[3] + score_size[3] + 6],
fill=(0, 0, 0, 160)
)
draw_overlay.text((text_x, text_y), label_text, fill=text_color, font=font)
draw_overlay.text((text_x, text_y + label_size[3] + 2), score_text, fill=text_color, font=font)
final_image = Image.alpha_composite(final_image, overlay).convert("RGB")
# === Buat legenda ===
legend = Image.new("RGB", (500, 50), (255, 255, 255))
draw_legend = ImageDraw.Draw(legend)
x = 10
for cid, label in label_map.items():
draw_legend.rectangle([x, 10, x + 20, 30], fill=color_map[cid])
draw_legend.text((x + 25, 10), label, fill="black", font=font)
x += 130
# === Gabungkan gambar & legenda ===
combined = Image.new("RGB", (final_image.width, final_image.height + 50), (255, 255, 255))
combined.paste(final_image, (0, 0))
combined.paste(legend, (10, final_image.height))
return combined
except Exception as e:
print("❌ Error saat segmentasi:", e)
return image
iface = gr.Interface(
fn=predict_segmentation_with_legend,
inputs=gr.Image(type="pil", label="Upload Citra Side Scan Sonar"),
outputs=gr.Image(type="pil", label="Hasil Segmentasi"),
title="YOLOv8/YOLOv11 Segmentasi Citra Sonar",
description="Upload citra sonar dan dapatkan hasil segmentasi lengkap dengan bounding box, mask, label, confidence, dan legenda warna.",
allow_flagging="never"
)
if __name__ == "__main__":
iface.launch(share=True)