mkhodary101 commited on
Commit
aca5f43
Β·
verified Β·
1 Parent(s): 7ef0fcc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -114
app.py CHANGED
@@ -5,25 +5,22 @@ import numpy as np
5
  import time
6
  from ultralytics import YOLO
7
  import spaces
8
-
9
- @spaces.GPU
10
 
11
  class CrowdDetection:
12
  def __init__(self, model_path="yolov8n.pt"):
13
- """Initialize the YOLO model once to avoid PicklingError."""
14
  self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
15
  if not os.path.exists(model_path):
16
- # Download the model if not present
17
- from ultralytics import YOLO
18
- self.model = YOLO("yolov8n.pt") # This downloads the model automatically
19
- self.model.save(model_path) # Save locally
20
  else:
21
  self.model = YOLO(model_path)
22
  self.model.to(self.device)
23
 
24
  @spaces.GPU
25
  def detect_crowd(self, video_path):
26
- """Process video using YOLOv8 for crowd detection."""
27
  cap = cv2.VideoCapture(video_path)
28
  if not cap.isOpened():
29
  raise ValueError(f"❌ Failed to open video: {video_path}")
@@ -35,10 +32,9 @@ class CrowdDetection:
35
  output_path = "output_crowd.mp4"
36
  fourcc = cv2.VideoWriter_fourcc(*"mp4v")
37
  out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
38
-
39
  if not out.isOpened():
40
  cap.release()
41
- raise ValueError(f"❌ Failed to initialize video writer for {output_path}")
42
 
43
  CROWD_THRESHOLD = 10
44
  frame_count = 0
@@ -46,146 +42,125 @@ class CrowdDetection:
46
  while cap.isOpened():
47
  ret, frame = cap.read()
48
  if not ret:
49
- break # End of video
50
-
51
  frame_count += 1
52
 
53
- # Run YOLO inference on the frame
54
  results = self.model(frame)
 
55
 
56
- # Count detected persons
57
- person_count = sum(
58
- 1 for result in results
59
- for cls in result.boxes.cls.cpu().numpy() if int(cls) == 0
60
- )
61
-
62
- # Draw bounding boxes
63
  for result in results:
64
  boxes = result.boxes.xyxy.cpu().numpy()
65
  classes = result.boxes.cls.cpu().numpy()
66
-
67
  for box, cls in zip(boxes, classes):
68
  if int(cls) == 0: # Person class
69
  x1, y1, x2, y2 = map(int, box)
70
  cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
71
- cv2.putText(frame, "Person", (x1, y1 - 10),
72
- cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
73
 
74
- # Display count on frame
75
  alert_text = "Crowd Alert!" if person_count > CROWD_THRESHOLD else f"People: {person_count}"
76
  cv2.putText(frame, alert_text, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1,
77
  (0, 0, 255) if person_count > CROWD_THRESHOLD else (0, 255, 0), 2)
78
-
79
  out.write(frame)
80
 
81
  cap.release()
82
  out.release()
83
-
84
- if frame_count == 0:
85
- raise ValueError("❌ No frames were processed!")
86
-
87
- if not os.path.exists(output_path):
88
- raise FileNotFoundError(f"❌ Output video not found: {output_path}")
89
-
90
  return output_path
91
 
92
- # Define Gradio interface function
93
- def process_video(video):
94
- try:
95
- detector = CrowdDetection() # Instantiate inside to avoid pickling
96
- output_path = detector.detect_crowd(video)
97
- return "Crowd detection complete!", output_path
98
- except Exception as e:
99
- return f"Error: {str(e)}", None
100
-
101
- # Create Gradio interface
102
- with gr.Blocks() as demo:
103
- gr.Markdown("# Crowd Detection with YOLOv8")
104
- gr.Markdown("Upload a video to detect people and get crowd alerts (threshold: 10 people)")
105
-
106
- with gr.Row():
107
- with gr.Column():
108
- video_input = gr.Video(label="Upload Video")
109
- submit_btn = gr.Button("Detect Crowd")
110
- with gr.Column():
111
- status_output = gr.Textbox(label="Status")
112
- video_output = gr.Video(label="Result")
113
-
114
- submit_btn.click(
115
- fn=process_video,
116
- inputs=[video_input],
117
- outputs=[status_output, video_output]
118
- )
119
-
120
- demo.launch(debug=True)
121
-
122
-
123
  class PeopleTracking:
124
  def __init__(self, yolo_model_path="yolov8n.pt"):
125
  self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
126
- self.model = YOLO(yolo_model_path).to(self.device)
127
-
 
 
 
 
 
 
128
  def track_people(self, video_path):
129
  cap = cv2.VideoCapture(video_path)
 
 
 
 
 
 
130
  output_path = "output_tracking.mp4"
131
- fourcc = cv2.VideoWriter_fourcc(*"mp4v")
132
- out = cv2.VideoWriter(output_path, fourcc, int(cap.get(cv2.CAP_PROP_FPS)),
133
- (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))))
134
-
 
