shimaa22 commited on
Commit
14f9889
·
verified ·
1 Parent(s): c4bb614

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -137
app.py CHANGED
@@ -1,55 +1,27 @@
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
@@ -58,156 +30,127 @@ def process_video(video_file, selected_classes):
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:
70
  break
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=[
202
- gr.Video(label="Upload Video"),
203
- gr.CheckboxGroup(choices=list(class_names.values()), label="Select Classes")
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
- )
212
 
213
  demo.launch()
 
1
  import gradio as gr
2
  import cv2
3
+ import tempfile
4
+ import time
5
  from ultralytics import YOLO
6
  from deep_sort_realtime.deepsort_tracker import DeepSort
 
 
 
7
 
8
  # ======================
9
+ # LOAD MODEL
10
  # ======================
11
+ model = YOLO("best.pt") # يفضل yolov8n
 
 
12
  class_names = model.names
13
 
14
+ tracker = DeepSort(max_age=15)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  # ======================
17
+ # PROCESS VIDEO
18
  # ======================
19
  def process_video(video_file, selected_classes):
20
 
21
  cap = cv2.VideoCapture(video_file)
22
 
23
+ fps = int(cap.get(cv2.CAP_PROP_FPS))
24
+ w, h = 640, 360
 
 
 
25
 
26
  temp_output = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
27
  out_path = temp_output.name
 
30
  out_path,
31
  cv2.VideoWriter_fourcc(*"mp4v"),
32
  fps,
33
+ (w, h)
34
  )
35
 
36
+ frame_id = 0
37
+
38
+ # counters
39
+ total_objects = 0
40
+ active_frames = 0
41
+ inactive_frames = 0
42
+
43
+ start_time = time.time()
44
+
45
  while True:
46
  ret, frame = cap.read()
47
  if not ret:
48
  break
49
 
50
+ frame_id += 1
51
+
52
+ # ⚡ SKIP FRAMES (speed boost)
53
+ if frame_id % 2 != 0:
54
+ continue
55
+
56
+ frame = cv2.resize(frame, (w, h))
57
 
58
  results = model(frame)[0]
59
 
60
  detections = []
61
 
62
+ # map selected classes
63
+ selected_ids = [k for k, v in class_names.items() if v in selected_classes]
64
+
65
  for box in results.boxes:
66
  cls_id = int(box.cls[0])
 
67
 
68
+ if cls_id not in selected_ids:
69
  continue
70
 
71
  x1, y1, x2, y2 = box.xyxy[0].tolist()
72
  conf = float(box.conf[0])
73
 
74
+ detections.append(([x1, y1, x2-x1, y2-y1], conf, cls_id))
75
 
76
  tracks = tracker.update_tracks(detections, frame=frame)
77
 
78
+ active_in_frame = 0
79
+
 
80
  for t in tracks:
81
  if not t.is_confirmed():
82
  continue
83
 
84
+ x1, y1, x2, y2 = map(int, t.to_ltrb())
85
  track_id = t.track_id
 
86
 
87
+ active_in_frame += 1
88
+ total_objects += 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
+ cv2.rectangle(frame, (x1, y1), (x2, y2), (0,255,0), 2)
91
  cv2.putText(frame,
92
+ f"ID {track_id}",
93
+ (x1, y1 - 10),
94
  cv2.FONT_HERSHEY_SIMPLEX,
95
+ 0.5,
96
  (0,255,0),
97
  2)
98
 
99
+ # Active / Inactive logic
100
+ if active_in_frame > 0:
101
+ active_frames += 1
102
+ else:
103
+ inactive_frames += 1
104
+
105
+ cv2.putText(frame,
106
+ f"Objects: {active_in_frame}",
107
+ (10, 30),
108
+ cv2.FONT_HERSHEY_SIMPLEX,
109
+ 0.8,
110
+ (255, 0, 0),
111
+ 2)
112
+
113
  out.write(frame)
114
 
115
  cap.release()
116
  out.release()
117
 
118
+ total_time = time.time() - start_time
 
 
 
 
 
119
 
120
+ summary = f"""
121
+ 🚜 Processing Done!
122
 
123
+ 🔢 Total tracked detections: {total_objects}
124
+ 🟢 Active frames: {active_frames}
125
+ 🔴 Inactive frames: {inactive_frames}
126
+ ⏱ Processing time: {total_time:.2f} sec
127
+ """
128
 
129
+ return out_path, summary
130
 
 
131
 
132
+ # ======================
133
+ # GRADIO UI
134
+ # ======================
135
+ with gr.Blocks() as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
136
 
137
+ gr.Markdown("# 🚜 Excavator Monitoring AI (YOLO + Tracking)")
138
 
139
+ video_input = gr.Video()
140
+ class_selector = gr.CheckboxGroup(
141
+ choices=list(class_names.values()),
142
+ label="Select Classes"
143
+ )
144
 
145
+ btn = gr.Button("Process Video 🚀")
146
 
147
+ output_video = gr.Video()
148
+ output_text = gr.Textbox()
149
 
150
+ btn.click(
151
+ fn=process_video,
152
+ inputs=[video_input, class_selector],
153
+ outputs=[output_video, output_text]
154
+ )
 
 
 
 
 
 
 
 
 
 
 
155
 
156
  demo.launch()