refactor: consolidate counting config through src/config_loader

- config.yaml gains counting.max_reid_frames (200) + debounce_frames (8);
  CountingConfig + parsing + pinned-value test added
- predict.py load_zones() delegates to read_zone_polygons() (geometry only);
  legacy zones.json knob reads removed (config.yaml is canonical)
- run_prediction wires 5 more live knobs from cfg.counting.* (entry/exit
  overlap, tolerance_missing_frames, max_reid_frames, debounce_frames)
- delete deprecated src/config.py (v3 keys) + tests/test_config.py;
  src/main.py bridges onto unified config so the deprecated entrypoint
  keeps working
- 8 never-read globals (JARAK_ABSORBSI_GHOST, CAMERA_NOISE_DEADBAND, ...)
  left untouched — flagged for Phase 2 dead-code cleanup

Verified: pytest 21 passed; full pipeline runs on synthetic video
(engines load, 30 frames, clean finish).
This commit is contained in:
andrew committed 2026-09-17 12:59:54 +07:00
1 parent 0467e0ce68
commit 12b70a3431
7 files changed
+94 -128

No files matched your search

-28
View File
@@ -1,28 +0,0 @@
"""Smoke tests for config loader (src/config.py). Needs python-dotenv only."""
from src.config import load_config
_KEYS = [
"LOCAL_RTSP", "JETSON_RTSP", "MODEL_SACK_PATH", "MODEL_TRUCK_PATH",
"COUNTING_LINE_Y", "COUNTING_LINE_X_START", "COUNTING_LINE_X_END",
"SACK_CONF_THRESHOLD", "TRUCK_CONF_THRESHOLD", "BATCH_TIMEOUT_SECONDS",
"CSV_OUTPUT_DIR", "DATA_SEED",
]
def test_load_from_env_file(tmp_path, monkeypatch):
for k in _KEYS:
monkeypatch.delenv(k, raising=False)
env = tmp_path / "test.env"
env.write_text(
"LOCAL_RTSP=rtsp://cam/1\n"
"MODEL_SACK_PATH=/m/sack.pt\n"
"MODEL_TRUCK_PATH=/m/truck.pt\n"
"SACK_CONF_THRESHOLD=0.55\n"
)
cfg = load_config(str(env))
assert cfg.local_rtsp == "rtsp://cam/1"
assert cfg.sack_model_path == "/m/sack.pt"
assert cfg.truck_model_path == "/m/truck.pt"
assert cfg.sack_conf == 0.55
assert cfg.truck_conf == 0.50 # default preserved
+19
View File
@@ -39,6 +39,25 @@ def test_repo_config_loads_and_validates(repo_config_path):
assert dp.min_bbox_area >= 0
def test_counting_knobs_match_production_defaults(repo_config_path):
"""All live counting knobs in predict.py must come from config.yaml."""
cfg = load_config(repo_config_path)
c = cfg.counting
assert c.confirm_delay_sec == 0.5
assert c.exit_confirm_delay_sec == 6.0
assert c.entry_overlap_threshold == 0.20
assert c.exit_overlap_threshold == 0.05
assert c.camera_noise_deadband == 50
assert c.duplicate_circle_radius == 30
assert c.min_valid_area == 15000
assert c.max_reid_transit_distance == 400
assert c.circle_stay_timeout_sec == 10.0
assert c.jarak_toleransi_duplikat == 30
assert c.tolerance_missing_frames == 1200
assert c.max_reid_frames == 200
assert c.debounce_frames == 8
def test_mode_preset_only_filters_and_engines(repo_config_path):
"""Modes must not carry per-class conf/iou — those live in detection_params."""
with open(repo_config_path) as f: