Spaces:
Runtime error
Runtime error
File size: 3,752 Bytes
af7647d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | import gradio as gr
from ultralytics import YOLO
from PIL import Image
import os
from huggingface_hub import hf_hub_download
import numpy as np
# --- 1. SETUP & MODEL LOADING ---
# We download the model securely at startup
MODEL_REPO = "youkii-xr/hieroglyphic-detection" # <--- REPLACE THIS
MODEL_FILENAME = "best.pt"
print(f"Attempting to download {MODEL_FILENAME} from {MODEL_REPO}...")
try:
model_path = hf_hub_download(
repo_id=MODEL_REPO,
filename=MODEL_FILENAME,
token=os.environ.get("HF_TOKEN") # Needs 'HF_TOKEN' secret in Space settings
)
print(f"Model downloaded to: {model_path}")
model = YOLO(model_path)
except Exception as e:
print(f"CRITICAL ERROR loading model: {e}")
model = None
# --- 2. DETECTION LOGIC ---
# NOTE: Type hints (image: Image.Image) and Docstrings are MANDATORY for MCP
def detect_hieroglyphs(image: Image.Image, conf_threshold: float = 0.25):
"""
Detects Egyptian hieroglyph symbols in an image.
Args:
image: The image to analyze (uploaded file).
conf_threshold: Confidence threshold for detection (default 0.25).
Returns:
A tuple containing the annotated image with bounding boxes and a JSON summary of findings.
"""
if image is None:
return None, {"error": "No image provided"}
if model is None:
return None, {"error": "Model failed to load on server."}
try:
# Run Inference
results = model.predict(
source=image,
conf=conf_threshold,
iou=0.45,
imgsz=640,
verbose=False,
device='cpu', # Spaces usually run on CPU unless you pay for GPU
max_det=300
)
# 1. Generate Visual Output
# plot() returns BGR numpy array, convert to RGB PIL
annotated_array = results[0].plot()
annotated_image = Image.fromarray(annotated_array[..., ::-1])
# 2. Generate Data Output (JSON)
detections = []
gardiner_counts = {}
for box in results[0].boxes:
if box.cls.numel() > 0:
cls_id = int(box.cls[0])
if 0 <= cls_id < len(model.names):
code = model.names[cls_id]
conf = float(box.conf[0])
if code not in gardiner_counts: gardiner_counts[code] = 0
gardiner_counts[code] += 1
detections.append({
"code": code,
"confidence": round(conf, 2),
# Convert bbox to list for JSON serialization
"box": [round(x, 1) for x in box.xyxy[0].cpu().numpy().tolist()]
})
summary = {
"status": "success",
"total_detected": len(detections),
"unique_symbols": list(gardiner_counts.keys()),
"counts": gardiner_counts
}
return annotated_image, summary
except Exception as e:
print(f"Error during inference: {e}")
return None, {"error": str(e)}
# --- 3. INTERFACE & SERVER ---
# mcp_server=True creates the endpoint automatically
demo = gr.Interface(
fn=detect_hieroglyphs,
inputs=[
gr.Image(type="pil", label="Upload Image"),
gr.Number(value=0.25, label="Confidence Threshold")
],
outputs=[
gr.Image(label="Annotated Result"),
gr.JSON(label="Detection Data")
],
title="Egyptian Hieroglyph MCP Server",
description="MCP-compatible server for Hieroglyph Detection. Connect this to Claude Desktop."
)
if __name__ == "__main__":
demo.launch(mcp_server=True) |