youkii-xr commited on
Commit
d17f949
Β·
verified Β·
1 Parent(s): 74b222d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -60
app.py CHANGED
@@ -36,10 +36,8 @@ def generate_human_report(detections, counts):
36
  report += f"===================================\n"
37
  report += f"Glyph Density: {total} Symbols Identified\n\n"
38
  report += "πŸ”£ GARDINER CODE INVENTORY:\n"
39
-
40
  for code, count in sorted_counts:
41
  report += f"β€’ Code [{code}]: {count} instance(s)\n"
42
-
43
  report += f"\n===================================\n"
44
  report += f"CONFIDENCE: High\n"
45
  report += f"STATUS: Digitized & Ready for Translation."
@@ -57,7 +55,7 @@ def detect_hieroglyphs(image: Image.Image, conf_threshold: float = 0.25):
57
  annotated_array = results[0].plot()
58
  annotated_image = Image.fromarray(annotated_array[..., ::-1])
59
 
60
- # Save for Download Button
61
  temp_dir = tempfile.gettempdir()
62
  save_path = os.path.join(temp_dir, "rosetta_decoded_result.jpg")
63
  annotated_image.save(save_path)
@@ -87,52 +85,65 @@ def detect_hieroglyphs(image: Image.Image, conf_threshold: float = 0.25):
87
  except Exception as e:
88
  return None, {"error": str(e)}, f"System Failure: {str(e)}", None
89
 
90
- # --- 3. UI STYLING (THE BLUE LAPIS THEME) ---
91
 
92
- cursor_url = "url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDMyIDMyIj4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiNkNGFmMzciIHN0cm9rZS13aWR0aD0iMS41Ij4KICAgIDxjaXJjbGUgY3g9IjE2IiBjeT0iMTYiIHI9IjgiIGZpbGw9InJnYmEoMjEyLCAxNzUsIDU1LCAwLjEpIi8+CiAgICA8cGF0aCBkPSZNMTYsNCBMMTYsOCIvPgogICAgPHBhdGggZD0iTTE2LDI0IEwxNiwyOCIvPgogICAgPHBhdGggZD0iTTQsMTYgTDgsMTYiLz4KICAgIDxwYXRoIGQ9Ik0yNCwxNiBMMjgsMTYiLz4KICAgIDxjaXJjbGUgY3g9IjE2IiBjeT0iMTYiIHI9IjIiIGZpbGw9IiNkNGFmMzciLz4KICA8L2c+Cjwvc3ZnPg==')"
 
93
 