135
  while cap.isOpened():
136
  ret, frame = cap.read()
137
  if not ret:
138
  break
139
-
140
  results = self.model.track(frame, persist=True)
141
  for result in results:
142
  boxes = result.boxes.xyxy.cpu().numpy()
143
  classes = result.boxes.cls.cpu().numpy()
144
- ids = result.boxes.id.cpu().numpy() if hasattr(result.boxes, "id") else np.arange(len(boxes))
145
-
146
  for box, cls, obj_id in zip(boxes, classes, ids):
147
  if int(cls) == 0:
148
  x1, y1, x2, y2 = map(int, box)
149
  cv2.rectangle(frame, (x1, y1), (x2, y2), (255, 0, 0), 2)
150
- cv2.putText(frame, f"ID {int(obj_id)}", (x1, y1 - 10),
151
- cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
152
-
153
  out.write(frame)
154
-
155
  cap.release()
156
  out.release()
 
 
157
  return output_path
158
 
159
- # Define Fall Detection
160
  class FallDetection:
161
  def __init__(self, yolo_model_path="yolov8l.pt"):
162
- self.model = YOLO(yolo_model_path)
163
-
 
 
 
 
 
 
 
164
  def detect_fall(self, video_path):
165
  cap = cv2.VideoCapture(video_path)
 
 
 
 
 
 
166
  output_path = "output_fall.mp4"
167
- fourcc = cv2.VideoWriter_fourcc(*"mp4v")
168
- out = cv2.VideoWriter(output_path, fourcc, int(cap.get(cv2.CAP_PROP_FPS)),
169
- (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))))
170
-
 
171
  while cap.isOpened():
172
  ret, frame = cap.read()
173
  if not ret:
174
  break
175
-
176
  results = self.model(frame)
177
  for result in results:
178
  boxes = result.boxes.xyxy.cpu().numpy()
179
  classes = result.boxes.cls.cpu().numpy()
180
-
181
  for box, cls in zip(boxes, classes):
182
  if int(cls) == 0:
183
  x1, y1, x2, y2 = map(int, box)
184
  width = x2 - x1
185
  height = y2 - y1
186
- aspect_ratio = width / height
187
-
188
- if aspect_ratio > 0.55:
189
  color = (0, 0, 255)
190
  label = "FALL DETECTED"
191
  else:
@@ -194,49 +169,77 @@ class FallDetection:
194
 
195
  cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2)
196
  cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
197
-
198
  out.write(frame)
199
-
200
  cap.release()
201
  out.release()
 
 
202
  return output_path
203
 
204
- # Define Fight Detection
205
  class FightDetection:
206
  def __init__(self, yolo_model_path="yolov8n-pose.pt"):
207
- self.model = YOLO(yolo_model_path).to(torch.device("cuda" if torch.cuda.is_available() else "cpu"))
208
-
 
 
 
 
 
 
 
209
  def detect_fight(self, video_path):
210
  cap = cv2.VideoCapture(video_path)
 
 
 
 
 
 
211
  output_path = "output_fight.mp4"
