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:
1 parent
0467e0ce68
commit
12b70a3431
7 files changed
+94
-128
No files matched your search
+26
-33
@@ -30,7 +30,6 @@ from src.config_loader import (
|
||||
load_config,
|
||||
read_zone_polygons,
|
||||
resolve_active_mode,
|
||||
LEGACY_ZONE_KNOBS,
|
||||
)
|
||||
|
||||
# --- SQLite Database & State Configuration ---
|
||||
@@ -649,43 +648,30 @@ DEFAULT_TRUCK = []
|
||||
|
||||
|
||||
def load_zones():
|
||||
global ZONA_PALET_REF, ZONA_TRUCK_REF, GARIS_COUNTING_REF, DUPLICATE_CIRCLE_RADIUS_REF
|
||||
global MIN_VALID_AREA_REF, JARAK_TOLERANSI_DUPLIKAT_REF, MAX_REID_TRANSIT_DISTANCE_REF
|
||||
global CIRCLE_STAY_TIMEOUT_SEC, INFERENCE_STRIDE, CONFIRM_DELAY_SEC, EXIT_CONFIRM_DELAY_SEC
|
||||
"""Load zone geometry from zones.json (polygons only — knobs live in config.yaml).
|
||||
|
||||
Delegates to src.config_loader.read_zone_polygons: legacy knob keys in
|
||||
zones.json are ignored with a warning (config.yaml counting.* wins).
|
||||
ZONA_COUNTING_REF is derived from the truck polygon (bottom quarter),
|
||||
not from the file's "counting" key — preserved pre-YAML behaviour.
|
||||
"""
|
||||
global ZONA_PALET_REF, ZONA_TRUCK_REF, GARIS_COUNTING_REF
|
||||
global ZONA_COUNTING_REF, left_limit_ref, right_limit_ref, EXTERNAL_STREAM_URL_REF
|
||||
if os.path.exists(ZONES_JSON_PATH):
|
||||
try:
|
||||
with open(ZONES_JSON_PATH, 'r') as f:
|
||||
data = json.load(f)
|
||||
ZONA_PALET_REF = np.array(data.get('palet', []), dtype=np.int32)
|
||||
ZONA_TRUCK_REF = np.array(data.get('truck', []), dtype=np.int32)
|
||||
ZONA_COUNTING_REF = get_bottom_quarter(ZONA_TRUCK_REF)
|
||||
left_limit_ref = float(data.get('left_limit', 0.05))
|
||||
right_limit_ref = float(data.get('right_limit', 0.95))
|
||||
GARIS_COUNTING_REF = ZONA_TRUCK_REF.copy()
|
||||
DUPLICATE_CIRCLE_RADIUS_REF = data.get('duplicate_circle_radius', 30)
|
||||
MIN_VALID_AREA_REF = data.get('min_valid_area', 15000)
|
||||
JARAK_TOLERANSI_DUPLIKAT_REF = data.get('jarak_toleransi_duplikat', 20)
|
||||
MAX_REID_TRANSIT_DISTANCE_REF = data.get('max_reid_transit_distance', 400)
|
||||
CIRCLE_STAY_TIMEOUT_SEC = data.get('circle_stay_timeout_sec', 10.0)
|
||||
INFERENCE_STRIDE = data.get('inference_stride', 2)
|
||||
CONFIRM_DELAY_SEC = data.get('confirm_delay_sec', 0.5)
|
||||
EXIT_CONFIRM_DELAY_SEC = data.get('exit_confirm_delay_sec', 6.0)
|
||||
EXTERNAL_STREAM_URL_REF = data.get('external_stream_url', 'http://192.168.192.96:8888/cam/')
|
||||
if not EXTERNAL_STREAM_URL_REF:
|
||||
EXTERNAL_STREAM_URL_REF = 'http://192.168.192.96:8888/cam/'
|
||||
# Knob keys below are LEGACY: config.yaml counting.* is canonical and
|
||||
# run_prediction overrides these globals from it. Kept reading here
|
||||
# only so import-time defaults stay sane; warn once to guide migration.
|
||||
_legacy_knobs = sorted(LEGACY_ZONE_KNOBS & set(data.keys()))
|
||||
if _legacy_knobs:
|
||||
print(f"[WARN] zones.json knob keys {_legacy_knobs} diabaikan — "
|
||||
f"pakai config.yaml (counting.*) sebagai gantinya.")
|
||||
print("[INFO] Berhasil memuat koordinat zona dan parameter kalibrasi dari zones.json")
|
||||
return
|
||||
zones = read_zone_polygons(ZONES_JSON_PATH)
|
||||
ZONA_PALET_REF = np.array(zones.get('palet', []), dtype=np.int32)
|
||||
ZONA_TRUCK_REF = np.array(zones.get('truck', []), dtype=np.int32)
|
||||
ZONA_COUNTING_REF = get_bottom_quarter(ZONA_TRUCK_REF)
|
||||
left_limit_ref = float(zones.get('left_limit', 0.05))
|
||||
right_limit_ref = float(zones.get('right_limit', 0.95))
|
||||
GARIS_COUNTING_REF = ZONA_TRUCK_REF.copy()
|
||||
EXTERNAL_STREAM_URL_REF = zones.get('external_stream_url', '') or 'http://192.168.192.96:8888/cam/'
|
||||
print("[INFO] Berhasil memuat koordinat zona dari zones.json (via src.config_loader)")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"[WARNING] Gagal memuat zones.json ({e}), menggunakan default.")
|
||||
|
||||
|
||||
ZONA_PALET_REF = np.array(DEFAULT_PALET, dtype=np.int32)
|
||||
ZONA_TRUCK_REF = np.array(DEFAULT_TRUCK, dtype=np.int32)
|
||||
ZONA_COUNTING_REF = get_bottom_quarter(ZONA_TRUCK_REF)
|
||||
@@ -1247,6 +1233,8 @@ def run_prediction(model_path, source_path,
|
||||
global width, height, CONFIRM_DELAY_SEC, EXIT_CONFIRM_DELAY_SEC
|
||||
global active_batch_info, system_state
|
||||
global DUPLICATE_CIRCLE_RADIUS, MIN_VALID_AREA, JARAK_TOLERANSI_DUPLIKAT, MAX_REID_TRANSIT_DISTANCE
|
||||
global ENTRY_OVERLAP_THRESHOLD, EXIT_OVERLAP_THRESHOLD, TOLERANSI_FRAME_HILANG
|
||||
global MAX_REID_FRAMES, DEBOUNCE_FRAMES
|
||||
global DB_PATH, STATE_FILE, BATCH_MODE_FILE, LIVE_STREAM_FRAME_PATH
|
||||
global CAMERA_NAME, OBJECT_LABEL, DAILY_CUTOFF_TIME, BATCH_MERGE_THRESHOLD_SECONDS
|
||||
global CIRCLE_STAY_TIMEOUT_SEC, _CFG
|
||||
@@ -1293,6 +1281,11 @@ def run_prediction(model_path, source_path,
|
||||
JARAK_TOLERANSI_DUPLIKAT = cfg.counting.jarak_toleransi_duplikat
|
||||
MAX_REID_TRANSIT_DISTANCE = cfg.counting.max_reid_transit_distance
|
||||
CIRCLE_STAY_TIMEOUT_SEC = cfg.counting.circle_stay_timeout_sec
|
||||
ENTRY_OVERLAP_THRESHOLD = cfg.counting.entry_overlap_threshold
|
||||
EXIT_OVERLAP_THRESHOLD = cfg.counting.exit_overlap_threshold
|
||||
TOLERANSI_FRAME_HILANG = cfg.counting.tolerance_missing_frames
|
||||
MAX_REID_FRAMES = cfg.counting.max_reid_frames
|
||||
DEBOUNCE_FRAMES = cfg.counting.debounce_frames
|
||||
|
||||
# Legacy batch_mode.json no longer drives the mode — nudge once if stale.
|
||||
_legacy_warn = check_legacy_batch_mode(cfg, BATCH_MODE_FILE)
|
||||
|
||||
Reference in new issue
Block a user