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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -63
app.py CHANGED
@@ -9,7 +9,6 @@ import tempfile
9
  # --- 1. SETUP & MODEL LOADING ---
10
  MODEL_REPO = "youkii-xr/hieroglyphic-detection"
11
  MODEL_FILENAME = "best.pt"
12
- # Fix for the Ultralytics config warning in containers
13
  os.environ["YOLO_CONFIG_DIR"] = "/tmp/Ultralytics"
14
 
15
  try:
@@ -25,9 +24,8 @@ except Exception as e:
25
  print(f"Error: {e}")
26
  model = None
27
 
28
- # --- 2. LOGIC: DECODING & REPORTING ---
29
  def generate_human_report(detections, counts):
30
- """Generates a natural language summary of the findings."""
31
  if not detections:
32
  return "Rosetta Decoder detects no identifiable Gardiner codes in this image."
33
 
@@ -56,17 +54,14 @@ def detect_hieroglyphs(image: Image.Image, conf_threshold: float = 0.25):
56
  try:
57
  results = model.predict(source=image, conf=conf_threshold, iou=0.45, imgsz=640, verbose=False, device='cpu', max_det=300)
58
 
59
- # Visual
60
  annotated_array = results[0].plot()
61
  annotated_image = Image.fromarray(annotated_array[..., ::-1])
62
 
63
  # Save for Download Button
64
- # We create a temp file so the download button can find it
65
  temp_dir = tempfile.gettempdir()
66
  save_path = os.path.join(temp_dir, "rosetta_decoded_result.jpg")
67
  annotated_image.save(save_path)
68
 
69
- # Data
70
  detections = []
71
  gardiner_counts = {}
72
 
@@ -87,72 +82,57 @@ def detect_hieroglyphs(image: Image.Image, conf_threshold: float = 0.25):
87
  }
88
 
89
  text_report = generate_human_report(detections, gardiner_counts)
90
-
91
- # Return: Image, JSON, Text, FilePath (for download)
92
  return annotated_image, summary_json, text_report, save_path
93
 
94
  except Exception as e:
95
  return None, {"error": str(e)}, f"System Failure: {str(e)}", None
96
 
97
- # --- 3. UI STYLING (HTML/CSS INJECTION) ---
98
 
99
- # SVG Cursor: A stylized "Lens"
100
  cursor_url = "url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDMyIDMyIj4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiNkNGFmMzciIHN0cm9rZS13aWR0aD0iMS41Ij4KICAgIDxjaXJjbGUgY3g9IjE2IiBjeT0iMTYiIHI9IjgiIGZpbGw9InJnYmEoMjEyLCAxNzUsIDU1LCAwLjEpIi8+CiAgICA8cGF0aCBkPSZNMTYsNCBMMTYsOCIvPgogICAgPHBhdGggZD0iTTE2LDI0IEwxNiwyOCIvPgogICAgPHBhdGggZD0iTTQsMTYgTDgsMTYiLz4KICAgIDxwYXRoIGQ9Ik0yNCwxNiBMMjgsMTYiLz4KICAgIDxjaXJjbGUgY3g9IjE2IiBjeT0iMTYiIHI9IjIiIGZpbGw9IiNkNGFmMzciLz4KICA8L2c+Cjwvc3ZnPg==')"
101
 