212
- fourcc = cv2.VideoWriter_fourcc(*"mp4v")
213
- out = cv2.VideoWriter(output_path, fourcc, int(cap.get(cv2.CAP_PROP_FPS)),
214
- (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))))
215
-
 
216
  while cap.isOpened():
217
  ret, frame = cap.read()
218
  if not ret:
219
  break
220
-
221
  results = self.model.track(frame, persist=True)
 
 
 
222
  for result in results:
223
  keypoints = result.keypoints.xy.cpu().numpy() if result.keypoints else []
 
224
  classes = result.boxes.cls.cpu().numpy() if result.boxes else []
225
-
226
- for kp, cls in zip(keypoints, classes):
227
  if int(cls) == 0:
228
- x1, y1 = int(kp[0][0]), int(kp[0][1])
229
- x2, y2 = int(kp[-1][0]), int(kp[-1][1])
230
- cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 2)
231
- cv2.putText(frame, "FIGHT DETECTED", (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
232
-
 
 
 
 
 
 
 
233
  out.write(frame)
234
-
235
  cap.release()
236
  out.release()
 
 
237
  return output_path
238
 
239
- # Function to process video based on selected feature
240
  def process_video(feature, video):
241
  detectors = {
242
  "Crowd Detection": CrowdDetection,
@@ -244,10 +247,13 @@ def process_video(feature, video):
244
  "Fall Detection": FallDetection,
245
  "Fight Detection": FightDetection
246
  }
247
-
248
- detector = detectors[feature]()
249
- method_name = f"detect_{feature.lower().replace(' ', '_')}"
250
- return getattr(detector, method_name)(video)
 
 
 
251
 
252
  # Gradio Interface
253
  interface = gr.Interface(
@@ -257,9 +263,9 @@ interface = gr.Interface(
257
  gr.Video(label="Upload Video")
258
  ],
259
  outputs=gr.Video(label="Processed Video"),
260
- title="YOLOv8 Multitask Video Processing"
 
261
  )
262
 
263
  if __name__ == "__main__":
264
- interface.launch(debug=True)
265
-
 
5
  import time
6
  from ultralytics import YOLO
7
  import spaces
8
+ import os
 
9
 
10
  class CrowdDetection:
11
  def __init__(self, model_path="yolov8n.pt"):
12
+ """Initialize the YOLO model once."""
13
  self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
14
  if not os.path.exists(model_path):
15
+ self.model = YOLO("yolov8n.pt") # Downloads if not present
16
+ self.model.save(model_path)
 
 
17
  else:
18
  self.model = YOLO(model_path)
19
  self.model.to(self.device)
20
 
21
  @spaces.GPU
22
  def detect_crowd(self, video_path):
23
+ """Process video for crowd detection."""
24
  cap = cv2.VideoCapture(video_path)
25
  if not cap.isOpened():
26
  raise ValueError(f"❌ Failed to open video: {video_path}")
 
32
  output_path = "output_crowd.mp4"
33
  fourcc = cv2.VideoWriter_fourcc(*"mp4v")
34
  out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
 
35
  if not out.isOpened():
36
  cap.release()
37
+ raise ValueError(f"❌ Failed to initialize video writer")
38
 
39
  CROWD_THRESHOLD = 10
40
  frame_count = 0
 
42
  while cap.isOpened():
43
  ret, frame = cap.read()
44
  if not ret:
45
+ break
 
46
  frame_count += 1
47
 
 
48
  results = self.model(frame)
49
+ person_count = sum(1 for result in results for cls in result.boxes.cls.cpu().numpy() if int(cls) == 0)
50
 
 
 
 
 
 
 
 
51
  for result in results:
52
  boxes = result.boxes.xyxy.cpu().numpy()
53
  classes = result.boxes.cls.cpu().numpy()
 
54
  for box, cls in zip(boxes, classes):
55
  if int(cls) == 0: # Person class
56
  x1, y1, x2, y2 = map(int, box)
57
  cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
58
+ cv2.putText(frame, "Person", (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
 
59
 
 
60
  alert_text = "Crowd Alert!" if person_count > CROWD_THRESHOLD else f"People: {person_count}"
61
  cv2.putText(frame, alert_text, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1,
62
  (0, 0, 255) if person_count > CROWD_THRESHOLD else (0, 255, 0), 2)
 
63
  out.write(frame)
64
 
65
  cap.release()
66
  out.release()
67
+ if frame_count == 0 or not os.path.exists(output_path):
68
+ raise ValueError("❌ Processing failed")
 
 
 
 
 
69
  return output_path
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  class PeopleTracking:
72
  def __init__(self, yolo_model_path="yolov8n.pt"):
73
  self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
74
+ if not os.path.exists(yolo_model_path):
75
+ self.model = YOLO("yolov8n.pt")
76
+ self.model.save(yolo_model_path)
77
+ else:
78
+ self.model = YOLO(yolo_model_path)
79
+ self.model.to(self.device)
80
+
81
+ @spaces.GPU
82
  def track_people(self, video_path):
83
  cap = cv2.VideoCapture(video_path)
84
+ if not cap.isOpened():
85
+ raise ValueError(f"❌ Failed to open video: {video_path}")
86
+
87
+ fps = int(cap.get(cv2.CAP_PROP_FPS))
88
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
89
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
90
  output_path = "output_tracking.mp4"
91
+ out = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height))
92
+ if not out.isOpened():
93
+ cap.release()
94
+ raise ValueError(f"❌ Failed to initialize video writer")
95
+
96
  while cap.isOpened():
97
  ret, frame = cap.read()
98
  if not ret:
99
  break
100
+
101
  results = self.model.track(frame, persist=True)
102
  for result in results:
103
  boxes = result.boxes.xyxy.cpu().numpy()
104
  classes = result.boxes.cls.cpu().numpy()
105
+ ids = result.boxes.id.cpu().numpy() if result.boxes.id is not None else np.arange(len(boxes))
106
+
107
  for box, cls, obj_id in zip(boxes, classes, ids):
108
  if int(cls) == 0:
109
  x1, y1, x2, y2 = map(int, box)
110
  cv2.rectangle(frame, (x1, y1), (x2, y2), (255, 0, 0), 2)
111
+ cv2.putText(frame, f"ID {int(obj_id)}", (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
112
+
 
113
  out.write(frame)
114
+
115
  cap.release()
116
  out.release()
117
+ if not os.path.exists(output_path):
118
+ raise ValueError("❌ Processing failed")
119
  return output_path
120
 
 
121
  class FallDetection:
122
  def __init__(self, yolo_model_path="yolov8l.pt"):
123
+ self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
124
+ if not os.path.exists(yolo_model_path):
125
+ self.model = YOLO("yolov8l.pt")
126
+ self.model.save(yolo_model_path)
127
+ else:
128
+ self.model = YOLO(yolo_model_path)
129
+ self.model.to(self.device)
130
+
131
+ @spaces.GPU
132
  def detect_fall(self, video_path):
133
  cap = cv2.VideoCapture(video_path)
134
+ if not cap.isOpened():
135
+ raise ValueError(f"❌ Failed to open video: {video_path}")
136
+
137
+ fps = int(cap.get(cv2.CAP_PROP_FPS))
138
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
139
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
140
  output_path = "output_fall.mp4"
141
+ out = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height))
142
+ if not out.isOpened():
143
+ cap.release()
144
+ raise ValueError(f"❌ Failed to initialize video writer")
145
+
146
  while cap.isOpened():
147
  ret, frame = cap.read()
148
  if not ret:
149
  break
150
+
151
  results = self.model(frame)
152
  for result in results:
153
  boxes = result.boxes.xyxy.cpu().numpy()
154
  classes = result.boxes.cls.cpu().numpy()
155
+
156
  for box, cls in zip(boxes, classes):
157
  if int(cls) == 0:
158
  x1, y1, x2, y2 = map(int, box)
159
  width = x2 - x1
160
  height = y2 - y1
161
+ aspect_ratio = width / height if height > 0 else float('inf')
162
+
163
+ if aspect_ratio > 0.55: # Person lying down
164
  color = (0, 0, 255)
165
  label = "FALL DETECTED"
166
  else:
 
169
 
170
  cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2)
171
  cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
172
+
173
  out.write(frame)
174
+
175
  cap.release()
176
  out.release()
177
+ if not os.path.exists(output_path):
178
+ raise ValueError("❌ Processing failed")
179
  return output_path
180
 
 
181
  class FightDetection:
182
  def __init__(self, yolo_model_path="yolov8n-pose.pt"):
183
+ self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
184
+ if not os.path.exists(yolo_model_path):
185
+ self.model = YOLO("yolov8n-pose.pt")
186
+ self.model.save(yolo_model_path)
187
+ else:
188
+ self.model = YOLO(yolo_model_path)
189
+ self.model.to(self.device)
190
+
191
+ @spaces.GPU
192
  def detect_fight(self, video_path):
193
  cap = cv2.VideoCapture(video_path)
194
+ if not cap.isOpened():
195
+ raise ValueError(f"❌ Failed to open video: {video_path}")
196
+
197
+ fps = int(cap.get(cv2.CAP_PROP_FPS))
198
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
199
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
200
  output_path = "output_fight.mp4"
201
+ out = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height))
202
+ if not out.isOpened():
203
+ cap.release()
204
+ raise ValueError(f"❌ Failed to initialize video writer")
205
+
206
  while cap.isOpened():
