youkii-xr commited on
Commit
822b928
·
verified ·
1 Parent(s): 4d3949e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +16 -24
app.py CHANGED
@@ -54,31 +54,24 @@ def create_labeled_zip(image, detections):
54
  zip_path = os.path.join(tempfile.gettempdir(), "rosetta_glyphs.zip")
55
 
56
  try:
57
- # Load a font (try-except block for system compatibility)
58
  try:
59
- # Try loading a standard font, fallback to default if fails
60
  font = ImageFont.truetype("arial.ttf", 16)
61
  except IOError:
62
  font = ImageFont.load_default()
63
 
64
  for i, d in enumerate(detections):
65
- # Crop
66
  box = d['box']
67
  crop = image.crop((box[0], box[1], box[2], box[3]))
68
 
69
- # Prepare Label
70
  label_text = f"{d['code']} {int(d['confidence']*100)}%"
71
  draw = ImageDraw.Draw(crop)
72
 
73
- # Calculate text size using textbbox (newer PIL versions)
74
  left, top, right, bottom = draw.textbbox((0, 0), label_text, font=font)
75
  text_w = right - left
76
  text_h = bottom - top
77
 
78
  img_w, img_h = crop.size
79
 
80
- # Draw background rectangle (bottom right)
81
- # Check if image is too small for label, if so, skip drawing to avoid crash
82
  if img_w > text_w and img_h > text_h:
83
  rect_x0 = img_w - text_w - 4
84
  rect_y0 = img_h - text_h - 4
@@ -88,11 +81,9 @@ def create_labeled_zip(image, detections):
88
  draw.rectangle([rect_x0, rect_y0, rect_x1, rect_y1], fill="black")
89
  draw.text((rect_x0 + 2, rect_y0), label_text, fill="white", font=font)
90
 
91
- # Save crop
92
  filename = f"{d['code']}_{i}.png"
93
  crop.save(os.path.join(zip_dir, filename))
94
 
95
- # Create Zip
96
  shutil.make_archive(zip_path.replace('.zip', ''), 'zip', zip_dir)
97
  return zip_path
98
 
@@ -122,7 +113,6 @@ def core_detect(image, conf_threshold):
122
  conf = float(box.conf[0])
123
  xyxy = box.xyxy[0].tolist()
124
 
125
- # Create detection object
126
  detection = {
127
  "code": code,
128
  "description": gardiner_map.get(code, "Unknown"),
@@ -130,8 +120,6 @@ def core_detect(image, conf_threshold):
130
  "box": xyxy
131
  }
132
  detections.append(detection)
133
-
134
- # Create crop (Clean crop for Gallery display)
135
  crop_img = image.crop((xyxy[0], xyxy[1], xyxy[2], xyxy[3]))
136
  crops.append((crop_img, f"{code}\n({int(conf*100)}%)"))
137
 
@@ -239,11 +227,9 @@ def process_pipeline(image, conf_threshold):
239
  annotated_img, detections, crops = core_detect(image, conf_threshold)
240
 
241
  # 2. Prepare Downloads
242
- # A. Annotated Image
243
  ann_path = os.path.join(tempfile.gettempdir(), "annotated_hieroglyphs.jpg")
244
  annotated_img.save(ann_path)
245
 
246
- # B. Zip File with Labels
247
  zip_path = create_labeled_zip(image, detections)
248
 
249
  # 3. Extract Keywords & Translate
@@ -265,16 +251,18 @@ def process_pipeline(image, conf_threshold):
265
  print(f"Pipeline Error: {e}")
266
  return None, None, None, f"System Failure: {str(e)}", "", None, str(e), None, []
267
 
268
- # --- 6. MCP API FUNCTIONS ---
269
 
270
- def detect_hieroglyphs_api(image: Image.Image, conf: float = 0.25) -> Tuple[str, Dict[str, Any]]:
 
271
  ann_img, dets, _ = core_detect(image, conf)
272
  with tempfile.NamedTemporaryFile(dir="/tmp/gradio_results", suffix=".jpg", delete=False) as t:
273
  ann_img.save(t.name)
274
  path = t.name
275
  return path, {"count": len(dets), "detections": dets}
276
 
277
- def translate_codes_api(keywords_text: str) -> Tuple[str, str]:
 
