from edge.config import Config from edge.tracking import IouTracker from edge.smoothing import KeypointSmoother from edge.detectors.fall import FallDetector from edge.detectors.immobility import ImmobilityWatchdog from edge.detectors.ghost import GhostIncidentDetector from edge.detectors.zone import ZoneIntrusionDetector from edge.engine import EventEngine from edge.snapshot import RingBuffer, FaceBlurrer, Snapshotter from edge.models import Person, BBox def _head_boxes(persons: list) -> list: # 배경인물 머리영역 근사: 코 주변 작은 박스 (MVP; 실제는 얼굴 검출 포트로 교체) boxes = [] for p in persons: nose = p.keypoints[0] boxes.append(BBox(nose.x - 20, nose.y - 25, nose.x + 20, nose.y + 15)) return boxes def run_once(source, pose, tracker, smoother, engine, ring, snapshotter, sink, now_fn): ok, frame = source.read() if not ok: return [] now = now_fn() persons = pose.infer(frame) smoothed = [Person(p.bbox, smoother.smooth(p.keypoints, now)) for p in persons] tracks = tracker.update(smoothed, now) lost = tracker.lost() ring.push(now, frame) events = engine.process(tracks, lost, now) if events: snaps = snapshotter.capture([frame], [_head_boxes(persons)]) for e in events: sink.try_send(e, snaps) return events def build_pipeline(config: Config, source, pose) -> dict: return { "source": source, "pose": pose, "tracker": IouTracker(), "smoother": KeypointSmoother(), "engine": EventEngine( FallDetector(config.fall), ImmobilityWatchdog(config.immobility), GhostIncidentDetector(config.ghost), ZoneIntrusionDetector([], config.zone), config.engine, ), "ring": RingBuffer(), "snapshotter": Snapshotter(FaceBlurrer()), }