207
  ret, frame = cap.read()
208
  if not ret:
209
  break
210
+
211
  results = self.model.track(frame, persist=True)
212
+ fight_detected = False
213
+ person_count = 0
214
+
215
  for result in results:
216
  keypoints = result.keypoints.xy.cpu().numpy() if result.keypoints else []
217
+ boxes = result.boxes.xyxy.cpu().numpy() if result.boxes else []
218
  classes = result.boxes.cls.cpu().numpy() if result.boxes else []
219
+
220
+ for box, kp, cls in zip(boxes, keypoints, classes):
221
  if int(cls) == 0:
222
+ person_count += 1
223
+ x1, y1, x2, y2 = map(int, box)
224
+ # Simple fight detection: check if arms (keypoints 5, 7) are raised high
225
+ if len(kp) > 7 and (kp[5][1] < y1 + (y2 - y1) * 0.3 or kp[7][1] < y1 + (y2 - y1) * 0.3):
226
+ fight_detected = True
227
+ cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255) if fight_detected else (0, 255, 0), 2)
228
+ label = "FIGHT DETECTED" if fight_detected else "Person"
229
+ cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
230
+ (0, 0, 255) if fight_detected else (0, 255, 0), 2)
231
+
232
+ if fight_detected and person_count > 1:
233
+ cv2.putText(frame, "FIGHT ALERT!", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
234
  out.write(frame)
235
+
236
  cap.release()
237
  out.release()
238
+ if not os.path.exists(output_path):
239
+ raise ValueError("❌ Processing failed")
240
  return output_path
241
 
242
+ # Unified processing function
243
  def process_video(feature, video):
244
  detectors = {
245
  "Crowd Detection": CrowdDetection,
 
247
  "Fall Detection": FallDetection,
248
  "Fight Detection": FightDetection
249
  }
250
+ try:
251
+ detector = detectors[feature]()
252
+ method_name = feature.lower().replace(" ", "_") # Match method names exactly
253
+ output_path = getattr(detector, method_name)(video)
254
+ return output_path
255
+ except Exception as e:
256
+ raise ValueError(f"Error processing video: {str(e)}")
257
 
258
  # Gradio Interface
259
  interface = gr.Interface(
 
263
  gr.Video(label="Upload Video")
264
  ],
265
  outputs=gr.Video(label="Processed Video"),
266
+ title="YOLOv8 Multitask Video Processing",
267
+ description="Select a feature to process your video: Crowd Detection, People Tracking, Fall Detection, or Fight Detection."
268
  )
269
 
270
  if __name__ == "__main__":
271
+ interface.launch(debug=True)