Mosensei commited on
Commit
3f72175
·
verified ·
1 Parent(s): b92d5b5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +244 -116
app.py CHANGED
@@ -1,211 +1,339 @@
1
  import gradio as gr
2
  import mlflow
3
- import dagshub
 
 
4
  from ultralytics import YOLO
5
  from PIL import Image
6
  import cv2
7
  import numpy as np
8
- import os
9
- import time
10
- import tempfile
11
 
12
  # ==============================
13
- # MLflow Authentication via Secrets (زي ما أنت عايز بالظبط)
14
  # ==============================
15
  tracking_uri = os.getenv("MLFLOW_TRACKING_URI")
16
  username = os.getenv("MLFLOW_TRACKING_USERNAME")
17
  password = os.getenv("MLFLOW_TRACKING_PASSWORD")
18
 
19
  if not all([tracking_uri, username, password]):
20
- raise ValueError("MLflow Secrets مش موجودة أو غلط! روح Settings → Secrets وتأكد من الأسماء التلاتة")
21
 
22
  os.environ["MLFLOW_TRACKING_URI"] = tracking_uri
23
  os.environ["MLFLOW_TRACKING_USERNAME"] = username
24
  os.environ["MLFLOW_TRACKING_PASSWORD"] = password
25
 
26
- # تفعيل DagsHub
27
- dagshub.init(repo_owner="Mosensei7", repo_name="AutonomousVehiclesDetectionDEPI", mlflow=True)
28
-
29
- # إنشاء experiment مخصص
30
  mlflow.set_experiment("YOLOv12s_Inference_Logs")
31
-
32
- print("✅ MLflow + DagsHub connected successfully via Secrets!")
33
 
34
  # ==============================
35
- # تحميل الموديل الصحيح
36
  # ==============================
37
- # لو رافع الموديل على HF كـ repo، استخدم الاسم الكامل
38
- model = YOLO("Mosensei7/yolov12s-egyptian-autonomous-vehicles/best.pt") # غيّر الاسم لو مختلف
39
 
40
  # ==============================
41
- # Inference مع رفع كل حاجة على DagsHub
42
  # ==============================
43
  def run_inference(media_file, media_type):
44
  if media_file is None:
45
- return None, None, "⚠️ ارفع صورة أو فيديو أولاً"
46
-
47
  media_path = media_file.name
48
-
49
- with mlflow.start_run(run_name=f"YOLOv12s_Inference_{int(time.time())}") as run:
50
  mlflow.log_param("media_type", media_type)
51
- mlflow.log_param("model_version", "YOLOv12s")
52
  mlflow.log_param("timestamp", time.strftime("%Y-%m-%d %H:%M:%S"))
53
-
54
- run_url = f"https://dagshub.com/Mosensei7/AutonomousVehiclesDetectionDEPI/mlflow/#/experiments/{mlflow.get_experiment_by_name('YOLOv12s_Inference_Logs').experiment_id}/runs/{run.info.run_id}"
55
-
56
  if media_type == "Image":
57
  img = Image.open(media_path).convert("RGB")
58
  img_array = np.array(img)
59
-
60
  results = model(img_array)[0]
61
  annotated = results.plot()
62
  output_img = Image.fromarray(annotated[..., ::-1])
63
-
64
- # رفع input/output
65
  with tempfile.TemporaryDirectory() as tmpdir:
66
  in_path = os.path.join(tmpdir, "input.jpg")
67
  out_path = os.path.join(tmpdir, "output.jpg")
68
  img.save(in_path)
69
  output_img.save(out_path)
70
-
71
- mlflow.log_artifact(in_path, "input")
72
- mlflow.log_artifact(out_path, "output")
73
-
74
  detections = len(results.boxes) if results.boxes is not None else 0
75
- mlflow.log_metric("detections", detections)
76
-
77
- return output_img, None, f"**✅ تم الكشف والتسجيل بنجاح!**\n\n**Run ID:** `{run.info.run_id}`\n[👀 شوف الـ Log كامل على DagsHub]({run_url})"
78
-
 
 
79
  else: # Video
80
  cap = cv2.VideoCapture(media_path)
81
  fps = cap.get(cv2.CAP_PROP_FPS) or 30
82
  w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
83
  h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
84
-
85
  output_video = "output_video.mp4"
