Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
-
# app.py - النسخة
|
| 2 |
-
# app.py - النسخة النهائية والمعدلة
|
| 3 |
|
| 4 |
import os
|
| 5 |
import json
|
|
@@ -33,7 +32,6 @@ def base64_to_image(b64_string):
|
|
| 33 |
return Image.open(io.BytesIO(img_data))
|
| 34 |
|
| 35 |
def start_new_session():
|
| 36 |
-
"""يبدأ جلسة جديدة على الخادم ويعيد معرف الجلسة وأمر إظهار الواجهة."""
|
| 37 |
print("Requesting to start a new session...")
|
| 38 |
try:
|
| 39 |
response = requests.post(API_START_SESSION_URL, timeout=30)
|
|
@@ -42,7 +40,6 @@ def start_new_session():
|
|
| 42 |
session_id = session_data.get("session_id")
|
| 43 |
if not session_id:
|
| 44 |
raise gr.Error("لم يتمكن الخادم من بدء جلسة جديدة.")
|
| 45 |
-
|
| 46 |
status_message = f"✅ تم بدء جلسة جديدة بنجاح. أنت الآن متصل بالخادم."
|
| 47 |
print(f"Session started successfully: {session_id}")
|
| 48 |
return session_id, status_message, gr.update(visible=True)
|
|
@@ -52,15 +49,12 @@ def start_new_session():
|
|
| 52 |
raise gr.Error(error_message)
|
| 53 |
|
| 54 |
def handle_end_session(session_id):
|
| 55 |
-
"""ينهي الجلسة الحالية على الخادم."""
|
| 56 |
if not session_id:
|
| 57 |
return "لا توجد جلسة نشطة لإنهائها.", None, gr.update(visible=False)
|
| 58 |
-
|
| 59 |
print(f"Requesting to end session: {session_id}")
|
| 60 |
try:
|
| 61 |
response = requests.post(f"{API_END_SESSION_URL}?session_id={session_id}", timeout=30)
|
| 62 |
response.raise_for_status()
|
| 63 |
-
|
| 64 |
status_message = f"🔌 تم إنهاء الجلسة بنجاح. انقطع الاتصال بالخادم."
|
| 65 |
print(status_message)
|
| 66 |
return status_message, None, gr.update(visible=False)
|
|
@@ -79,10 +73,8 @@ def run_single_frame_via_api(session_id, rgb_image_path, measurements_path):
|
|
| 79 |
with open(measurements_path, 'r') as f:
|
| 80 |
measurements_dict = json.load(f)
|
| 81 |
image_b64 = image_to_base64(rgb_image_pil)
|
| 82 |
-
|
| 83 |
payload = {
|
| 84 |
-
"session_id": session_id,
|
| 85 |
-
"image_b64": image_b64,
|
| 86 |
"measurements": {
|
| 87 |
"pos_global": measurements_dict.get('pos_global', [0.0, 0.0]),
|
| 88 |
"theta": measurements_dict.get('theta', 0.0),
|
|
@@ -90,7 +82,6 @@ def run_single_frame_via_api(session_id, rgb_image_path, measurements_path):
|
|
| 90 |
"target_point": measurements_dict.get('target_point', [0.0, 100.0])
|
| 91 |
}
|
| 92 |
}
|
| 93 |
-
|
| 94 |
print(f"Sending run_step request for session: {session_id}")
|
| 95 |
response = requests.post(API_RUN_STEP_URL, json=payload, timeout=60)
|
| 96 |
response.raise_for_status()
|
|
@@ -105,35 +96,31 @@ def run_single_frame_via_api(session_id, rgb_image_path, measurements_path):
|
|
| 105 |
raise gr.Error(f"حدث خطأ أثناء الاتصال بالـ API: {e}")
|
| 106 |
except Exception as e:
|
| 107 |
raise gr.Error(f"حدث خطأ غير متوقع: {e}")
|
|
|
|
| 108 |
# ==============================================================================
|
| 109 |
# 4. تعريف واجهة Gradio
|
| 110 |
# ==============================================================================
|
| 111 |
|
| 112 |
-
# --- الخطوة 1: تعريف متغير CSS مع المحددات الصحيحة ---
|
| 113 |
CUSTOM_CSS = """
|
| 114 |
-
/* القاعدة الأساسية لتوسيع الواجهة */
|
| 115 |
.gradio-container {max-width: 100% !important;}
|
| 116 |
-
|
| 117 |
-
/* استهداف الجدول داخل الحاوية التي أعطيناها المعرف 'examples-container' */
|
| 118 |
#examples-container .gradio-table {
|
| 119 |
-
table-layout: fixed;
|
| 120 |
-
width: 100
|
| 121 |
}
|
| 122 |
-
|
| 123 |
-
/* العمود الثاني (ملف القياسات): عرض ثابت وصغير */
|
| 124 |
#examples-container .gradio-table th:nth-child(1),
|
| 125 |
-
#examples-container .gradio-table
|
| 126 |
-
width:
|
| 127 |
}
|
| 128 |
-
/* إخفاء العمود الثاني
|
| 129 |
#examples-container .gradio-table th:nth-child(2),
|
| 130 |
#examples-container .gradio-table td:nth-child(2) {
|
| 131 |
display: none !important;
|
| 132 |
}
|
| 133 |
-
/* الأعمدة
|
| 134 |
#examples-container .gradio-table th:nth-child(n+3),
|
| 135 |
#examples-container .gradio-table td:nth-child(n+3) {
|
| 136 |
-
width:
|
| 137 |
text-align: center !important;
|
| 138 |
}
|
| 139 |
"""
|
|
@@ -155,101 +142,54 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"), cs
|
|
| 155 |
gr.Markdown("")
|
| 156 |
|
| 157 |
with gr.Group(visible=False) as main_controls_group:
|
| 158 |
-
with gr.Row(equal_height=
|
|
|
|
| 159 |
with gr.Column(scale=2):
|
| 160 |
with gr.Group():
|
| 161 |
gr.Markdown("### 🗂️ ارفع ملفات السيناريو")
|
| 162 |
api_rgb_image_path = gr.Image(type="filepath", label="(RGB)")
|
| 163 |
api_measurements_path = gr.File(label="(JSON)", type="filepath")
|
| 164 |
api_run_button = gr.Button("🚀 أرسل البيانات للمعالجة", variant="primary")
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
# with gr.Row():
|
| 168 |
-
# --- التعديل: إضافة elem_id إلى حاوية الأمثلة ---
|
| 169 |
with gr.Group(elem_id="examples-container"):
|
| 170 |
gr.Markdown("### ✨ أمثلة جاهزة")
|
| 171 |
-
if os.path.isdir(EXAMPLES_DIR)
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
# --- التعديل: إزالة elem_classes من هنا ---
|
| 189 |
-
gr.Examples(
|
| 190 |
-
examples=[
|
| 191 |
-
[
|
| 192 |
-
os.path.join(EXAMPLES_DIR, "sample1", "rgb.jpg"),
|
| 193 |
-
os.path.join(EXAMPLES_DIR, "sample1", "measurements.json"),
|
| 194 |
-
f"{data1.get('speed', 0.0):.2f}",
|
| 195 |
-
f"{data1.get('theta', 0.0):.2f}",
|
| 196 |
-
str(data1.get('pos_global', 'N/A')),
|
| 197 |
-
str(data1.get('target_point', 'N/A'))
|
| 198 |
],
|
| 199 |
-
[
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
str(data2.get('pos_global', 'N/A')),
|
| 205 |
-
str(data2.get('target_point', 'N/A'))
|
| 206 |
-
],
|
| 207 |
-
[ os.path.join(EXAMPLES_DIR, "sample3", "rgb.jpg"),
|
| 208 |
-
os.path.join(EXAMPLES_DIR, "sample3", "measurements.json"),
|
| 209 |
-
f"{data3.get('speed', 0.0):.2f}",
|
| 210 |
-
f"{data3.get('theta', 0.0):.2f}",
|
| 211 |
-
str(data3.get('pos_global', 'N/A')),
|
| 212 |
-
str(data3.get('target_point', 'N/A'))
|
| 213 |
-
]
|
| 214 |
-
],
|
| 215 |
-
inputs=[
|
| 216 |
-
api_rgb_image_path,
|
| 217 |
-
api_measurements_path,
|
| 218 |
-
example_speed,
|
| 219 |
-
example_theta,
|
| 220 |
-
example_pos,
|
| 221 |
-
example_target
|
| 222 |
-
],
|
| 223 |
-
label="اختر سيناريو اختبار"
|
| 224 |
-
)
|
| 225 |
else:
|
| 226 |
-
gr.Markdown("لم يتم العثور على مجلد الأمثلة (`examples`)
|
| 227 |
|
|
|
|
| 228 |
with gr.Column(scale=3):
|
| 229 |
with gr.Group():
|
| 230 |
gr.Markdown("### 📊 النتائج من الخادم")
|
| 231 |
api_output_image = gr.Image(label="لوحة التحكم المرئية (من الـ API)", type="pil", interactive=False, height=600)
|
| 232 |
api_control_json = gr.JSON(label="أوامر التحكم (من الـ API)")
|
| 233 |
|
| 234 |
-
|
| 235 |
# --- ربط منطق الواجهة ---
|
| 236 |
-
start_session_button.click(
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
outputs=[session_id_state, status_textbox, main_controls_group]
|
| 240 |
-
)
|
| 241 |
-
|
| 242 |
-
end_session_button.click(
|
| 243 |
-
fn=handle_end_session,
|
| 244 |
-
inputs=[session_id_state],
|
| 245 |
-
outputs=[status_textbox, session_id_state, main_controls_group]
|
| 246 |
-
)
|
| 247 |
-
|
| 248 |
-
api_run_button.click(
|
| 249 |
-
fn=run_single_frame_via_api,
|
| 250 |
-
inputs=[session_id_state, api_rgb_image_path, api_measurements_path],
|
| 251 |
-
outputs=[api_output_image, api_control_json],
|
| 252 |
-
)
|
| 253 |
|
| 254 |
if __name__ == "__main__":
|
| 255 |
demo.queue().launch(debug=True)
|
|
|
|
| 1 |
+
# app.py - النسخة النهائية والمحسّنة
|
|
|
|
| 2 |
|
| 3 |
import os
|
| 4 |
import json
|
|
|
|
| 32 |
return Image.open(io.BytesIO(img_data))
|
| 33 |
|
| 34 |
def start_new_session():
|
|
|
|
| 35 |
print("Requesting to start a new session...")
|
| 36 |
try:
|
| 37 |
response = requests.post(API_START_SESSION_URL, timeout=30)
|
|
|
|
| 40 |
session_id = session_data.get("session_id")
|
| 41 |
if not session_id:
|
| 42 |
raise gr.Error("لم يتمكن الخادم من بدء جلسة جديدة.")
|
|
|
|
| 43 |
status_message = f"✅ تم بدء جلسة جديدة بنجاح. أنت الآن متصل بالخادم."
|
| 44 |
print(f"Session started successfully: {session_id}")
|
| 45 |
return session_id, status_message, gr.update(visible=True)
|
|
|
|
| 49 |
raise gr.Error(error_message)
|
| 50 |
|
| 51 |
def handle_end_session(session_id):
|
|
|
|
| 52 |
if not session_id:
|
| 53 |
return "لا توجد جلسة نشطة لإنهائها.", None, gr.update(visible=False)
|
|
|
|
| 54 |
print(f"Requesting to end session: {session_id}")
|
| 55 |
try:
|
| 56 |
response = requests.post(f"{API_END_SESSION_URL}?session_id={session_id}", timeout=30)
|
| 57 |
response.raise_for_status()
|
|
|
|
| 58 |
status_message = f"🔌 تم إنهاء الجلسة بنجاح. انقطع الاتصال بالخادم."
|
| 59 |
print(status_message)
|
| 60 |
return status_message, None, gr.update(visible=False)
|
|
|
|
| 73 |
with open(measurements_path, 'r') as f:
|
| 74 |
measurements_dict = json.load(f)
|
| 75 |
image_b64 = image_to_base64(rgb_image_pil)
|
|
|
|
| 76 |
payload = {
|
| 77 |
+
"session_id": session_id, "image_b64": image_b64,
|
|
|
|
| 78 |
"measurements": {
|
| 79 |
"pos_global": measurements_dict.get('pos_global', [0.0, 0.0]),
|
| 80 |
"theta": measurements_dict.get('theta', 0.0),
|
|
|
|
| 82 |
"target_point": measurements_dict.get('target_point', [0.0, 100.0])
|
| 83 |
}
|
| 84 |
}
|
|
|
|
| 85 |
print(f"Sending run_step request for session: {session_id}")
|
| 86 |
response = requests.post(API_RUN_STEP_URL, json=payload, timeout=60)
|
| 87 |
response.raise_for_status()
|
|
|
|
| 96 |
raise gr.Error(f"حدث خطأ أثناء الاتصال بالـ API: {e}")
|
| 97 |
except Exception as e:
|
| 98 |
raise gr.Error(f"حدث خطأ غير متوقع: {e}")
|
| 99 |
+
|
| 100 |
# ==============================================================================
|
| 101 |
# 4. تعريف واجهة Gradio
|
| 102 |
# ==============================================================================
|
| 103 |
|
|
|
|
| 104 |
CUSTOM_CSS = """
|
|
|
|
| 105 |
.gradio-container {max-width: 100% !important;}
|
|
|
|
|
|
|
| 106 |
#examples-container .gradio-table {
|
| 107 |
+
table-layout: fixed !important;
|
| 108 |
+
width: 100% !important;
|
| 109 |
}
|
| 110 |
+
/* تصحيح: تنسيق العمود الأول (الصورة) ليشمل الرأس والبيانات */
|
|
|
|
| 111 |
#examples-container .gradio-table th:nth-child(1),
|
| 112 |
+
#examples-container .gradio-table td:nth-child(1) {
|
| 113 |
+
width: 120px !important;
|
| 114 |
}
|
| 115 |
+
/* إخفاء العمود الثاني (ملف القياسات) */
|
| 116 |
#examples-container .gradio-table th:nth-child(2),
|
| 117 |
#examples-container .gradio-table td:nth-child(2) {
|
| 118 |
display: none !important;
|
| 119 |
}
|
| 120 |
+
/* تنسيق الأعمدة الرقمية المتبقية */
|
| 121 |
#examples-container .gradio-table th:nth-child(n+3),
|
| 122 |
#examples-container .gradio-table td:nth-child(n+3) {
|
| 123 |
+
width: 110px !important;
|
| 124 |
text-align: center !important;
|
| 125 |
}
|
| 126 |
"""
|
|
|
|
| 142 |
gr.Markdown("")
|
| 143 |
|
| 144 |
with gr.Group(visible=False) as main_controls_group:
|
| 145 |
+
with gr.Row(equal_height=False):
|
| 146 |
+
# --- العمود الأيسر: للمدخلات والأمثلة ---
|
| 147 |
with gr.Column(scale=2):
|
| 148 |
with gr.Group():
|
| 149 |
gr.Markdown("### 🗂️ ارفع ملفات السيناريو")
|
| 150 |
api_rgb_image_path = gr.Image(type="filepath", label="(RGB)")
|
| 151 |
api_measurements_path = gr.File(label="(JSON)", type="filepath")
|
| 152 |
api_run_button = gr.Button("🚀 أرسل البيانات للمعالجة", variant="primary")
|
| 153 |
+
|
|
|
|
|
|
|
|
|
|
| 154 |
with gr.Group(elem_id="examples-container"):
|
| 155 |
gr.Markdown("### ✨ أمثلة جاهزة")
|
| 156 |
+
if os.path.isdir(EXAMPLES_DIR):
|
| 157 |
+
try:
|
| 158 |
+
with open(os.path.join(EXAMPLES_DIR, "sample1", "measurements.json"), 'r') as f: data1 = json.load(f)
|
| 159 |
+
with open(os.path.join(EXAMPLES_DIR, "sample2", "measurements.json"), 'r') as f: data2 = json.load(f)
|
| 160 |
+
with open(os.path.join(EXAMPLES_DIR, "sample3", "measurements.json"), 'r') as f: data3 = json.load(f)
|
| 161 |
+
|
| 162 |
+
with gr.Column(visible=False):
|
| 163 |
+
example_speed = gr.Textbox()
|
| 164 |
+
example_theta = gr.Textbox()
|
| 165 |
+
example_pos = gr.Textbox()
|
| 166 |
+
example_target = gr.Textbox()
|
| 167 |
+
|
| 168 |
+
gr.Examples(
|
| 169 |
+
examples=[
|
| 170 |
+
[os.path.join(EXAMPLES_DIR, "sample1", "rgb.jpg"), os.path.join(EXAMPLES_DIR, "sample1", "measurements.json"), f"{data1.get('speed', 0.0):.2f}", f"{data1.get('theta', 0.0):.2f}", str(data1.get('pos_global', 'N/A')), str(data1.get('target_point', 'N/A'))],
|
| 171 |
+
[os.path.join(EXAMPLES_DIR, "sample2", "rgb.jpg"), os.path.join(EXAMPLES_DIR, "sample2", "measurements.json"), f"{data2.get('speed', 0.0):.2f}", f"{data2.get('theta', 0.0):.2f}", str(data2.get('pos_global', 'N/A')), str(data2.get('target_point', 'N/A'))],
|
| 172 |
+
[os.path.join(EXAMPLES_DIR, "sample3", "rgb.jpg"), os.path.join(EXAMPLES_DIR, "sample3", "measurements.json"), f"{data3.get('speed', 0.0):.2f}", f"{data3.get('theta', 0.0):.2f}", str(data3.get('pos_global', 'N/A')), str(data3.get('target_point', 'N/A'))]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
],
|
| 174 |
+
inputs=[api_rgb_image_path, api_measurements_path, example_speed, example_theta, example_pos, example_target],
|
| 175 |
+
label="اختر سيناريو اختبار"
|
| 176 |
+
)
|
| 177 |
+
except FileNotFoundError:
|
| 178 |
+
gr.Markdown("لم يتم العثور على ملفات الأمثلة داخل مجلد `examples`.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
else:
|
| 180 |
+
gr.Markdown("لم يتم العثور على مجلد الأمثلة (`examples`).")
|
| 181 |
|
| 182 |
+
# --- العمود الأيمن: للمخرجات ---
|
| 183 |
with gr.Column(scale=3):
|
| 184 |
with gr.Group():
|
| 185 |
gr.Markdown("### 📊 النتائج من الخادم")
|
| 186 |
api_output_image = gr.Image(label="لوحة التحكم المرئية (من الـ API)", type="pil", interactive=False, height=600)
|
| 187 |
api_control_json = gr.JSON(label="أوامر التحكم (من الـ API)")
|
| 188 |
|
|
|
|
| 189 |
# --- ربط منطق الواجهة ---
|
| 190 |
+
start_session_button.click(fn=start_new_session, inputs=None, outputs=[session_id_state, status_textbox, main_controls_group])
|
| 191 |
+
end_session_button.click(fn=handle_end_session, inputs=[session_id_state], outputs=[status_textbox, session_id_state, main_controls_group])
|
| 192 |
+
api_run_button.click(fn=run_single_frame_via_api, inputs=[session_id_state, api_rgb_image_path, api_measurements_path], outputs=[api_output_image, api_control_json])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
|
| 194 |
if __name__ == "__main__":
|
| 195 |
demo.queue().launch(debug=True)
|