94
  custom_css = f"""
95
- /* Import 'Cairo' font: Modern, readable, fits the region */
96
  @import url('https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;600;700&display=swap');
97
  @import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&display=swap');
98
 
 
99
  :root {{
100
- /* --- LAPIS LAZULI NIGHT THEME --- */
101
- --bg-gradient: radial-gradient(circle at 50% 0%, #0a0a2e 0%, #000000 100%); /* Deep Blue to Black */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  --card-bg: rgba(15, 15, 35, 0.7);
103
- --text-primary: #e0e7ff; /* Soft Blue-White for comfortable reading */
104
- --text-accent: #d4af37; /* Gold */
105
  --border-color: #d4af37;
106
  --btn-grad: linear-gradient(135deg, #b8860b 0%, #d4af37 100%);
107
  --btn-text: #000;
108
- --glow-color: rgba(212, 175, 55, 0.4);
109
-
110
- /* Guide Box Colors */
111
  --info-bg: rgba(212, 175, 55, 0.08);
112
  --info-border: #d4af37;
 
113
  }}
114
 
115
- /* --- GLOBAL SETTINGS --- */
116
  body, .gradio-container {{
117
  background: var(--bg-gradient) !important;
118
- font-family: 'Cairo', sans-serif !important; /* Replaced Cinzel with Cairo */
119
  color: var(--text-primary) !important;
120
- cursor: {cursor_url} 16 16, auto !important;
121
- -webkit-font-smoothing: antialiased; /* Fixes pixelation */
122
- -moz-osx-font-smoothing: grayscale;
123
  }}
124
 
125
- button, a, .cursor-pointer {{
126
- cursor: {cursor_url} 16 16, pointer !important;
 
127
  }}
128
 
129
  /* --- CARDS --- */
130
  .card {{
131
  background: var(--card-bg) !important;
132
- border: 1px solid rgba(212, 175, 55, 0.2) !important;
133
  border-radius: 12px;
134
  padding: 24px;
135
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
136
  backdrop-filter: blur(12px);
137
  margin-bottom: 24px;
138
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
@@ -141,7 +152,7 @@ button, a, .cursor-pointer {{
141
  .card:hover {{
142
  transform: translateY(-4px);
143
  border-color: var(--border-color) !important;
144
- box-shadow: 0 10px 40px rgba(0,0,0,0.5), 0 0 20px var(--glow-color);
145
  }}
146
 
147
  /* --- BUTTONS --- */
@@ -161,15 +172,27 @@ button.primary-btn:hover {{
161
  box-shadow: 0 0 25px var(--glow-color);
162
  }}
163
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  /* --- TYPOGRAPHY --- */
165
  .card-title {{
166
  font-family: 'Cairo', sans-serif;
167
- font-size: 18px; /* Larger for better reading */
168
  font-weight: 700;
169
  color: var(--text-accent);
170
  text-transform: uppercase;
171
  letter-spacing: 2px;
172
- border-bottom: 1px solid rgba(212, 175, 55, 0.2);
173
  padding-bottom: 12px;
174
  margin-bottom: 18px;
175
  display: flex;
@@ -177,19 +200,17 @@ button.primary-btn:hover {{
177
  gap: 8px;
178
  }}
179
 
180
- /* --- GOLDEN GUIDE BOXES --- */
181
  .guide-step {{
182
  background-color: var(--info-bg);
183
  border-left: 4px solid var(--info-border);
184
  padding: 16px;
185
  margin: 12px 0;
186
  border-radius: 0 8px 8px 0;
187
- font-family: 'Space Mono', monospace; /* Keep mono for technical instructions */
188
  font-size: 13px;
189
  line-height: 1.6;
190
- color: #e0e7ff;
191
  }}
192
-
193
  .step-number {{
194
  color: var(--text-accent);
195
  font-weight: bold;
@@ -197,34 +218,31 @@ button.primary-btn:hover {{
197
  display: block;
198
  margin-bottom: 6px;
199
  font-size: 12px;
200
- letter-spacing: 1px;
201
  }}
202
-
203
  .path-highlight {{
204
- background: rgba(212, 175, 55, 0.15);
205
  padding: 3px 8px;
206
  border-radius: 4px;
207
  color: var(--text-accent);
208
  font-weight: bold;
209
- border: 1px solid rgba(212, 175, 55, 0.3);
210
  }}
211
 
212
- /* UI CLEANUP */
213
  .gradio-image, .gradio-json {{ background: transparent !important; border: none !important; }}
214
  .report-box textarea {{
215
- background-color: rgba(10, 10, 20, 0.5) !important;
216
  border: 1px solid var(--border-color) !important;
217
  font-family: 'Space Mono', monospace !important;
218
- color: #a5b4fc !important; /* Lighter text for better contrast */
219
  font-size: 14px !important;
220
  }}
221
- /* Override default gradio text color */
222
  .block-title {{ color: var(--text-accent) !important; }}
223
  span {{ color: var(--text-primary); }}
224
  """
225
 
226
  header_html = """
227
- <div style="padding: 20px 0; border-bottom: 1px solid rgba(212, 175, 55, 0.2); margin-bottom: 20px;">
228
  <div style="display: flex; align-items: center; gap: 20px;">
229
  <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#d4af37" stroke-width="2">
230
  <rect x="3" y="3" width="18" height="18" rx="2" />
@@ -234,8 +252,8 @@ header_html = """
234
  <circle cx="12" cy="12" r="3" stroke="#d4af37" fill="none"/>
