From 9b3720c424a946ff3b87e36989c23e9bf656e89e Mon Sep 17 00:00:00 2001 From: perco Date: Wed, 3 Jun 2026 09:18:56 +0200 Subject: [PATCH] Normalize French plates, filter invalid lengths, reduce frame rate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add _normalize_plate(): strips non-alphanumeric, rejects < 6 or > 8 chars, formats standard new French plates as AB-123-CD - Applied after PlateRecognizer and local LPR results - CAPTURE_DURATION 15→20s, CAPTURE_FPS 5→2fps (40 frames vs 75) Co-Authored-By: Claude Sonnet 4.6 --- app/watcher.py | 23 +++++++++++++++++++++-- docker-compose.yml | 4 ++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/app/watcher.py b/app/watcher.py index fc99bdb..3b58484 100644 --- a/app/watcher.py +++ b/app/watcher.py @@ -34,6 +34,20 @@ _token_time = 0.0 _last_event_time = 0.0 _analyzer: PlateAnalyzer | None = None +import re as _re +_FR_PLATE_RE = _re.compile(r'^([A-Z]{2})(\d{3})([A-Z]{2})$') + +def _normalize_plate(raw: str) -> str: + """Validate and format a French plate (6-8 alphanumeric chars). + Standard new format AB-123-CD is detected and hyphenated automatically.""" + alnum = "".join(c for c in raw.upper() if c.isalnum()) + if len(alnum) < 6 or len(alnum) > 8: + return "" + m = _FR_PLATE_RE.match(alnum) + if m: + return f"{m.group(1)}-{m.group(2)}-{m.group(3)}" + return alnum + def _rtsp_url() -> str: if CAMERA_RTSP: @@ -209,6 +223,7 @@ def _process_clip(event_id: str, event_dir: str, clip_path: str, camera_name: st from lpr import call_platerecognizer for _, frame, _ in scored[:3]: p, c = call_platerecognizer(frame, PLATERECOGNIZER_KEY) + p = _normalize_plate(p) if p and c > conf: plate, conf = p, c if conf >= 0.7: @@ -225,9 +240,13 @@ def _process_clip(event_id: str, event_dir: str, clip_path: str, camera_name: st else: log.info("PlateRecognizer returned no result, falling back to local LPR") if _analyzer: - plate, conf, plate_bbox, plate_corrected = _analyzer.read_plate(best_frame) + _p, _c, plate_bbox, plate_corrected = _analyzer.read_plate(best_frame) + plate = _normalize_plate(_p) + conf = _c if plate else 0.0 elif _analyzer: - plate, conf, plate_bbox, plate_corrected = _analyzer.read_plate(best_frame) + _p, _c, plate_bbox, plate_corrected = _analyzer.read_plate(best_frame) + plate = _normalize_plate(_p) + conf = _c if plate else 0.0 log.info(f"LPR: plate={plate!r} conf={conf:.2f} bbox={plate_bbox}") diff --git a/docker-compose.yml b/docker-compose.yml index 6187598..4344553 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,8 +16,8 @@ services: - SNAPSHOTS_DIR=/data/snapshots - EVENTS_DIR=/data/events - POLL_INTERVAL=2 - - CAPTURE_DURATION=15 - - CAPTURE_FPS=5 + - CAPTURE_DURATION=20 + - CAPTURE_FPS=2 - COOLDOWN=60 - PLATERECOGNIZER_API_KEY=c1127284b5ef06b49ade33f1dfc0f50169b88c1d labels: