Rosetta-Decoder / app.py
youkii-xr's picture
Update app.py
11743be verified
Raw
History Blame
5.64 kB
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 ---
MODEL_REPO = "youkii-xr/hieroglyphic-detection"
MODEL_FILENAME = "best.pt"
print(f"Server Status: Public MCP Endpoint Active")
print(f"Security: Model weights are protected (private repo)")
try:
model_path = hf_hub_download(
repo_id=MODEL_REPO,
filename=MODEL_FILENAME,
token=os.environ.get("HF_TOKEN")
)
print(f"System: Model loaded successfully from private storage.")
model = YOLO(model_path)
except Exception as e:
print(f"CRITICAL ERROR: Could not load model. Check HF_TOKEN in Settings. {e}")
model = None
# --- 2. DETECTION LOGIC ---
def detect_hieroglyphs(image: Image.Image, conf_threshold: float = 0.25):
if image is None:
return None, {"error": "No image provided"}
if model is None:
return None, {"error": "Server Error: Model not loaded."}
try:
results = model.predict(
source=image,
conf=conf_threshold,
iou=0.45,
imgsz=640,
verbose=False,
device='cpu',
max_det=300
)
annotated_array = results[0].plot()
annotated_image = Image.fromarray(annotated_array[..., ::-1])
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),
"box": [round(x, 1) for x in box.xyxy[0].cpu().numpy().tolist()]
})
summary = {
"status": "success",
"total_found": len(detections),
"unique_symbols": list(gardiner_counts.keys()),
"counts": gardiner_counts
}
return annotated_image, summary
except Exception as e:
print(f"Inference Error: {e}")
return None, {"error": str(e)}
# --- 3. UI/UX CONFIGURATION ---
custom_css = """
@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;700&display=swap');
/* Force background color via CSS since Theme is disabled */
body, .gradio-container {
background-color: #fdf6e3 !important;
}
h1, h2, h3, span {
font-family: 'Cinzel', serif !important;
color: #8b4513 !important;
}
/* The Magic Button Animation */
@keyframes goldenPulse {
0% { box-shadow: 0 0 0 0 rgba(212, 175, 55, 0.7); transform: scale(1); }
50% { box-shadow: 0 0 0 10px rgba(212, 175, 55, 0); transform: scale(1.02); }
100% { box-shadow: 0 0 0 0 rgba(212, 175, 55, 0); transform: scale(1); }
}
#magic-btn {
background: linear-gradient(135deg, #b8860b 0%, #d4af37 100%);
border: 1px solid #8b4513;
color: white !important;
font-family: 'Cinzel', serif;
font-weight: bold;
font-size: 1.2em;
animation: goldenPulse 2s infinite;
transition: all 0.3s ease;
}
#magic-btn:hover {
animation: none;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(139, 69, 19, 0.4);
}
.json-output {
background-color: #fff8dc;
border: 1px solid #d4af37;
}
"""
claude_config_content = """
{
"mcpServers": {
"hieroglyph-detector": {
"command": "uv",
"args": [
"python",
"client.py"
],
"env": {
"GRADIO_SERVER_URL": "YOUR_SPACE_URL_HERE"
}
}
}
}
"""
# --- 4. BUILD THE APP WITH BLOCKS ---
# FIX: Removed 'theme' argument to prevent TypeError on older Gradio versions
with gr.Blocks(css=custom_css, title="Horus Vision") as demo:
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("""
# ๐Ÿ‘๏ธ Horus Vision
### AI Hieroglyphic Decoder
""")
with gr.Column(scale=3):
gr.Markdown("""
> *"The eye sees all."* Upload an image of Egyptian text.
""")
with gr.Tabs():
with gr.TabItem("๐Ÿ” Decoder"):
with gr.Row():
with gr.Column():
img_input = gr.Image(type="pil", label="Upload Papyrus", sources=["upload", "clipboard"])
conf_slider = gr.Slider(minimum=0.1, maximum=1.0, value=0.25, label="Confidence")
analyze_btn = gr.Button("๐Ÿ”ฎ Decipher Symbols", elem_id="magic-btn", variant="primary")
with gr.Column():
img_output = gr.Image(label="Annotated Result", interactive=False)
json_output = gr.JSON(label="Glyph Data", elem_classes="json-output")
analyze_btn.click(
fn=detect_hieroglyphs,
inputs=[img_input, conf_slider],
outputs=[img_output, json_output]
)
with gr.TabItem("๐Ÿค– Connect to Claude"):
gr.Markdown("### MCP Server Configuration")
gr.Code(value=claude_config_content, language="json", label="claude_desktop_config.json", interactive=False)
# --- 5. LAUNCH ---
if __name__ == "__main__":
demo.launch(
mcp_server=True,
ssr_mode=False,
allowed_paths=["/tmp"]
)