235
  </svg>
236
  <div>
237
- <h1 style="margin: 0; font-size: 36px; font-weight: 700; color: #e0e7ff; text-shadow: 0 0 10px rgba(212, 175, 55, 0.3);">ROSETTA DECODER</h1>
238
- <p style="margin: 0; font-size: 14px; color: #d4af37; letter-spacing: 3px; font-weight: 600;">AI HIEROGLYPHIC TRANSLATION SYSTEM</p>
239
  </div>
240
  </div>
241
  </div>
@@ -244,7 +262,7 @@ header_html = """
244
  mission_html = """
245
  <div class="card">
246
  <div class="card-title">πŸ“‘ VISION STATEMENT</div>
247
- <p style="opacity: 0.9; font-size: 16px; line-height: 1.8; color: #e0e7ff;">
248
  <b>Bridging the Ancient and the Digital.</b><br>
249
  The Rosetta Decoder project utilizes advanced computer vision to identify and catalog Ancient Egyptian hieroglyphs.
250
  By automating the detection of Gardiner codes, we are creating a digital bridge that will eventually allow for instant,
@@ -309,17 +327,30 @@ claude_json_content = """{
309
  }"""
310
 
311
  # --- 4. MAIN APP ASSEMBLY ---
 
 
 
 
 
 
 
 
312
  with gr.Blocks(title="Rosetta Decoder") as demo:
313
- # Inject Styles
314
  gr.HTML(f"<style>{custom_css}</style>")
315
 
316
- # Top Section
317
- gr.HTML(header_html)
 
 
 
 
 
 
318
  gr.HTML(mission_html)
319
 
320
  # Workspace
321
  with gr.Row():
322
- # INPUT COLUMN
323
  with gr.Column(scale=1):
324
  gr.HTML('<div class="card"><div class="card-title">INPUT IMAGE</div>')
325
  with gr.Tabs():
@@ -334,36 +365,25 @@ with gr.Blocks(title="Rosetta Decoder") as demo:
334
  btn_cam = gr.Button("πŸ” LIVE DECODE", elem_classes="primary-btn")
335
  gr.HTML('</div>')
336
 
337
- # OUTPUT COLUMN
338
  with gr.Column(scale=1):
339
  gr.HTML('<div class="card"><div class="card-title">AI ANALYSIS RESULTS</div>')
340
  out_image = gr.Image(label="Decoded Result", interactive=False)
341
-
342
- # Download Button
343
  btn_download = gr.DownloadButton("πŸ’Ύ DOWNLOAD RESULT", visible=True)
344
-
345
  out_report = gr.Textbox(label="Analysis Log", lines=6, elem_classes="report-box", placeholder="Waiting for data stream...")
346
  with gr.Accordion("Raw Glyph Data (JSON)", open=False):
347
  out_json = gr.JSON(label="JSON Data")
348
  gr.HTML('</div>')
349
 
350
- # Footer Section
351
  gr.HTML(guide_instructions_html)
352
  gr.Code(value=claude_json_content, language="json", label="claude_desktop_config.json", interactive=False, lines=15)
353
  gr.HTML("</div>")
354
 
355
  # Event Wiring
356
- btn_upload.click(
357
- fn=detect_hieroglyphs,
358
- inputs=[img_upload, slider_upload],
359
- outputs=[out_image, out_json, out_report, btn_download]
360
- )
361
 
362
- btn_cam.click(
363
- fn=detect_hieroglyphs,
364
- inputs=[img_cam, slider_cam],
365
- outputs=[out_image, out_json, out_report, btn_download]
366
- )
367
 
368
  if __name__ == "__main__":