278
  if isinstance(keywords_text, str):
279
  keywords = [k.strip() for k in keywords_text.split(',')]
280
  else:
@@ -283,7 +271,8 @@ def translate_codes_api(keywords_text: str) -> Tuple[str, str]:
283
  clean_mystical = re.sub('<[^<]+?>', '', mystical)
284
  return clean_mystical, academic
285
 
286
- def get_analytics_chart_api(json_data: Dict[str, Any]) -> str:
 
287
  dets = json_data.get("detections", [])
288
  fig = core_analytics(dets, 640, 640)
289
  if fig is None: return "No data."
@@ -293,7 +282,8 @@ def get_analytics_chart_api(json_data: Dict[str, Any]) -> str:
293
  plt.close(fig)
294
  return path
295
 
296
- def list_all_codes_api() -> Dict[str, Any]:
 
297
  return gardiner_data
298
 
299
  # --- 7. HTML GENERATORS ---
@@ -406,9 +396,10 @@ guide_html = """
406
  </div>
407
  """
408
 
 
409
  claude_json_content = """{
410
  "mcpServers": {
411
- "gradio": {
412
  "command": "npx",
413
  "args": [
414
  "mcp-remote",
@@ -439,18 +430,19 @@ with gr.Blocks(title="Rosetta Decoder Ultimate") as demo:
439
  gr.HTML(trail_script)
440
 
441
  # --- MCP TOOL REGISTRATION LAYER (Hidden) ---
 
442
  with gr.Row(visible=False):
443
  btn_detect = gr.Button("Detect")
444
- btn_detect.click(fn=detect_hieroglyphs_api, inputs=[gr.Image(label="img"), gr.Number(label="conf")], outputs=[gr.Textbox(label="path"), gr.JSON(label="json")], api_name="detect")
445
 
446
  btn_trans = gr.Button("Translate")
447
- btn_trans.click(fn=translate_codes_api, inputs=[gr.Textbox(label="text")], outputs=[gr.Textbox(label="mystic"), gr.Textbox(label="academic")], api_name="translate")
448
 
449
  btn_anal = gr.Button("Analytics")
450
- btn_anal.click(fn=get_analytics_chart_api, inputs=[gr.JSON(label="data")], outputs=[gr.Textbox(label="chart_path")], api_name="analytics")
451
 
452
  btn_list = gr.Button("List")
453
- btn_list.click(fn=list_all_codes_api, inputs=[], outputs=[gr.JSON(label="data")], api_name="list_codes")
454
 
455
  # --- Visible UI ---
456
  with gr.Row(elem_classes="header-row"):
 
54
  zip_path = os.path.join(tempfile.gettempdir(), "rosetta_glyphs.zip")
55
 
56
  try:
 
57
  try:
 
58
  font = ImageFont.truetype("arial.ttf", 16)
59
  except IOError:
60
  font = ImageFont.load_default()
61
 
62
  for i, d in enumerate(detections):
 
63
  box = d['box']
64
  crop = image.crop((box[0], box[1], box[2], box[3]))
65
 
 
66
  label_text = f"{d['code']} {int(d['confidence']*100)}%"
67
  draw = ImageDraw.Draw(crop)
68
 
 
69
  left, top, right, bottom = draw.textbbox((0, 0), label_text, font=font)
70
  text_w = right - left
71
  text_h = bottom - top
72
 
73
  img_w, img_h = crop.size
74
 
 
 
75
  if img_w > text_w and img_h > text_h:
76
  rect_x0 = img_w - text_w - 4
77
  rect_y0 = img_h - text_h - 4
 
81
  draw.rectangle([rect_x0, rect_y0, rect_x1, rect_y1], fill="black")
82
  draw.text((rect_x0 + 2, rect_y0), label_text, fill="white", font=font)
83
 
 
84
  filename = f"{d['code']}_{i}.png"
85
  crop.save(os.path.join(zip_dir, filename))
86
 
 
87
  shutil.make_archive(zip_path.replace('.zip', ''), 'zip', zip_dir)
88
  return zip_path
89
 
 
113
  conf = float(box.conf[0])
114
  xyxy = box.xyxy[0].tolist()
115
 
 
116
  detection = {
117
  "code": code,
118
  "description": gardiner_map.get(code, "Unknown"),
 
120
  "box": xyxy
121
  }
122
  detections.append(detection)
 
 
123
  crop_img = image.crop((xyxy[0], xyxy[1], xyxy[2], xyxy[3]))
124
  crops.append((crop_img, f"{code}\n({int(conf*100)}%)"))
125
 
 
227
  annotated_img, detections, crops = core_detect(image, conf_threshold)
228
 
229
  # 2. Prepare Downloads
 
230
  ann_path = os.path.join(tempfile.gettempdir(), "annotated_hieroglyphs.jpg")
231
  annotated_img.save(ann_path)
232
 
 
233
  zip_path = create_labeled_zip(image, detections)
234
 
235
  # 3. Extract Keywords & Translate
 
251
  print(f"Pipeline Error: {e}")
252
  return None, None, None, f"System Failure: {str(e)}", "", None, str(e), None, []
253
 
254
+ # --- 6. MCP API FUNCTIONS (RENAMED FOR CLAUDE) ---
255
 
256
+ def detect_glyphs(image: Image.Image, conf: float = 0.25) -> Tuple[str, Dict[str, Any]]:
257
+ """Detects hieroglyphs in an image. Returns path to annotated image and JSON data."""
258
  ann_img, dets, _ = core_detect(image, conf)
259
  with tempfile.NamedTemporaryFile(dir="/tmp/gradio_results", suffix=".jpg", delete=False) as t:
260
  ann_img.save(t.name)
261
  path = t.name
262
  return path, {"count": len(dets), "detections": dets}
263
 
264
+ def translate_story(keywords_text: str) -> Tuple[str, str]:
265
+ """Translates a list of codes or keywords into a mystical story and academic text."""
266
  if isinstance(keywords_text, str):
267
  keywords = [k.strip() for k in keywords_text.split(',')]
268
  else:
 
271
  clean_mystical = re.sub('<[^<]+?>', '', mystical)
272
  return clean_mystical, academic
273
 
274
+ def get_stats(json_data: Dict[str, Any]) -> str:
275
+ """Generates analytics charts from detection JSON. Returns path to chart image."""
276
  dets = json_data.get("detections", [])
277
  fig = core_analytics(dets, 640, 640)
278
  if fig is None: return "No data."
 
282
  plt.close(fig)
283
  return path
284
 
285
+ def list_codes() -> Dict[str, Any]:
286
+ """Returns the full dictionary of supported Gardiner codes and descriptions."""
287
  return gardiner_data
288
 
289
  # --- 7. HTML GENERATORS ---
 
396
  </div>
397
  """
