shimaa22 commited on
Commit
c0e04d3
·
verified ·
1 Parent(s): 98c898b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +159 -47
app.py CHANGED
@@ -1,41 +1,69 @@
1
  import gradio as gr
2
  import cv2
3
  from ultralytics import YOLO
 
4
  import tempfile
 
 
5
 
6
- # تحميل الموديل
 
 
7
  model = YOLO("best.pt")
 
8
 
9
- # أسماء الكلاسات
10
  class_names = model.names
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  def process_video(video_file, selected_classes):
13
- cap = cv2.VideoCapture(video_file)
14
 
15
- if not cap.isOpened():
16
- return None, "Error opening video", "", 0, 0
17
 
18
- width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
19
- height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
20
  fps = cap.get(cv2.CAP_PROP_FPS)
21
 
 
 
22
  temp_output = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
23
- output_path = temp_output.name
24
 
25
  out = cv2.VideoWriter(
26
- output_path,
27
- cv2.VideoWriter_fourcc(*'mp4v'),
28
  fps,
29
  (width, height)
30
  )
31
 
32
- total_objects = 0
33
- active_frames = 0
34
- total_frames = 0
35
-
36
- # تحويل أسماء الكلاسات لأرقام
37
- selected_ids = [k for k, v in class_names.items() if v in selected_classes]
38
-
39
  while True:
40
  ret, frame = cap.read()
41
  if not ret:
@@ -43,45 +71,131 @@ def process_video(video_file, selected_classes):
43
 
44
  total_frames += 1
45
 
46
- results = model(frame)
 
 
 
 
 
 
 
 
 
47
 
48
- boxes = results[0].boxes
49
- count_in_frame = 0
50
 
51
- if boxes is not None:
52
- for box in boxes:
53
- cls_id = int(box.cls[0])
54
 
55
- if cls_id in selected_ids:
56
- count_in_frame += 1
57
 
58
- total_objects += count_in_frame
 
 
 
 
 
59
 
60
- # active لو فيه object
61
- if count_in_frame > 0:
62
- active_frames += 1
63
 
64
- # رسم النتائج (فلترة)
65
- annotated_frame = results[0].plot()
66
 
67
- out.write(annotated_frame)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
  cap.release()
70
  out.release()
71
 
72
- # حساب الزمن
73
- active_time = active_frames / fps
74
- inactive_time = (total_frames - active_frames) / fps
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
- summary = f"""
77
- 📊 Total Objects Detected: {total_objects}
78
- ⏱️ Active Time: {active_time:.2f} sec
79
- 💤 Inactive Time: {inactive_time:.2f} sec
80
- """
81
 
82
- return output_path, summary, output_path, active_time, inactive_time
83
 
84
 
 
 
 
85
  demo = gr.Interface(
86
  fn=process_video,
87
  inputs=[
@@ -90,13 +204,11 @@ demo = gr.Interface(
90
  ],
91
  outputs=[
92
  gr.Video(label="Processed Video"),
93
- gr.Textbox(label="Summary"),
94
- gr.File(label="Download Video"),
95
- gr.Number(label="Active Time (sec)"),
96
- gr.Number(label="Inactive Time (sec)")
97
  ],
98
- title="YOLO Smart Video Analyzer 🎯🔥",
99
- description="ارفع فيديو + اختار الكلاسات، وهيطلعلك تحليل كامل"
100
  )
101
 
102
  demo.launch()
 
1
  import gradio as gr
2
  import cv2
3
  from ultralytics import YOLO
4
+ from deep_sort_realtime.deepsort_tracker import DeepSort
5
  import tempfile
6
+ import numpy as np
7
+ import json
8
 
9
+ # ======================
10
+ # MODELS
11
+ # ======================
12
  model = YOLO("best.pt")
13
+ tracker = DeepSort(max_age=30)
14
 
 
15
  class_names = model.names
16
 
17
+ # نخزن history لكل ماكينة
18
+ track_memory = {}
19
+ track_stats = {}
20
+
21
+ # ======================
22
+ # ACTIVITY CLASSIFIER
23
+ # ======================
24
+ def classify_activity(dx, dy, speed):
25
+
26
+ if speed < 1.2:
27
+ return "WAITING"
28
+
29
+ if abs(dy) > abs(dx) and dy > 2:
30
+ return "DIGGING"
31
+
32
+ if abs(dx) > 3:
33
+ return "SWINGING"
34
+
35
+ if speed > 7:
36
+ return "DUMPING"
37
+
38
+ return "ACTIVE"
39
+
40
+
41
+ # ======================
42
+ # MAIN FUNCTION
43
+ # ======================
44
  def process_video(video_file, selected_classes):
 
45
 
46
+ cap = cv2.VideoCapture(video_file)
 
47
 
48
+ width = int(cap.get(3))
49
+ height = int(cap.get(4))
50
  fps = cap.get(cv2.CAP_PROP_FPS)
51
 
52
+ total_frames = 0
53
+
54
  temp_output = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
55
+ out_path = temp_output.name
56
 
57
  out = cv2.VideoWriter(
58
+ out_path,
59
+ cv2.VideoWriter_fourcc(*"mp4v"),
60
  fps,
61
  (width, height)
62
  )
63
 
64
+ # ======================
65
+ # VIDEO LOOP
66
+ # ======================
 
 
 
 
67
  while True:
68
  ret, frame = cap.read()
69
  if not ret:
 
71
 
72
  total_frames += 1
73
 
74
+ results = model(frame)[0]
75
+
76
+ detections = []
77
+
78
+ for box in results.boxes:
79
+ cls_id = int(box.cls[0])
80
+ cls_name = class_names[cls_id].lower()
81
+
82
+ if cls_name not in [c.lower() for c in selected_classes]:
83
+ continue
84
 
85
+ x1, y1, x2, y2 = box.xyxy[0].tolist()
86
+ conf = float(box.conf[0])
87
 
88
+ detections.append(([x1, y1, x2-x1, y2-y1], conf, cls_name))
 
 
89
 
90
+ tracks = tracker.update_tracks(detections, frame=frame)
 
91
 
92
+ # ======================
93
+ # TRACK PROCESSING
94
+ # ======================
95
+ for t in tracks:
96
+ if not t.is_confirmed():
97
+ continue
98
 
99
+ track_id = t.track_id
100
+ x1, y1, x2, y2 = t.to_ltrb()
 
101
 
102
+ cx = (x1 + x2) / 2
103
+ cy = (y1 + y2) / 2
104
 
105
+ timestamp_sec = total_frames / fps
106
+ timestamp = f"00:00:{timestamp_sec:06.3f}"
107
+
108
+ # init
109
+ if track_id not in track_memory:
110
+ track_memory[track_id] = (cx, cy)
111
+ track_stats[track_id] = {
112
+ "active": 0,
113
+ "idle": 0,
114
+ "activity_log": []
115
+ }
116
+
117
+ px, py = track_memory[track_id]
118
+
119
+ dx = cx - px
120
+ dy = cy - py
121
+ speed = np.sqrt(dx**2 + dy**2)
122
+
123
+ activity = classify_activity(dx, dy, speed)
124
+
125
+ # ACTIVE vs IDLE
126
+ if activity == "WAITING":
127
+ state = "IDLE"
128
+ track_stats[track_id]["idle"] += 1
129
+ else:
130
+ state = "ACTIVE"
131
+ track_stats[track_id]["active"] += 1
132
+
133
+ track_stats[track_id]["activity_log"].append(activity)
134
+
135
+ track_memory[track_id] = (cx, cy)
136
+
137
+ # ======================
138
+ # DRAW
139
+ # ======================
140
+ cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0,255,0), 2)
141
+
142
+ cv2.putText(frame,
143
+ f"ID:{track_id} {activity}",
144
+ (int(x1), int(y1)-10),
145
+ cv2.FONT_HERSHEY_SIMPLEX,
146
+ 0.6,
147
+ (0,255,0),
148
+ 2)
149
+
150
+ out.write(frame)
151
 
152
  cap.release()
153
  out.release()
154
 
155
+ # ======================
156
+ # BUILD JSON OUTPUT
157
+ # ======================
158
+ results_json = []
159
+
160
+ for track_id, data in track_stats.items():
161
+
162
+ total = data["active"] + data["idle"]
163
+
164
+ active_sec = data["active"] / fps
165
+ idle_sec = data["idle"] / fps
166
+
167
+ utilization = (active_sec / (active_sec + idle_sec + 1e-6)) * 100
168
+
169
+ main_activity = max(set(data["activity_log"]), key=data["activity_log"].count)
170
+
171
+ equipment_json = {
172
+ "frame_id": total_frames,
173
+ "equipment_id": f"EX-{track_id:03d}",
174
+ "equipment_class": "excavator",
175
+ "timestamp": f"00:00:{total_frames / fps:06.3f}",
176
+ "utilization": {
177
+ "current_state": "ACTIVE" if active_sec > idle_sec else "IDLE",
178
+ "current_activity": main_activity,
179
+ "motion_source": "arm_and_body_motion"
180
+ },
181
+ "time_analytics": {
182
+ "total_tracked_seconds": round(total / fps, 2),
183
+ "total_active_seconds": round(active_sec, 2),
184
+ "total_idle_seconds": round(idle_sec, 2),
185
+ "utilization_percent": round(utilization, 2)
186
+ }
187
+ }
188
+
189
+ results_json.append(equipment_json)
190
 
191
+ json_output = json.dumps(results_json, indent=2)
 
 
 
 
192
 
193
+ return out_path, json_output, out_path
194
 
195
 
196
+ # ======================
197
+ # GRADIO UI
198
+ # ======================
199
  demo = gr.Interface(
200
  fn=process_video,
201
  inputs=[
 
204
  ],
205
  outputs=[
206
  gr.Video(label="Processed Video"),
207
+ gr.Textbox(label="JSON Output"),
208
+ gr.File(label="Download Video")
 
 
209
  ],
210
+ title="Smart Excavator Analytics"
211
+ description="YOLO + Tracking + Activity + Utilization JSON"
212
  )
213
 
214
  demo.launch()