Download src/analytics.py from Abhisingh-18/Crowd-Intelligence: direct link, hf CLI and curl.
- Browser
- Download file 4.22 kB
-
https://huggingface.co/Abhisingh-18/Crowd-Intelligence/resolve/main/src/analytics.py
- Command line
-
hf download hf://Abhisingh-18/Crowd-Intelligence/src/analytics.py
-
curl -L -o analytics.py https://huggingface.co/Abhisingh-18/Crowd-Intelligence/resolve/main/src/analytics.py
4.22 kB
| import numpy as np | |
| from scipy.ndimage import gaussian_filter | |
| import pandas as pd | |
| class AnalyticsEngine: | |
| def __init__(self, fps=30, width=1920, height=1080): | |
| self.fps = fps | |
| self.width = width | |
| self.height = height | |
| # tracks = { id: [(x, y, frame_number), ...] } | |
| self.tracks = {} | |
| # density_over_time = { frame_number: count } | |
| self.density_over_time = {} | |
| # heatmap_accumulator: 2D array to store visits | |
| self.heatmap_grid = np.zeros((height // 10, width // 10)) | |
| def update_tracks(self, results, frame_number): | |
| """ | |
| Updates the tracks dictionary with new detections. | |
| """ | |
| if results.boxes is None or results.boxes.id is None: | |
| self.density_over_time[frame_number] = 0 | |
| return | |
| ids = results.boxes.id.cpu().numpy().astype(int) | |
| boxes = results.boxes.xywh.cpu().numpy() # x, y, w, h (center coordinates) | |
| self.density_over_time[frame_number] = len(ids) | |
| for track_id, box in zip(ids, boxes): | |
| x, y, w, h = box | |
| if track_id not in self.tracks: | |
| self.tracks[track_id] = [] | |
| self.tracks[track_id].append((x, y, frame_number)) | |
| # Update heatmap grid (downsampled) | |
| grid_x = min(int(x / 10), (self.width // 10) - 1) | |
| grid_y = min(int(y / 10), (self.height // 10) - 1) | |
| self.heatmap_grid[grid_y, grid_x] += 1 | |
| def get_unique_count(self): | |
| return len(self.tracks) | |
| def calculate_dwell_times(self): | |
| dwell_times = {} | |
| for track_id, trajectory in self.tracks.items(): | |
| if len(trajectory) < 2: | |
| continue | |
| first_frame = trajectory[0][2] | |
| last_frame = trajectory[-1][2] | |
| dwell_seconds = (last_frame - first_frame) / self.fps | |
| dwell_times[track_id] = dwell_seconds | |
| return dwell_times | |
| def classify_direction(self, trajectory): | |
| """ | |
| Classifies direction based on first and last points. | |
| """ | |
| if len(trajectory) < 2: | |
| return "Unknown" | |
| start_x, start_y, _ = trajectory[0] | |
| end_x, end_y, _ = trajectory[-1] | |
| dx = end_x - start_x | |
| dy = end_y - start_y | |
| if abs(dx) > abs(dy): | |
| return "Left -> Right" if dx > 0 else "Right -> Left" | |
| else: | |
| return "Top -> Bottom" if dy > 0 else "Bottom -> Top" | |
| def get_direction_distribution(self): | |
| directions = {"Left -> Right": 0, "Right -> Left": 0, "Top -> Bottom": 0, "Bottom -> Top": 0, "Unknown": 0} | |
| for track_id, trajectory in self.tracks.items(): | |
| dir_label = self.classify_direction(trajectory) | |
| directions[dir_label] += 1 | |
| return directions | |
| def get_heatmap(self, sigma=5): | |
| """ | |
| Returns a smoothed heatmap. | |
| """ | |
| smoothed = gaussian_filter(self.heatmap_grid, sigma=sigma) | |
| # Normalize | |
| if np.max(smoothed) > 0: | |
| smoothed = (smoothed / np.max(smoothed)) * 255 | |
| return smoothed.astype(np.uint8) | |
| def get_density_df(self): | |
| """ | |
| Returns density over time as a Pandas DataFrame. | |
| """ | |
| df = pd.DataFrame(list(self.density_over_time.items()), columns=['Frame', 'Count']) | |
| df['Time (s)'] = df['Frame'] / self.fps | |
| return df | |
| def check_roi_crossing(self, roi_polygon): | |
| """ | |
| Checks how many unique IDs crossed or entered a specific ROI. | |
| roi_polygon: List of (x, y) coordinates. | |
| Simple implementation: center point inside polygon. | |
| """ | |
| # (This is a simplified version, can be enhanced with Shapely) | |
| from matplotlib.path import Path | |
| path = Path(roi_polygon) | |
| crossed_ids = set() | |
| for track_id, trajectory in self.tracks.items(): | |
| for x, y, _ in trajectory: | |
| if path.contains_point((x, y)): | |
| crossed_ids.add(track_id) | |
| break | |
| return len(crossed_ids) | |