# config.yaml — canonical configuration for the production pipeline # (predict.py + counter_dashboard.py). Single source of truth. # # Secrets & deployment-specific values (RTSP_URL, dashboard host/ports, # SECRET_KEY, SITE_NAME) stay in .env — they are NOT duplicated here. # Zone polygons stay in zones.json. Tracker hyperparams stay in cfg/tracker.yaml. # # Model modes: add new entries under models.modes (E, F, ...) without code changes. # A mode only selects engines + class filters; per-class conf/iou/min_bbox_area # live in models.detection_params and apply to ALL modes. stream: resolution: [1280, 720] inference_stride: 2 models: active_mode: "C" # A|B|C|D (+ future E, F, ...). Dashboard switch writes here (manual restart to apply). # Engine file paths (relative to repo root). Mode `engines` entries reference these keys. paths: combined: "models/v4-best.engine" truck_only: "models/v4-best.engine" sack_only: "models/best.engine" box: "models/yolo11n-bbox-100ep-sack+box-20260909-best.engine" truck_detector: "models/truck-detector.engine" # Mode presets: engines to load + class filters. NOTHING else per mode. # Each engine declares the classes it contributes, so tracker roles # (shared vs dedicated, separate truck model) derive structurally — # new modes need zero Python changes. modes: A: description: "Combined v4 sack+truck only (legacy, no box counting)" engines: - path: combined classes: [truck, sack] class_filters: truck: ["truck"] sack: ["sack"] box: [] B: description: "v4 truck-only + yolo11n sack+box (shared tracker, shared ID space)" engines: - path: truck_only classes: [truck] - path: box classes: [sack, box] class_filters: truck: ["truck"] sack: ["sack"] box: ["box"] C: description: "Combined v4 sack+truck + yolo11n box-only (dedicated tracker)" engines: - path: combined classes: [truck, sack] - path: box classes: [box] class_filters: truck: ["truck"] sack: ["sack"] box: ["box"] D: description: "v4 truck-only + best sack-only + yolo11n box-only (3 engines)" engines: - path: truck_only classes: [truck] - path: sack_only classes: [sack] - path: box classes: [box] class_filters: truck: ["truck"] sack: ["sack"] box: ["box"] # Shared per-class detection params (ALL modes). iou default = Ultralytics default. # min_bbox_area is a permissive guardrail in px^2 @1280x720 (existing # perspective min_valid_area filter still applies on top). detection_params: truck: conf: 0.35 iou: 0.7 min_bbox_area: 5000 sack: conf: 0.35 iou: 0.7 min_bbox_area: 1500 box: conf: 0.35 iou: 0.7 min_bbox_area: 1500 # Polygons live in zones.json (kept separate: site calibration cadence). zones: config_file: "zones.json" # Tracker hyperparams live in cfg/tracker.yaml (kept separate: ML tuning cadence). tracker: config_file: "cfg/tracker.yaml" counting: confirm_delay_sec: 0.5 exit_confirm_delay_sec: 6.0 entry_overlap_threshold: 0.20 exit_overlap_threshold: 0.05 camera_noise_deadband: 50 # Effective values below match zones.json (which previously overrode predict.py defaults). duplicate_circle_radius: 30 min_valid_area: 15000 max_reid_transit_distance: 400 circle_stay_timeout_sec: 10.0 jarak_toleransi_duplikat: 30 tolerance_missing_frames: 1200 batch: timeout_seconds: 30.0 merge_threshold_seconds: 300 daily_cutoff_time: "06:00" output: dir: "/opt/jetson-counter" db_name: "jetson_counter.db" state_file: "current_batch.json" # batch_mode_file is DEPRECATED: dashboard now persists the mode switch to # models.active_mode in this file. Key kept so old deployments can be detected. batch_mode_file: "batch_mode.json" live_frame_path: "/dev/shm/jetson-counter/live_frame.jpg" live_status_path: "/dev/shm/jetson-counter/live_status.json" camera: name: "CC1" object_label: "karung-pakan"