feat: live count worker, tracking, and page updates

This commit is contained in:
Andrew-AAAA committed 2026-09-30 11:31:13 +07:00
1 parent 4606c0adeb
commit 1403a07b86
5 files changed
+77 -15

No files matched your search

+9 -5
View File
@@ -43,7 +43,8 @@ class Session:
dedup_radius: float, margin: int, imgsz: int,
entry_travel_min: float, handoff_radius: float,
unload_confirm_frames: int, min_area_scale: float,
spatial_dedup: bool, whep_url: str = ""):
spatial_dedup: bool, whep_url: str = "",
count_classes: tuple = ("sack",)):
self.source = source
# When the browser watches the camera over WebRTC it never asks for the
# MJPEG, so encoding a JPEG per frame would be pure waste (REQ-177).
@@ -61,6 +62,7 @@ class Session:
self.unload_confirm_frames = unload_confirm_frames
self.min_area_scale = min_area_scale
self.spatial_dedup = spatial_dedup
self.count_classes = tuple(count_classes)
self.started_at = time.time()
self.error = ""
@@ -167,7 +169,8 @@ class Session:
# segfault without it (same reason predict.py does this).
model(np.zeros((720, 1280, 3), dtype=np.uint8), imgsz=self.imgsz, verbose=False)
tracker = ByteTrackTracker(model, self.conf)
tracker = ByteTrackTracker(model, self.conf,
class_filter=tuple(self.count_classes))
stabilizer = BboxStabilizer(ema_alpha=0.35, max_hold_frames=10,
max_height_ratio=1.5, min_height_ratio=0.70)
counter = LineCrossCounter(
@@ -200,7 +203,8 @@ class Session:
break
frame = cv2.resize(frame, (1280, 720))
detections = [d for d in tracker.update(frame, []) if d.class_name == "sack"]
# The tracker only emits count_classes, so no post-filter is needed.
detections = tracker.update(frame, [])
stable = stabilizer.update(detections)
inside, outside = [], []
small = 0
@@ -338,7 +342,7 @@ def start(source: str, model_path: str, line_y: int, line_x_start: int, line_x_e
imgsz: int = 640, entry_travel_min: float = 60.0,
handoff_radius: float = 100.0, unload_confirm_frames: int = 3,
min_area_scale: float = 1.0, spatial_dedup: bool = False,
whep: str = "") -> dict:
whep: str = "", count_classes: tuple = ("sack",)) -> dict:
global _session
with _guard:
if _session is not None and _session.status()["running"]:
@@ -350,7 +354,7 @@ def start(source: str, model_path: str, line_y: int, line_x_start: int, line_x_e
_session = Session(source, model_path, line_y, line_x_start, line_x_end,
conf, dedup_radius, margin, imgsz, entry_travel_min,
handoff_radius, unload_confirm_frames, min_area_scale,
spatial_dedup, whep)
spatial_dedup, whep, count_classes)
_session.start()
time.sleep(0.4) # let an immediate failure surface in the response
return _session.status()