elon-trump commited on
Commit
f6c1f46
1 Parent(s): be9c91a

Upload 8 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ Screencast[[:space:]]from[[:space:]]25-10-24[[:space:]]04:51:15[[:space:]]PM[[:space:]]IST.webm filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use a Python 3.10 image
2
+ FROM python:3.10-slim
3
+
4
+ # Set the working directory inside the container
5
+ WORKDIR /app
6
+
7
+ # Install system dependencies (needed for OpenCV)
8
+ RUN apt-get update && apt-get install -y \
9
+ libgl1-mesa-glx \
10
+ libglib2.0-0 \
11
+ && rm -rf /var/lib/apt/lists/*
12
+
13
+ # Copy the requirements.txt to install dependencies
14
+ COPY requirements.txt .
15
+
16
+ # Install the Python dependencies
17
+ RUN pip install --no-cache-dir -r requirements.txt
18
+
19
+ # Copy the application code
20
+ COPY . .
21
+
22
+ # Expose the port for Streamlit (default is 8501)
23
+ EXPOSE 8501
24
+
25
+ # Command to run your application (use Streamlit as example)
26
+ CMD ["streamlit", "run", "app.py"]
27
+
Object_Flow_Tracker.py ADDED
@@ -0,0 +1,334 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ from typing import Union, Tuple, List, Dict
4
+ import time
5
+ import os
6
+ from ultralytics import YOLO
7
+ import torch
8
+ import logging
9
+ import sys
10
+ from collections import deque
11
+
12
+ # Configure logging
13
+ logging.basicConfig(
14
+ level=logging.INFO,
15
+ format='%(asctime)s - %(levelname)s - %(message)s',
16
+ stream=sys.stdout
17
+ )
18
+ logger = logging.getLogger(__name__)
19
+
20
+ class YOLOFlowTracker:
21
+ def __init__(self,
22
+ yolo_model_path: str,
23
+ confidence_threshold: float = 0.5,
24
+ window_size: int = 21,
25
+ max_level: int = 3,
26
+ track_len: int = 10,
27
+ grid_size: int = 20): # Grid cell size in pixels
28
+ """Initialize the tracker with detailed error checking."""
29
+ try:
30
+ logger.info("Initializing YOLOFlowTracker...")
31
+
32
+ # Initialize YOLO model
33
+ self.yolo_model = YOLO(yolo_model_path)
34
+ self.conf_threshold = confidence_threshold
35
+
36
+ # Store configuration
37
+ self.window_size = window_size
38
+ self.max_level = max_level
39
+ self.track_len = track_len
40
+ self.grid_size = grid_size
41
+
42
+ # Initialize tracking parameters
43
+ self.lk_params = dict(
44
+ winSize=(window_size, window_size),
45
+ maxLevel=max_level,
46
+ criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 30, 0.01)
47
+ )
48
+
49
+ # Initialize state variables
50
+ self.prev_gray = None
51
+ self.tracks = {}
52
+ self.track_ids = 0
53
+ self.prev_time = time.time()
54
+ self.fps = 0
55
+ self.frame_count = 0
56
+ self.prev_points = None
57
+ self.prev_grid_flow = None
58
+
59
+ # Device information
60
+ self.device = "cuda" if torch.cuda.is_available() else "cpu"
61
+ if self.device == "cuda":
62
+ self.device_name = torch.cuda.get_device_name(0)
63
+ else:
64
+ self.device_name = "CPU"
65
+
66
+ logger.info("YOLOFlowTracker initialized successfully")
67
+
68
+ except Exception as e:
69
+ logger.error(f"Failed to initialize YOLOFlowTracker: {str(e)}")
70
+ raise
71
+
72
+ def detect_objects(self, frame: np.ndarray) -> List[Dict]:
73
+ """Detect objects using YOLO-v8."""
74
+ try:
75
+ results = self.yolo_model(frame, verbose=False)[0]
76
+ detections = []
77
+
78
+ for box in results.boxes:
79
+ x1, y1, x2, y2 = map(int, box.xyxy[0].tolist())
80
+ conf = float(box.conf)
81
+
82
+ if conf > self.conf_threshold:
83
+ detection = {
84
+ 'bbox': (x1, y1, x2, y2),
85
+ 'confidence': conf,
86
+ 'center': (int((x1 + x2) / 2), int((y1 + y2) / 2))
87
+ }
88
+ detections.append(detection)
89
+
90
+ return detections
91
+
92
+ except Exception as e:
93
+ logger.error(f"Error in object detection: {str(e)}")
94
+ return []
95
+
96
+ def create_grid_points(self, bbox: Tuple[int, int, int, int], margin: int = 50) -> np.ndarray:
97
+ """Create a grid of points around the bounding box."""
98
+ x1, y1, x2, y2 = bbox
99
+
100
+ # Add margin around bbox
101
+ x1 = max(0, x1 - margin)
102
+ y1 = max(0, y1 - margin)
103
+ x2 = x2 + margin
104
+ y2 = y2 + margin
105
+
106
+ # Create grid points
107
+ x_points = np.arange(x1, x2, self.grid_size)
108
+ y_points = np.arange(y1, y2, self.grid_size)
109
+
110
+ # Create meshgrid
111
+ xv, yv = np.meshgrid(x_points, y_points)
112
+
113
+ # Reshape to Nx2 array of points
114
+ return np.stack([xv.flatten(), yv.flatten()], axis=1).astype(np.float32)
115
+
116
+ def draw_grid_flow(self, img: np.ndarray, points: np.ndarray,
117
+ next_points: np.ndarray, status: np.ndarray) -> None:
118
+ """Draw grid flow arrows with professional styling."""
119
+ mask = status.flatten() == 1
120
+ points = points[mask]
121
+ next_points = next_points[mask]
122
+
123
+ # Calculate flow vectors
124
+ flow_vectors = next_points - points
125
+
126
+ # Calculate vector magnitudes
127
+ magnitudes = np.linalg.norm(flow_vectors, axis=1)
128
+ max_magnitude = np.max(magnitudes) if magnitudes.size > 0 else 1
129
+
130
+ for pt1, pt2, magnitude in zip(points, next_points, magnitudes):
131
+ # Skip very small movements
132
+ if magnitude < 0.5:
133
+ continue
134
+
135
+ # Normalize magnitude for color intensity
136
+ intensity = min(magnitude / max_magnitude, 1.0)
137
+
138
+ # Create color gradient from blue to yellow based on magnitude
139
+ color = (0,
140
+ int(255 * intensity), # Green component
141
+ int(255 * (1 - intensity))) # Red component
142
+
143
+ # Calculate arrow properties
144
+ angle = np.arctan2(pt2[1] - pt1[1], pt2[0] - pt1[0])
145
+ length = np.sqrt((pt2[0] - pt1[0])**2 + (pt2[1] - pt1[1])**2)
146
+
147
+ # Draw arrow with adaptive size
148
+ arrow_length = min(length, self.grid_size * 0.8)
149
+ arrow_head_size = min(5 + intensity * 5, arrow_length * 0.3)
150
+
151
+ # Calculate end point
152
+ end_pt = (int(pt1[0] + arrow_length * np.cos(angle)),
153
+ int(pt1[1] + arrow_length * np.sin(angle)))
154
+
155
+ # Draw arrow shaft with anti-aliasing
156
+ cv2.line(img, tuple(map(int, pt1)), end_pt, color, 1, cv2.LINE_AA)
157
+
158
+ # Draw arrow head
159
+ arrow_head_angle = np.pi / 6 # 30 degrees
160
+ pt_left = (
161
+ int(end_pt[0] - arrow_head_size * np.cos(angle + arrow_head_angle)),
162
+ int(end_pt[1] - arrow_head_size * np.sin(angle + arrow_head_angle))
163
+ )
164
+ pt_right = (
165
+ int(end_pt[0] - arrow_head_size * np.cos(angle - arrow_head_angle)),
166
+ int(end_pt[1] - arrow_head_size * np.sin(angle - arrow_head_angle))
167
+ )
168
+
169
+ # Draw arrow head with anti-aliasing
170
+ cv2.polylines(img, [np.array([end_pt, pt_left, pt_right])],
171
+ True, color, 1, cv2.LINE_AA)
172
+
173
+ def draw_performance_metrics(self, img: np.ndarray) -> None:
174
+ """Draw FPS and device information on the frame."""
175
+ current_time = time.time()
176
+ self.frame_count += 1
177
+ if current_time - self.prev_time >= 1.0:
178
+ self.fps = self.frame_count
179
+ self.frame_count = 0
180
+ self.prev_time = current_time
181
+
182
+ # Create semi-transparent overlay
183
+ overlay = img.copy()
184
+ cv2.rectangle(overlay, (10, 10), (250, 70), (0, 0, 0), -1)
185
+ cv2.addWeighted(overlay, 0.3, img, 0.7, 0, img)
186
+
187
+ # Draw metrics
188
+ metrics = [
189
+ f"FPS: {self.fps}",
190
+ f"Device: {self.device_name}",
191
+ f"Grid Size: {self.grid_size}px"
192
+ ]
193
+
194
+ for i, text in enumerate(metrics):
195
+ cv2.putText(img, text, (20, 30 + i*20),
196
+ cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
197
+
198
+ def process_frame(self, frame: np.ndarray) -> np.ndarray:
199
+ """Process a single frame with detection and tracking."""
200
+ try:
201
+ if frame is None:
202
+ logger.error("Received empty frame")
203
+ return None
204
+
205
+ # Convert frame to grayscale for optical flow
206
+ gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
207
+ vis = frame.copy()
208
+
209
+ # Initialize previous frame if needed
210
+ if self.prev_gray is None:
211
+ self.prev_gray = gray
212
+ return vis
213
+
214
+ # Detect objects
215
+ detections = self.detect_objects(frame)
216
+
217
+ for det in detections:
218
+ # Draw bounding box
219
+ x1, y1, x2, y2 = det['bbox']
220
+ cv2.rectangle(vis, (x1, y1), (x2, y2), (0, 255, 0), 2)
221
+
222
+ # Create grid points around the detected object
223
+ grid_points = self.create_grid_points(det['bbox'])
224
+
225
+ if grid_points.size > 0:
226
+ # Calculate optical flow for grid points
227
+ next_points, status, _ = cv2.calcOpticalFlowPyrLK(
228
+ self.prev_gray, gray, grid_points,
229
+ None, **self.lk_params
230
+ )
231
+
232
+ if next_points is not None:
233
+ # Draw flow grid
234
+ self.draw_grid_flow(vis, grid_points, next_points, status)
235
+
236
+ # Draw main object motion arrow
237
+ center = det['center']
238
+ mean_flow = np.mean(next_points[status.flatten() == 1] -
239
+ grid_points[status.flatten() == 1], axis=0)
240
+ if not np.isnan(mean_flow).any():
241
+ end_point = (int(center[0] + mean_flow[0] * 2),
242
+ int(center[1] + mean_flow[1] * 2))
243
+ cv2.arrowedLine(vis, center, end_point,
244
+ (0, 255, 255), 3, cv2.LINE_AA, tipLength=0.3)
245
+
246
+ # Draw performance metrics
247
+ self.draw_performance_metrics(vis)
248
+
249
+ # Update previous frame
250
+ self.prev_gray = gray.copy()
251
+
252
+ return vis
253
+
254
+ except Exception as e:
255
+ logger.error(f"Error processing frame: {str(e)}")
256
+ return frame if frame is not None else None
257
+
258
+ def process_video(self, source: Union[str, int], display: bool = True) -> None:
259
+ """Process video stream with detection and tracking."""
260
+ cap = None
261
+ window_name = 'Object Flow Tracking'
262
+
263
+ try:
264
+ logger.info(f"Opening video source: {source}")
265
+ cap = cv2.VideoCapture(source)
266
+
267
+ if not cap.isOpened():
268
+ raise ValueError(f"Failed to open video source: {source}")
269
+
270
+ if display:
271
+ cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
272
+
273
+ while True:
274
+ ret, frame = cap.read()
275
+ if not ret:
276
+ logger.info("End of video stream")
277
+ break
278
+
279
+ processed_frame = self.process_frame(frame)
280
+
281
+ if processed_frame is not None and display:
282
+ try:
283
+ cv2.imshow(window_name, processed_frame)
284
+ if cv2.waitKey(1) & 0xFF == ord('q'):
285
+ logger.info("User requested quit")
286
+ break
287
+ except Exception as e:
288
+ logger.error(f"Error displaying frame: {str(e)}")
289
+
290
+ time.sleep(0.001)
291
+
292
+ except Exception as e:
293
+ logger.error(f"Error in video processing: {str(e)}")
294
+
295
+ finally:
296
+ if cap is not None:
297
+ cap.release()
298
+ if display:
299
+ cv2.destroyAllWindows()
300
+ for _ in range(5):
301
+ cv2.waitKey(1)
302
+
303
+ def main():
304
+ try:
305
+ logger.info("Starting object flow tracking application...")
306
+
307
+ cuda_available = torch.cuda.is_available()
308
+ device = "cuda" if cuda_available else "cpu"
309
+ logger.info(f"Using device: {device}")
310
+
311
+ model_path = "yolov8n.pt"
312
+ if not os.path.exists(model_path):
313
+ logger.error(f"YOLO model not found at: {model_path}")
314
+ return
315
+
316
+ tracker = YOLOFlowTracker(
317
+ yolo_model_path=model_path,
318
+ confidence_threshold=0.5,
319
+ grid_size=20 # Adjust grid density
320
+ )
321
+
322
+ tracker.process_video('Data/2.mp4') # Use camera index 0
323
+
324
+ except KeyboardInterrupt:
325
+ logger.info("Application terminated by user")
326
+ except Exception as e:
327
+ logger.error(f"Application failed: {str(e)}")
328
+ finally:
329
+ cv2.destroyAllWindows()
330
+ for _ in range(5):
331
+ cv2.waitKey(1)
332
+
333
+ if __name__ == "__main__":
334
+ main()
Screencast from 25-10-24 04:51:15 PM IST.webm ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5b9d881f7fce27e02b2face616563a202a9a5f01766e258bb22066b0f0eaf957
3
+ size 21185916
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ streamlit
2
+ opencv-python-headless
3
+ ultralytics
4
+ torch
5
+ numpy==1.23.5
6
+ streamlit-webrtc
runtime.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ python-3.10
yolov8n.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f59b3d833e2ff32e194b5bb8e08d211dc7c5bdf144b90d2c8412c47ccfc83b36
3
+ size 6549796