102
  custom_css = f"""
103
- @import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;700&display=swap');
104
- @import url('https://fonts.googleapis.com/css2?family=Space+Mono:ital,wght@0,400;0,700;1,400&display=swap');
 
105
 
106
- /* --- THEME VARIABLES --- */
107
  :root {{
108
- /* DAY MODE */
109
- --bg-gradient: linear-gradient(135deg, #f0e6d2 0%, #e6dcc3 100%);
110
- --card-bg: rgba(255, 255, 255, 0.6);
111
- --text-primary: #3d342b;
112
- --text-accent: #8b4513; /* Saddle Brown */
113
- --border-color: #8b4513;
114
- --btn-grad: linear-gradient(135deg, #cd853f 0%, #8b4513 100%);
115
- --btn-text: #fff;
116
- --glow-color: rgba(139, 69, 19, 0.3);
117
- /* Guide Box Colors (Golden/Info) */
118
- --info-bg: rgba(212, 175, 55, 0.1);
119
- --info-border: #d4af37;
120
- }}
121
-
122
- .dark {{
123
- /* DARK MODE */
124
- --bg-gradient: radial-gradient(circle at 50% 0%, #1c1c1c 0%, #0a0a0a 100%);
125
- --card-bg: rgba(30, 30, 30, 0.7);
126
- --text-primary: #dcdcdc;
127
  --text-accent: #d4af37; /* Gold */
128
  --border-color: #d4af37;
129
  --btn-grad: linear-gradient(135deg, #b8860b 0%, #d4af37 100%);
130
  --btn-text: #000;
131
  --glow-color: rgba(212, 175, 55, 0.4);
132
- /* Guide Box Colors (Golden/Info) */
133
- --info-bg: rgba(212, 175, 55, 0.1);
 
134
  --info-border: #d4af37;
135
  }}
136
 
137
  /* --- GLOBAL SETTINGS --- */
138
  body, .gradio-container {{
139
  background: var(--bg-gradient) !important;
140
- font-family: 'Cinzel', serif !important;
141
  color: var(--text-primary) !important;
142
  cursor: {cursor_url} 16 16, auto !important;
 
 
143
  }}
144
 
145
  button, a, .cursor-pointer {{
146
  cursor: {cursor_url} 16 16, pointer !important;
147
  }}
148
 
149
- /* --- ANIMATED CARDS --- */
150
  .card {{
151
  background: var(--card-bg) !important;
152
- border: 1px solid rgba(128, 128, 128, 0.2) !important;
153
  border-radius: 12px;
154
  padding: 24px;
155
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
156
  backdrop-filter: blur(12px);
157
  margin-bottom: 24px;
158
  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
@@ -161,7 +141,7 @@ button, a, .cursor-pointer {{
161
  .card:hover {{
162
  transform: translateY(-4px);
163
  border-color: var(--border-color) !important;
164
- box-shadow: 0 10px 30px rgba(0,0,0,0.3), 0 0 15px var(--glow-color);
165
  }}
166
 
167
  /* --- BUTTONS --- */
@@ -170,25 +150,26 @@ button.primary-btn {{
170
  border: 1px solid var(--border-color) !important;
171
  color: var(--btn-text) !important;
172
  font-weight: 700 !important;
173
- font-family: 'Space Mono', monospace !important;
174
  text-transform: uppercase;
175
- letter-spacing: 2px;
176
  transition: all 0.3s ease;
 
177
  }}
178
  button.primary-btn:hover {{
179
  transform: scale(1.02);
180
- box-shadow: 0 0 20px var(--glow-color);
181
  }}
182
 
183
  /* --- TYPOGRAPHY --- */
184
  .card-title {{
185
- font-family: 'Space Mono', monospace;
186
- font-size: 14px;
187
  font-weight: 700;
188
  color: var(--text-accent);
189
  text-transform: uppercase;
190
- letter-spacing: 3px;
191
- border-bottom: 1px solid rgba(128,128,128, 0.2);
192
  padding-bottom: 12px;
193
  margin-bottom: 18px;
194
  display: flex;
@@ -203,9 +184,10 @@ button.primary-btn:hover {{
203
  padding: 16px;
204
  margin: 12px 0;
205
  border-radius: 0 8px 8px 0;
206
- font-family: 'Space Mono', monospace;
207
  font-size: 13px;
208
  line-height: 1.6;
 
209
  }}
210
 
211
  .step-number {{
@@ -214,42 +196,46 @@ button.primary-btn:hover {{
214
  text-transform: uppercase;
215
  display: block;
216
  margin-bottom: 6px;
217
- font-size: 11px;
218
  letter-spacing: 1px;
219
  }}
220
 
221
  .path-highlight {{
222
- background: rgba(128,128,128,0.2);
223
- padding: 2px 6px;
224
  border-radius: 4px;
225
  color: var(--text-accent);
226
  font-weight: bold;
 
227
  }}
228
 
229
  /* UI CLEANUP */
230
  .gradio-image, .gradio-json {{ background: transparent !important; border: none !important; }}
231
  .report-box textarea {{
232
- background-color: rgba(0,0,0,0.2) !important;
233
  border: 1px solid var(--border-color) !important;
234
  font-family: 'Space Mono', monospace !important;
235
- color: var(--text-accent) !important;
236
- font-size: 13px !important;
237
  }}
 
 
 
238
  """
239
 