398
 
399
+ # CHANGED: "gradio" key changed to "Rosetta Decoder"
400
  claude_json_content = """{
401
  "mcpServers": {
402
+ "Rosetta Decoder": {
403
  "command": "npx",
404
  "args": [
405
  "mcp-remote",
 
430
  gr.HTML(trail_script)
431
 
432
  # --- MCP TOOL REGISTRATION LAYER (Hidden) ---
433
+ # CHANGED: Renamed API names to be short verbs (detect, translate, etc.)
434
  with gr.Row(visible=False):
435
  btn_detect = gr.Button("Detect")
436
+ btn_detect.click(fn=detect_glyphs, inputs=[gr.Image(label="img"), gr.Number(label="conf")], outputs=[gr.Textbox(label="path"), gr.JSON(label="json")], api_name="detect")
437
 
438
  btn_trans = gr.Button("Translate")
439
+ btn_trans.click(fn=translate_story, inputs=[gr.Textbox(label="text")], outputs=[gr.Textbox(label="mystic"), gr.Textbox(label="academic")], api_name="translate")
440
 
441
  btn_anal = gr.Button("Analytics")
442
+ btn_anal.click(fn=get_stats, inputs=[gr.JSON(label="data")], outputs=[gr.Textbox(label="chart_path")], api_name="analyze")
443
 
444
  btn_list = gr.Button("List")
445
+ btn_list.click(fn=list_codes, inputs=[], outputs=[gr.JSON(label="data")], api_name="list_codes")
446
 
447
  # --- Visible UI ---
448
  with gr.Row(elem_classes="header-row"):