Download src/objectmodel_v1/zones.py from bench-labs/objectmodel-v1: direct link, hf CLI and curl.
- Browser
- Download file 2.24 kB
-
https://huggingface.co/bench-labs/objectmodel-v1/resolve/main/src/objectmodel_v1/zones.py
- Command line
-
hf download hf://bench-labs/objectmodel-v1/src/objectmodel_v1/zones.py
-
curl -L -o zones.py https://huggingface.co/bench-labs/objectmodel-v1/resolve/main/src/objectmodel_v1/zones.py
2.24 kB
| from __future__ import annotations | |
| from dataclasses import dataclass | |
| class ZoneEvent: | |
| track_id: int | |
| label: int | |
| kind: str | |
| frame_index: int | |
| position: tuple[float, float] | |
| def point_in_polygon(point: tuple[float, float], polygon: list[tuple[float, float]]) -> bool: | |
| x, y = point | |
| inside = False | |
| n = len(polygon) | |
| j = n - 1 | |
| for i in range(n): | |
| xi, yi = polygon[i] | |
| xj, yj = polygon[j] | |
| if (yi > y) != (yj > y) and x < (xj - xi) * (y - yi) / (yj - yi) + xi: | |
| inside = not inside | |
| j = i | |
| return inside | |
| class RestrictedZoneMonitor: | |
| """Fires an event when a tracked object's ground position crosses a zone boundary. | |
| Consumes `Track` objects from `SortTracker.update()`. The zone is a polygon in | |
| the same pixel coordinates as the tracked boxes (a rectangle is just a | |
| four-point polygon). Uses each box's bottom-center point rather than its | |
| centroid, since a zone drawn on a floor plane should key off where someone is | |
| standing, not their torso. Only reports the entered/exited transition, not | |
| every frame a track spends inside the zone. | |
| """ | |
| def __init__(self, polygon: list[tuple[float, float]]) -> None: | |
| self.polygon = polygon | |
| self._inside_state: dict[int, bool] = {} | |
| def update(self, tracks, frame_index: int = 0) -> list[ZoneEvent]: | |
| events: list[ZoneEvent] = [] | |
| live_ids = set() | |
| for track in tracks: | |
| live_ids.add(track.id) | |
| x0, y0, x1, y1 = track.box | |
| ground_point = ((x0 + x1) / 2.0, y1) | |
| is_inside = point_in_polygon(ground_point, self.polygon) | |
| was_inside = self._inside_state.get(track.id, False) | |
| if is_inside and not was_inside: | |
| events.append(ZoneEvent(track.id, track.label, "entered", frame_index, ground_point)) | |
| elif was_inside and not is_inside: | |
| events.append(ZoneEvent(track.id, track.label, "exited", frame_index, ground_point)) | |
| self._inside_state[track.id] = is_inside | |
| for track_id in list(self._inside_state): | |
| if track_id not in live_ids: | |
| del self._inside_state[track_id] | |
| return events | |