240
  header_html = """
241
- <div style="padding: 20px 0; border-bottom: 1px solid rgba(128,128,128,0.1); margin-bottom: 20px;">
242
- <div style="display: flex; align-items: center; gap: 15px;">
243
- <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="var(--text-accent)" stroke-width="2">
244
  <rect x="3" y="3" width="18" height="18" rx="2" />
245
  <path d="M7 7h10" />
246
  <path d="M7 12h10" />
247
  <path d="M7 17h10" />
248
- <circle cx="12" cy="12" r="3" stroke="var(--text-accent)" fill="none"/>
249
  </svg>
250
  <div>
251
- <h1 style="margin: 0; font-size: 28px; font-family: 'Cinzel', serif; letter-spacing: 1px; color: var(--text-primary);">ROSETTA DECODER</h1>
252
- <p style="margin: 0; font-family: 'Space Mono', monospace; font-size: 11px; color: var(--text-accent); letter-spacing: 3px;">AI HIEROGLYPHIC TRANSLATION SYSTEM</p>
253
  </div>
254
  </div>
255
  </div>
@@ -258,7 +244,7 @@ header_html = """
258
  mission_html = """
259
  <div class="card">
260
  <div class="card-title">📡 VISION STATEMENT</div>
261
- <p style="opacity: 0.9; font-size: 15px; line-height: 1.8;">
262
  <b>Bridging the Ancient and the Digital.</b><br>
263
  The Rosetta Decoder project utilizes advanced computer vision to identify and catalog Ancient Egyptian hieroglyphs.
264
  By automating the detection of Gardiner codes, we are creating a digital bridge that will eventually allow for instant,
@@ -353,7 +339,7 @@ with gr.Blocks(title="Rosetta Decoder") as demo:
353
  gr.HTML('<div class="card"><div class="card-title">AI ANALYSIS RESULTS</div>')
354
  out_image = gr.Image(label="Decoded Result", interactive=False)
355
 
356
- # Download Button (Standard Gradio Component)
357
  btn_download = gr.DownloadButton("💾 DOWNLOAD RESULT", visible=True)
358
 
359
  out_report = gr.Textbox(label="Analysis Log", lines=6, elem_classes="report-box", placeholder="Waiting for data stream...")
@@ -367,8 +353,6 @@ with gr.Blocks(title="Rosetta Decoder") as demo:
367
  gr.HTML("</div>")
368
 
369
  # Event Wiring
370
- # Note: detect_hieroglyphs now returns 4 values: Image, JSON, Text, FilePath
371
-
372
  btn_upload.click(
373
  fn=detect_hieroglyphs,
374
  inputs=[img_upload, slider_upload],
 
9
  # --- 1. SETUP & MODEL LOADING ---
10
  MODEL_REPO = "youkii-xr/hieroglyphic-detection"
11
  MODEL_FILENAME = "best.pt"
 
12
  os.environ["YOLO_CONFIG_DIR"] = "/tmp/Ultralytics"
13
 
14
  try:
 
24
  print(f"Error: {e}")
25
  model = None
26
 
27
+ # --- 2. LOGIC ---
28
  def generate_human_report(detections, counts):
 
29
  if not detections:
30
  return "Rosetta Decoder detects no identifiable Gardiner codes in this image."
31
 
 
54
  try:
55
  results = model.predict(source=image, conf=conf_threshold, iou=0.45, imgsz=640, verbose=False, device='cpu', max_det=300)
56
 
 
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)
64
 
 
65
  detections = []
66
  gardiner_counts = {}
67
 
 
82
  }
83
 
84
  text_report = generate_human_report(detections, gardiner_counts)
 
 
85
  return annotated_image, summary_json, text_report, save_path
86
 
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
  .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 --- */
 
150
  border: 1px solid var(--border-color) !important;
151
  color: var(--btn-text) !important;
152
  font-weight: 700 !important;
153
+ font-family: 'Cairo', sans-serif !important;
154
  text-transform: uppercase;
155
+ letter-spacing: 1px;
156
  transition: all 0.3s ease;
157
+ font-size: 16px !important;
158
  }}
159
  button.primary-btn:hover {{
160
  transform: scale(1.02);
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;
 
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 {{
 
196
  text-transform: uppercase;
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" />
231
  <path d="M7 7h10" />
232
  <path d="M7 12h10" />
233
  <path d="M7 17h10" />
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
  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,
 
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...")
 
353
  gr.HTML("</div>")
354
 
355
  # Event Wiring
 
 
356
  btn_upload.click(
357
  fn=detect_hieroglyphs,
358
  inputs=[img_upload, slider_upload],