369
  demo.launch(mcp_server=True, ssr_mode=False, allowed_paths=["/tmp"])
 
36
  report += f"===================================\n"
37
  report += f"Glyph Density: {total} Symbols Identified\n\n"
38
  report += "πŸ”£ GARDINER CODE INVENTORY:\n"
 
39
  for code, count in sorted_counts:
40
  report += f"β€’ Code [{code}]: {count} instance(s)\n"
 
41
  report += f"\n===================================\n"
42
  report += f"CONFIDENCE: High\n"
43
  report += f"STATUS: Digitized & Ready for Translation."
 
55
  annotated_array = results[0].plot()
56
  annotated_image = Image.fromarray(annotated_array[..., ::-1])
57
 
58
+ # Save for Download
59
  temp_dir = tempfile.gettempdir()
60
  save_path = os.path.join(temp_dir, "rosetta_decoded_result.jpg")
61
  annotated_image.save(save_path)
 
85
  except Exception as e:
86
  return None, {"error": str(e)}, f"System Failure: {str(e)}", None
87
 
88
+ # --- 3. UI STYLING & MYSTICAL CURSOR ---
89
 
90
+ # SVG Cursor: An Golden Ankh (Key of Life)
91
+ cursor_url = "url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNkNGFmMzciIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxjaXJjbGUgY3g9IjEyIiBjeT0iNiIgcj0iNCIgZmlsbD0icmdiYSgyMTIsIDE3NSwgNTUsIDAuMSkiLz48bGluZSB4MT0iMTIiIHkxPSIxMCIgeDI9IjEyIiB5Mj0iMjIiLz48bGluZSB4MT0iOCIgeTE9IjE1IiB4Mj0iMTYiIHkyPSIxNSIvPjwvc3ZnPg==')"
92
 
93
  custom_css = f"""
 
94
  @import url('https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;600;700&display=swap');
95
  @import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&display=swap');
96
 
97
+ /* --- THEME VARIABLES --- */
98
  :root {{
99
+ /* DAY MODE (Papyrus) */
100
+ --bg-gradient: linear-gradient(135deg, #f0e6d2 0%, #e6dcc3 100%);
101
+ --card-bg: rgba(255, 255, 255, 0.6);
102
+ --text-primary: #3d342b;
103
+ --text-accent: #8b4513;
104
+ --border-color: #8b4513;
105
+ --btn-grad: linear-gradient(135deg, #cd853f 0%, #8b4513 100%);
106
+ --btn-text: #fff;
107
+ --info-bg: rgba(139, 69, 19, 0.05);
108
+ --info-border: #8b4513;
109
+ --glow-color: rgba(139, 69, 19, 0.3);
110
+ }}
111
+
112
+ .dark {{
113
+ /* NIGHT MODE (Lapis Lazuli) */
114
+ --bg-gradient: radial-gradient(circle at 50% 0%, #0a0a2e 0%, #000000 100%);
115
  --card-bg: rgba(15, 15, 35, 0.7);
116
+ --text-primary: #e0e7ff;
117
+ --text-accent: #d4af37;
118
  --border-color: #d4af37;
119
  --btn-grad: linear-gradient(135deg, #b8860b 0%, #d4af37 100%);
120
  --btn-text: #000;
 
 
 
121
  --info-bg: rgba(212, 175, 55, 0.08);
122
  --info-border: #d4af37;
123
+ --glow-color: rgba(212, 175, 55, 0.4);
124
  }}
125
 
126
+ /* --- GLOBAL --- */
127
  body, .gradio-container {{
128
  background: var(--bg-gradient) !important;
129
+ font-family: 'Cairo', sans-serif !important;
130
  color: var(--text-primary) !important;
131
+ cursor: {cursor_url} 12 12, auto !important;
132
+ -webkit-font-smoothing: antialiased;
 
133
  }}
134
 
135
+ /* Force all clickable elements to use the Ankh cursor */
136
+ button, a, .cursor-pointer, .gradio-button {{
137
+ cursor: {cursor_url} 12 12, pointer !important;
138
  }}
139
 
140
  /* --- CARDS --- */
141
  .card {{
142
  background: var(--card-bg) !important;
143
+ border: 1px solid rgba(128, 128, 128, 0.2) !important;
144
  border-radius: 12px;
145
  padding: 24px;
146
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
147
  backdrop-filter: blur(12px);
148
  margin-bottom: 24px;
149
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
 
152
  .card:hover {{
153
  transform: translateY(-4px);
154
  border-color: var(--border-color) !important;
155
+ box-shadow: 0 10px 40px rgba(0,0,0,0.2), 0 0 20px var(--glow-color);
156
  }}
157
 
158
  /* --- BUTTONS --- */
 
172
  box-shadow: 0 0 25px var(--glow-color);
173
  }}
174
 
175
+ /* Toggle Button Styling */
176
+ button.toggle-btn {{
177
+ background: transparent !important;
178
+ border: 1px solid var(--border-color) !important;
179
+ color: var(--text-accent) !important;
180
+ font-size: 14px !important;
181
+ padding: 5px 15px !important;
182
+ }}
183
+ button.toggle-btn:hover {{
184
+ background: var(--info-bg) !important;
185
+ }}
186
+
187
  /* --- TYPOGRAPHY --- */
188
  .card-title {{
189
  font-family: 'Cairo', sans-serif;
190
+ font-size: 18px;
191
  font-weight: 700;
192
  color: var(--text-accent);
193
  text-transform: uppercase;
194
  letter-spacing: 2px;
195
+ border-bottom: 1px solid rgba(128,128,128, 0.2);
196
  padding-bottom: 12px;
197
  margin-bottom: 18px;
198
  display: flex;
 
200
  gap: 8px;
201
  }}
202
 
203
+ /* --- GUIDE BOXES --- */
204
  .guide-step {{
205
  background-color: var(--info-bg);
206
  border-left: 4px solid var(--info-border);
207
  padding: 16px;
208
  margin: 12px 0;
209
  border-radius: 0 8px 8px 0;
210
+ font-family: 'Space Mono', monospace;
211
  font-size: 13px;
212
  line-height: 1.6;
 
213
  }}
 
214
  .step-number {{
215
  color: var(--text-accent);
216
  font-weight: bold;
 
218
  display: block;
219
  margin-bottom: 6px;
220
  font-size: 12px;
 
221
  }}
 
222
  .path-highlight {{
223
+ background: rgba(128,128,128,0.2);
224
  padding: 3px 8px;
225
  border-radius: 4px;
226
  color: var(--text-accent);
227
  font-weight: bold;
228
+ border: 1px solid var(--border-color);
229
  }}
230
 
231
+ /* CLEANUP */
232
  .gradio-image, .gradio-json {{ background: transparent !important; border: none !important; }}
233
  .report-box textarea {{
234
+ background-color: rgba(0,0,0,0.2) !important;
235
  border: 1px solid var(--border-color) !important;
236
  font-family: 'Space Mono', monospace !important;
237
+ color: var(--text-primary) !important;
238
  font-size: 14px !important;
239
  }}
 
240
  .block-title {{ color: var(--text-accent) !important; }}
241
  span {{ color: var(--text-primary); }}
242
  """
243
 
244
  header_html = """
245
+ <div style="padding: 20px 0; border-bottom: 1px solid rgba(128,128,128,0.2); margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center;">
246
  <div style="display: flex; align-items: center; gap: 20px;">
247
  <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#d4af37" stroke-width="2">
248
  <rect x="3" y="3" width="18" height="18" rx="2" />
 
252
  <circle cx="12" cy="12" r="3" stroke="#d4af37" fill="none"/>
253
  </svg>
254
  <div>
255
+ <h1 style="margin: 0; font-size: 36px; font-weight: 700; color: var(--text-primary); text-shadow: 0 0 10px rgba(212, 175, 55, 0.3);">ROSETTA DECODER</h1>
256
+ <p style="margin: 0; font-size: 14px; color: var(--text-accent); letter-spacing: 3px; font-weight: 600;">AI HIEROGLYPHIC TRANSLATION SYSTEM</p>
257
  </div>
258
  </div>
259
  </div>
 
262
  mission_html = """
