Aumkeshchy2003 commited on
Commit
d87db9b
·
verified ·
1 Parent(s): 98c85aa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +148 -43
app.py CHANGED
@@ -6,6 +6,8 @@ import time
6
  import os
7
  from pathlib import Path
8
  from PIL import Image
 
 
9
 
10
  # Create cache directory for models
11
  os.makedirs("models", exist_ok=True)
@@ -24,12 +26,13 @@ else:
24
  torch.save(model.state_dict(), model_path)
25
 
26
  # Optimize model for speed
27
- model.conf = 0.3
28
- model.iou = 0.3
29
- model.classes = None
 
30
 
31
  if device.type == "cuda":
32
- model.half()
33
  else:
34
  torch.set_num_threads(os.cpu_count())
35
 
@@ -39,6 +42,27 @@ model.eval()
39
  np.random.seed(42)
40
  colors = np.random.randint(0, 255, size=(len(model.names), 3), dtype=np.uint8)
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  def process_video(video_path):
43
  # Check if video_path is None or empty
44
  if video_path is None or video_path == "":
@@ -57,52 +81,131 @@ def process_video(video_path):
57
  frame_height = int(cap.get(4))
58
  fps = cap.get(cv2.CAP_PROP_FPS)
59
 
60
- fourcc = cv2.VideoWriter_fourcc(*'mp4v')
 
61
  output_path = "output_video.mp4"
62
  out = cv2.VideoWriter(output_path, fourcc, fps, (frame_width, frame_height))
63
 
 
 
 
 
 
 
 
 
 
64
  total_frames = 0