86
  writer = cv2.VideoWriter(output_video, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
87
-
88
  frame_count = 0
89
  total_detections = 0
90
-
91
  while cap.isOpened():
92
  ret, frame = cap.read()
93
  if not ret:
94
  break
 
95
  results = model(frame)[0]
96
  annotated = results.plot()
97
  writer.write(annotated)
 
98
  frame_count += 1
99
  total_detections += len(results.boxes) if results.boxes is not None else 0
100
-
101
  cap.release()
102
  writer.release()
103
-
104
- mlflow.log_artifact(media_path, "input_video")
105
- mlflow.log_artifact(output_video, "output_video")
106
- mlflow.log_metric("frames", frame_count)
107
  mlflow.log_metric("total_detections", total_detections)
108
- mlflow.log_metric("avg_detections_per_frame", round(total_detections / frame_count, 2) if frame_count > 0 else 0)
109
-
110
- # حذف الفيديو المؤقت
 
 
 
111
  if os.path.exists(output_video):
112
  os.remove(output_video)
113
-
114
- return None, output_video, f"**✅ تم معالجة الفيديو والتسجيل بنجاح!**\n\n**Run ID:** `{run.info.run_id}`\n[👀 شوف الـ Log كامل على DagsHub]({run_url})"
115
 
116
  # ==============================
117
- # التصميم الفضائي الرهيب جدًا (Cyberpunk 2077 style)
118
  # ==============================
119
  css = """
 
 
 
 
 
 
120
  body {
121
- background: linear-gradient(135deg, #000428, #004e92);
122
- color: #00ffea;
123
- font-family: 'Rajdhani', sans-serif;
124
  }
 
125
  .gradio-container {
126
- max-width: 1200px;
127
- margin: 0 auto;
128
- background: linear-gradient(145deg, rgba(0,20,40,0.9), rgba(0,10,30,0.95));
129
- border: 3px solid #00ffea;
130
- border-radius: 30px;
131
- padding: 40px;
132
- box-shadow:
133
- 0 0 30px #00ffea,
134
- inset 0 0 30px rgba(0,255,234,0.2);
135
- }
136
- h1 {
137
- text-align: center;
138
- font-size: 3.8em;
139
- color: #00ffea;
140
- text-shadow:
141
- 0 0 10px #00ffea,
142
- 0 0 20px #00ffea,
143
- 0 0 40px #00ffea;
144
- letter-spacing: 4px;
145
- margin-bottom: 20px;
146
- }
147
- p {
148
  text-align: center;
149
- font-size: 1.4em;
150
- color: #00ffea;
151
- text-shadow: 0 0 10px #00ffea;
152
- }
153
- button {
154
- background: linear-gradient(45deg, #ff00ff, #00ffff, #00ff00);
155
- background-size: 300% 300%;
156
- animation: gradient 5s ease infinite;
157
- border: none;
158
- border-radius: 25px;
159
- font-size: 1.6em;
160
- height: 70px;
161
- font-weight: bold;
162
- box-shadow: 0 0 30px #00ffff;
163
- transition: all 0.3s;
164
- }
165
- button:hover {
166
- transform: scale(1.05);
167
- box-shadow: 0 0 50px #00ffff;
168
- }
169
- @keyframes gradient {
170
- 0% { background-position: 0% 50%; }
171
- 50% { background-position: 100% 50%; }
172
- 100% { background-position: 0% 50%; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  }
174
  """
175
 
176
  with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
177
- gr.Markdown("""
178
- # 🚀 YOLOv12s
179
- ### كشف المركبات في الشوارع المصرية بذكاء اصطناعي 🇪🇬
180
- **كل عملية كشف بتترفع تلقائيًا على DagsHub MLflow مع كل التفاصيل**
 
 
181
  """)
182
-
183
- with gr.Row():
 
184
  with gr.Column(scale=1):
185
- gr.Markdown("### 📤 ارفع ملفك")
186
  media = gr.File(
187
- label="صورة أو فيديو",
188
  file_types=[".jpg", ".jpeg", ".png", ".mp4", ".avi"],
189
- height=200
190
  )
 
 
191
  media_type = gr.Radio(
192
  ["Image", "Video"],
193
- label="نوع الميديا",
194
  value="Image",
195
- info="اختار نوع الملف اللي هترفعه"
196
  )
197
- btn = gr.Button("🔥 ابدأ الكشف الآن", variant="primary", size="lg")
198
-
 
 
 
 
 
 
 
 
 
 
 
199
  with gr.Column(scale=2):
200
- gr.Markdown("### 📊 النتيجة")
201
- img_out = gr.Image(label="نتيجة الكشف على الصورة", height=550)
202
- vid_out = gr.Video(label="نتيجة الكشف على الفيديو", height=550)
203
- info = gr.Markdown("**جاهز للكشف... ارفع ملف واضغط ابدأ**")
204
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  btn.click(
206
  fn=run_inference,
207
  inputs=[media, media_type],
208
  outputs=[img_out, vid_out, info]
209
  )
 
 
 
 
 
 
 
210
 
211
  demo.launch()
 
1
  import gradio as gr
2
  import mlflow
3
+ import os
4
+ import time
5
+ import tempfile
6
  from ultralytics import YOLO
7
  from PIL import Image
8
  import cv2
9
  import numpy as np
 
 
 
10
 
11
  # ==============================
12
+ # MLflow Configuration using Secrets
13
  # ==============================
14
  tracking_uri = os.getenv("MLFLOW_TRACKING_URI")
15
  username = os.getenv("MLFLOW_TRACKING_USERNAME")
16
  password = os.getenv("MLFLOW_TRACKING_PASSWORD")
17
 
18
  if not all([tracking_uri, username, password]):
19
+ raise ValueError("MLflow Secrets are not configured! Go to Space Settings → Secrets and verify the names")
20
 
21
  os.environ["MLFLOW_TRACKING_URI"] = tracking_uri
22
  os.environ["MLFLOW_TRACKING_USERNAME"] = username
23
  os.environ["MLFLOW_TRACKING_PASSWORD"] = password
24
 
 
 
 
 
25
  mlflow.set_experiment("YOLOv12s_Inference_Logs")
26
+ print("✅ MLflow configured successfully using secrets!")
 
27
 
28
  # ==============================
29
+ # Load Model
30
  # ==============================
31
+ model = YOLO("Yolo12s.pt")
 
32
 
33
  # ==============================
34
+ # Inference with Full MLflow Tracking
35
  # ==============================
36
  def run_inference(media_file, media_type):
37
  if media_file is None:
38
+ return None, None, "⚠️ Please upload a file first"
39
+
40
  media_path = media_file.name
41
+
42
+ with mlflow.start_run(run_name=f"Inference_{int(time.time())}") as run:
43
  mlflow.log_param("media_type", media_type)
44
+ mlflow.log_param("model", "YOLOv12s")
45
  mlflow.log_param("timestamp", time.strftime("%Y-%m-%d %H:%M:%S"))
46
+
 
 
47
  if media_type == "Image":
48
  img = Image.open(media_path).convert("RGB")
49
  img_array = np.array(img)
 
50
  results = model(img_array)[0]
51
  annotated = results.plot()
52
  output_img = Image.fromarray(annotated[..., ::-1])
53
+
 
54
  with tempfile.TemporaryDirectory() as tmpdir:
55
  in_path = os.path.join(tmpdir, "input.jpg")
56
  out_path = os.path.join(tmpdir, "output.jpg")
57
  img.save(in_path)
58
  output_img.save(out_path)
59
+ mlflow.log_artifact(in_path, artifact_path="input")
60
+ mlflow.log_artifact(out_path, artifact_path="output")
61
+
 
62
  detections = len(results.boxes) if results.boxes is not None else 0
63
+ mlflow.log_metric("detections_count", detections)
64
+
65
+ run_url = f"https://dagshub.com/Mosensei7/AutonomousVehiclesDetectionDEPI/mlflow/#/experiments/{mlflow.get_experiment_by_name('YOLOv12s_Inference_Logs').experiment_id}/runs/{run.info.run_id}"
66
+
67
+ return output_img, None, f"✅ **Detection Complete!**\n\n🔍 **Detections:** {detections}\n🆔 **Run ID:** `{run.info.run_id}`\n\n[📊 View on DagsHub]({run_url})"
68
+
69
  else: # Video
70
  cap = cv2.VideoCapture(media_path)
71
  fps = cap.get(cv2.CAP_PROP_FPS) or 30
72
  w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
73
  h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
74
+
75
  output_video = "output_video.mp4"
76
  writer = cv2.VideoWriter(output_video, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
77
+
78
  frame_count = 0
79
  total_detections = 0
80
+
81
  while cap.isOpened():
82
  ret, frame = cap.read()
83
  if not ret:
84
  break
85
+
86
  results = model(frame)[0]
87
  annotated = results.plot()
88
  writer.write(annotated)
89
+
90
  frame_count += 1
91
  total_detections += len(results.boxes) if results.boxes is not None else 0
92
+
93
  cap.release()
94
  writer.release()
95
+
96
+ mlflow.log_artifact(media_path, artifact_path="input_video")
97
+ mlflow.log_artifact(output_video, artifact_path="output_video")
98
+ mlflow.log_metric("frames_processed", frame_count)
99
  mlflow.log_metric("total_detections", total_detections)
100
+ mlflow.log_metric("avg_detections_per_frame", total_detections / frame_count if frame_count > 0 else 0)
101
+
102
+ run_url = f"https://dagshub.com/Mosensei7/AutonomousVehiclesDetectionDEPI/mlflow/#/experiments/{mlflow.get_experiment_by_name('YOLOv12s_Inference_Logs').experiment_id}/runs/{run.info.run_id}"
103
+
104
+ result_message = f"✅ **Video Processing Complete!**\n\n📹 **Frames:** {frame_count}\n🔍 **Total Detections:** {total_detections}\n📊 **Avg per Frame:** {total_detections / frame_count:.2f}\n🆔 **Run ID:** `{run.info.run_id}`\n\n[📊 View on DagsHub]({run_url})"
105
+
106
  if os.path.exists(output_video):
107
  os.remove(output_video)
108
+
109
+ return None, output_video, result_message
110
 
111
  # ==============================
112
+ # Modern Aesthetic UI
113
  # ==============================
114
  css = """
115
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
116
+
117
+ * {
118
+ font-family: 'Inter', sans-serif;
119
+ }
120
+
121
  body {
122
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
 
 
123
  }
124
+
125
  .gradio-container {
126
+ max-width: 1400px !important;
127
+ margin: 40px auto !important;
128
+ background: rgba(255, 255, 255, 0.95) !important;
129
+ border-radius: 24px !important;
130
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3) !important;
131
+ padding: 0 !important;
132
+ overflow: hidden !important;
133
+ }
134
+
135
+ /* Header Styling */
136
+ .header-container {
137
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
138
+ padding: 48px 40px;
 
 
 
 
 
 
 
 
 
139
  text-align: center;
140
+ border-radius: 24px 24px 0 0;
141
+ }
142
+
143
+ .header-container h1 {
144
+ color: white !important;
145
+ font-size: 2.8em !important;
146
+ font-weight: 700 !important;
147
+ margin: 0 0 12px 0 !important;
148
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
149
+ }
150
+
151
+ .header-container p {
152
+ color: rgba(255, 255, 255, 0.95) !important;
153
+ font-size: 1.1em !important;
154
+ margin: 0 !important;
155
+ }
156
+
157
+ /* Main Content Area */
158
+ .main-content {
159
+ padding: 48px 40px;
160
+ }
161
+
162
+ /* File Upload Area */
163
+ .file-upload-area {
164
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
165
+ border-radius: 16px;
166
+ padding: 32px;
167
+ border: 2px dashed #667eea;
168
+ transition: all 0.3s ease;
169
+ }
170
+
171
+ .file-upload-area:hover {
172
+ border-color: #764ba2;
173
+ transform: translateY(-2px);
174
+ box-shadow: 0 8px 16px rgba(102, 126, 234, 0.2);
175
+ }
176
+
177
+ /* Buttons */
178
+ button.primary {
179
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
180
+ border: none !important;
181
+ color: white !important;
182
+ font-weight: 600 !important;
183
+ font-size: 1.1em !important;
184
+ padding: 16px 48px !important;
185
+ border-radius: 12px !important;
186
+ cursor: pointer !important;
187
+ transition: all 0.3s ease !important;
188
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4) !important;
189
+ }
190
+
191
+ button.primary:hover {
192
+ transform: translateY(-2px) !important;
193
+ box-shadow: 0 8px 20px rgba(102, 126, 234, 0.6) !important;
194
+ }
195
+
196
+ /* Radio Buttons */
197
+ .radio-group label {
198
+ background: white;
199
+ padding: 12px 24px;
200
+ border-radius: 8px;
201
+ border: 2px solid #e5e7eb;
202
+ cursor: pointer;
203
+ transition: all 0.3s ease;
204
+ }
205
+
206
+ .radio-group label:hover {
207
+ border-color: #667eea;
208
+ background: #f5f7fa;
209
+ }
210
+
211
+ /* Output Areas */
212
+ .output-image, .output-video {
213
+ border-radius: 16px;
214
+ overflow: hidden;
215
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
216
+ background: white;
217
+ }
218
+
219
+ /* Info Box */
220
+ .info-box {
221
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
222
+ border-radius: 12px;
223
+ padding: 24px;
224
+ border-left: 4px solid #667eea;
225
+ }
226
+
227
+ /* Custom Scrollbar */
228
+ ::-webkit-scrollbar {
229
+ width: 8px;
230
+ }
231
+
232
+ ::-webkit-scrollbar-track {
233
+ background: #f1f1f1;
234
+ }
235
+
236
+ ::-webkit-scrollbar-thumb {
237
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
238
+ border-radius: 4px;
239
+ }
240
+
241
+ ::-webkit-scrollbar-thumb:hover {
242
+ background: #764ba2;
243
+ }
244
+
245
+ /* Animations */
246
+ @keyframes fadeIn {
247
+ from {
248
+ opacity: 0;
249
+ transform: translateY(20px);
250
+ }
251
+ to {
252
+ opacity: 1;
253
+ transform: translateY(0);
254
+ }
255
+ }
256
+
257
+ .animate-in {
258
+ animation: fadeIn 0.6s ease-out;
259
  }
260
  """
261
 
262
  with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
263
+ # Header
264
+ gr.HTML("""
265
+ <div class="header-container animate-in">
266
+ <h1>🚗 YOLOv12s Vehicle Detection</h1>
267
+ <p>Detect vehicles in Egyptian streets with state-of-the-art AI • All inferences logged to DagsHub MLflow</p>
268
+ </div>
269
  """)
270
+
271
+ with gr.Row(elem_classes="main-content"):
272
+ # Left Column - Input
273
  with gr.Column(scale=1):
274
+ gr.Markdown("### 📁 Upload Media")
275
  media = gr.File(
276
+ label="Drop your image or video here",
277
  file_types=[".jpg", ".jpeg", ".png", ".mp4", ".avi"],
278
+ elem_classes="file-upload-area"
279
  )
280
+
281
+ gr.Markdown("### 🎯 Media Type")
282
  media_type = gr.Radio(
283
  ["Image", "Video"],
284
+ label="Select type",
285
  value="Image",
286
+ elem_classes="radio-group"
287
  )
288
+
289
+ btn = gr.Button("🚀 Run Detection", variant="primary", size="lg", elem_classes="primary")
290
+
291
+ gr.Markdown("""
292
+ ---
293
+ ### 📊 Features
294
+ - Real-time vehicle detection
295
+ - Support for images & videos
296
+ - Auto-logging to DagsHub
297
+ - Detailed metrics tracking
298
+ """)
299
+
300
+ # Right Column - Output
301
  with gr.Column(scale=2):
302
+ gr.Markdown("### 🎬 Detection Results")
303
+
304
+ with gr.Tabs():
305
+ with gr.Tab("📸 Image Output"):
306
+ img_out = gr.Image(
307
+ label="Detected Objects",
308
+ height=500,
309
+ elem_classes="output-image"
310
+ )
311
+
312
+ with gr.Tab("🎥 Video Output"):
313
+ vid_out = gr.Video(
314
+ label="Processed Video",
315
+ height=500,
316
+ elem_classes="output-video"
317
+ )
318
+
319
+ gr.Markdown("### 📈 Run Information")
320
+ info = gr.Markdown(
321
+ "**Ready to detect...** Upload a file and click 'Run Detection' to start!",
322
+ elem_classes="info-box"
323
+ )
324
+
325
+ # Event Handler
326
  btn.click(
327
  fn=run_inference,
328
  inputs=[media, media_type],
329
  outputs=[img_out, vid_out, info]
330
  )
331
+
332
+ # Footer
333
+ gr.HTML("""
334
+ <div style="text-align: center; padding: 32px; color: #6b7280;">
335
+ <p>Powered by YOLOv12s • MLflow Tracking • DagsHub Integration</p>
336
+ </div>
337
+ """)
338
 
339
  demo.launch()