263
  <div class="card">
264
  <div class="card-title">πŸ“‘ VISION STATEMENT</div>
265
+ <p style="opacity: 0.9; font-size: 16px; line-height: 1.8; color: var(--text-primary);">
266
  <b>Bridging the Ancient and the Digital.</b><br>
267
  The Rosetta Decoder project utilizes advanced computer vision to identify and catalog Ancient Egyptian hieroglyphs.
268
  By automating the detection of Gardiner codes, we are creating a digital bridge that will eventually allow for instant,
 
327
  }"""
328
 
329
  # --- 4. MAIN APP ASSEMBLY ---
330
+ # JavaScript to toggle the 'dark' class on the body element
331
+ toggle_js = """
332
+ () => {
333
+ document.body.classList.toggle('dark');
334
+ document.querySelector('.gradio-container').classList.toggle('dark');
335
+ }
336
+ """
337
+
338
  with gr.Blocks(title="Rosetta Decoder") as demo:
339
+ # Inject CSS
340
  gr.HTML(f"<style>{custom_css}</style>")
341
 
342
+ # Top Section (Header + Toggle Button)
343
+ with gr.Row(elem_classes="header-row"):
344
+ with gr.Column(scale=4):
345
+ gr.HTML(header_html)
346
+ with gr.Column(scale=1):
347
+ # The Magic Toggle Button
348
+ btn_toggle = gr.Button("πŸŒ— Day / Night", elem_classes="toggle-btn")
349
+
350
  gr.HTML(mission_html)
351
 
352
  # Workspace
353
  with gr.Row():
 
354
  with gr.Column(scale=1):
355
  gr.HTML('<div class="card"><div class="card-title">INPUT IMAGE</div>')
356
  with gr.Tabs():
 
365
  btn_cam = gr.Button("πŸ” LIVE DECODE", elem_classes="primary-btn")
366
  gr.HTML('</div>')
367
 
 
368
  with gr.Column(scale=1):
369
  gr.HTML('<div class="card"><div class="card-title">AI ANALYSIS RESULTS</div>')
370
  out_image = gr.Image(label="Decoded Result", interactive=False)
 
 
371
  btn_download = gr.DownloadButton("πŸ’Ύ DOWNLOAD RESULT", visible=True)
 
372
  out_report = gr.Textbox(label="Analysis Log", lines=6, elem_classes="report-box", placeholder="Waiting for data stream...")
373
  with gr.Accordion("Raw Glyph Data (JSON)", open=False):
374
  out_json = gr.JSON(label="JSON Data")
375
  gr.HTML('</div>')
376
 
377
+ # Footer
378
  gr.HTML(guide_instructions_html)
379
  gr.Code(value=claude_json_content, language="json", label="claude_desktop_config.json", interactive=False, lines=15)
380
  gr.HTML("</div>")
381
 
382
  # Event Wiring
383
+ btn_toggle.click(None, None, None, js=toggle_js)
 
 
 
 
384
 
385
+ btn_upload.click(fn=detect_hieroglyphs, inputs=[img_upload, slider_upload], outputs=[out_image, out_json, out_report, btn_download])
386
+ btn_cam.click(fn=detect_hieroglyphs, inputs=[img_cam, slider_cam], outputs=[out_image, out_json, out_report, btn_download])
 
 
 
387
 
388
  if __name__ == "__main__":
389
  demo.launch(mcp_server=True, ssr_mode=False, allowed_paths=["/tmp"])