65
- total_time = 0
66
-
67
- while cap.isOpened():
68
- ret, frame = cap.read()
69
- if not ret:
70
- break
71
-
72
- start_time = time.time()
73
-
74
- # Convert frame for YOLOv5
75
- img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
76
- results = model(img, size=640)
77
-
78
- inference_time = time.time() - start_time
79
- total_time += inference_time
80
- total_frames += 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
- detections = results.xyxy[0].cpu().numpy()
83
-
84
- for *xyxy, conf, cls in detections:
85
- x1, y1, x2, y2 = map(int, xyxy)
86
- class_id = int(cls)
87
- color = colors[class_id].tolist()
88
- cv2.rectangle(frame, (x1, y1), (x2, y2), color, 3, lineType=cv2.LINE_AA)
89
- label = f"{model.names[class_id]} {conf:.2f}"
90
- cv2.putText(frame, label, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (255, 255, 255), 2)
91
-
92
- # Calculate FPS
93
- avg_fps = total_frames / total_time if total_time > 0 else 0
94
- cv2.putText(frame, f"FPS: {avg_fps:.2f}", (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
95
-
96
- out.write(frame)
97
-
98
- cap.release()
99
- out.release()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
  return output_path
102
 
103
  def process_image(image):
 
 
 
104
  img = np.array(image)
105
- results = model(img, size=640)
 
 
106
 
107
  detections = results.pred[0].cpu().numpy()
108
 
@@ -110,9 +213,10 @@ def process_image(image):
110
  x1, y1, x2, y2 = map(int, xyxy)
111
  class_id = int(cls)
112
  color = colors[class_id].tolist()
113
- cv2.rectangle(img, (x1, y1), (x2, y2), color, 3, lineType=cv2.LINE_AA)
114
  label = f"{model.names[class_id]} {conf:.2f}"
115
- cv2.putText(img, label, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (255, 255, 255), 2)
 
116
 
117
  return Image.fromarray(img)
118
 
@@ -236,4 +340,5 @@ with gr.Blocks(css=css, title="Video & Image Object Detection by YOLOv5") as dem
236
  This application enables seamless object detection using the YOLOv5 model, allowing users to analyze images and videos with high accuracy and efficiency.
237
  """, elem_classes="footer")
238
 
239
- demo.launch()
 
 
6
  import os
7
  from pathlib import Path
8
  from PIL import Image
9
+ from threading import Thread
10
+ from queue import Queue
11
 
12
  # Create cache directory for models
13
  os.makedirs("models", exist_ok=True)
 
26
  torch.save(model.state_dict(), model_path)
27
 
28
  # Optimize model for speed
29
+ model.conf = 0.25 # Slightly lower confidence threshold
30
+ model.iou = 0.45 # Better IoU threshold
31
+ model.classes = None
32
+ model.max_det = 100 # Limit maximum detections
33
 
34
  if device.type == "cuda":
35
+ model.half() # Use FP16 precision
36
  else:
37
  torch.set_num_threads(os.cpu_count())
38
 
 
42
  np.random.seed(42)
43
  colors = np.random.randint(0, 255, size=(len(model.names), 3), dtype=np.uint8)
44
 
45
+ # Async video processing
46
+ def process_frame(model, frame_queue, result_queue):
47
+ while True:
48
+ if frame_queue.empty():
49
+ time.sleep(0.001)
50
+ continue
51
+
52
+ frame_data = frame_queue.get()
53
+ if frame_data is None: # Signal to stop
54
+ result_queue.put(None)
55
+ break
56
+
57
+ frame, frame_index = frame_data
58
+ img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
59
+
60
+ # Use a smaller inference size for speed
61
+ results = model(img, size=384) # Reduced from 640 to 384
62
+
63
+ detections = results.xyxy[0].cpu().numpy()
64
+ result_queue.put((frame, detections, frame_index))
65
+
66
  def process_video(video_path):
67
  # Check if video_path is None or empty
68
  if video_path is None or video_path == "":
 
81
  frame_height = int(cap.get(4))
82
  fps = cap.get(cv2.CAP_PROP_FPS)
83
 
84
+ # Used h264 codec for better performance
85
+ fourcc = cv2.VideoWriter_fourcc(*'avc1')
86
  output_path = "output_video.mp4"
87
  out = cv2.VideoWriter(output_path, fourcc, fps, (frame_width, frame_height))
88
 
89
+ # Created queues for async processing
90
+ frame_queue = Queue(maxsize=10)
91
+ result_queue = Queue()
92
+
93
+ # Start processing thread
94
+ processing_thread = Thread(target=process_frame, args=(model, frame_queue, result_queue))
95
+ processing_thread.daemon = True
96
+ processing_thread.start()
97
+
98
  total_frames = 0
99
+ start_time = time.time()
100
+ processing_started = False
101
+ frames_buffer = {}
102
+ next_frame_to_write = 0
103
+
104
+ try:
105
+ while cap.isOpened():
106
+ ret, frame = cap.read()
107
+ if not ret:
108
+ break
109
+
110
+ if not processing_started:
111
+ processing_started = True
112
+ start_time = time.time()
113
+
114
+ frame_queue.put((frame, total_frames))
115
+ total_frames += 1
116
+
117
+ # Process results if available
118
+ while not result_queue.empty():
119
+ result = result_queue.get()
120
+ if result is None:
121
+ break
122
+
123
+ processed_frame, detections, frame_idx = result
124
+ frames_buffer[frame_idx] = (processed_frame, detections)
125
+
126
+ # Write frames in order
127
+ while next_frame_to_write in frames_buffer:
128
+ buffer_frame, buffer_detections = frames_buffer.pop(next_frame_to_write)
129
+
130
+ # Draw bounding boxes
131
+ for *xyxy, conf, cls in buffer_detections:
132
+ if conf < 0.35: # Additional filtering
133
+ continue
134
+ x1, y1, x2, y2 = map(int, xyxy)
135
+ class_id = int(cls)
136
+ color = colors[class_id].tolist()
137
+ cv2.rectangle(buffer_frame, (x1, y1), (x2, y2), color, 2, lineType=cv2.LINE_AA)
138
+ label = f"{model.names[class_id]} {conf:.2f}"
139
+ # Black text with white outline for better visibility
140
+ cv2.putText(buffer_frame, label, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX,
141
+ 0.7, (0, 0, 0), 2, cv2.LINE_AA)
142
+
143
+ # Calculate elapsed time and FPS
144
+ elapsed = time.time() - start_time
145
+ current_fps = next_frame_to_write / elapsed if elapsed > 0 else 0
146
+
147
+ # Add FPS counter with black text
148
+ cv2.putText(buffer_frame, f"FPS: {current_fps:.2f}", (20, 40),
149
+ cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2, cv2.LINE_AA)
150
+
151
+ out.write(buffer_frame)
152
+ next_frame_to_write += 1
153
+
154
+ # Signal thread to finish and process remaining frames
155
+ frame_queue.put(None)
156
 
157
+ # Process remaining buffered frames
158
+ while True:
159
+ if result_queue.empty():
160
+ time.sleep(0.01)
161
+ continue
162
+
163
+ result = result_queue.get()
164
+ if result is None:
165
+ break
166
+
167
+ processed_frame, detections, frame_idx = result
168
+ frames_buffer[frame_idx] = (processed_frame, detections)
169
+
170
+ # Write remaining frames in order
171
+ while next_frame_to_write in frames_buffer:
172
+ buffer_frame, buffer_detections = frames_buffer.pop(next_frame_to_write)
173
+
174
+ # Draw bounding boxes
175
+ for *xyxy, conf, cls in buffer_detections:
176
+ if conf < 0.35:
177
+ continue
178
+ x1, y1, x2, y2 = map(int, xyxy)
179
+ class_id = int(cls)
180
+ color = colors[class_id].tolist()
181
+ cv2.rectangle(buffer_frame, (x1, y1), (x2, y2), color, 2, lineType=cv2.LINE_AA)
182
+ label = f"{model.names[class_id]} {conf:.2f}"
183
+ cv2.putText(buffer_frame, label, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX,
184
+ 0.7, (0, 0, 0), 2, cv2.LINE_AA)
185
+
186
+ # Add FPS counter
187
+ elapsed = time.time() - start_time
188
+ current_fps = next_frame_to_write / elapsed if elapsed > 0 else 0
189
+ cv2.putText(buffer_frame, f"FPS: {current_fps:.2f}", (20, 40),
190
+ cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2, cv2.LINE_AA)
191
+
192
+ out.write(buffer_frame)
193
+ next_frame_to_write += 1
194
+
195
+ finally:
196
+ cap.release()
197
+ out.release()
198
 
199
  return output_path
200
 
201
  def process_image(image):
202
+ if image is None:
203
+ return None
204
+
205
  img = np.array(image)
206
+
207
+ # Process with smaller size for speed
208
+ results = model(img, size=512)
209
 
210
  detections = results.pred[0].cpu().numpy()
211
 
 
213
  x1, y1, x2, y2 = map(int, xyxy)
214
  class_id = int(cls)
215
  color = colors[class_id].tolist()
216
+ cv2.rectangle(img, (x1, y1), (x2, y2), color, 2, lineType=cv2.LINE_AA)
217
  label = f"{model.names[class_id]} {conf:.2f}"
218
+ # Black text
219
+ cv2.putText(img, label, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0), 2, cv2.LINE_AA)
220
 
221
  return Image.fromarray(img)
222
 
 
340
  This application enables seamless object detection using the YOLOv5 model, allowing users to analyze images and videos with high accuracy and efficiency.
341
  """, elem_classes="footer")
342
 
343
+ if __name__ == "__main__":
344
+ demo.launch()