Normalize French plates, filter invalid lengths, reduce frame rate

- 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 <noreply@anthropic.com>
This commit is contained in:
perco
2026-06-03 09:18:56 +02:00
co-authored by Claude Sonnet 4.6
parent 30561c44de
commit 9b3720c424
2 changed files with 23 additions and 4 deletions
+21 -2
View File
@@ -34,6 +34,20 @@ _token_time = 0.0
_last_event_time = 0.0 _last_event_time = 0.0
_analyzer: PlateAnalyzer | None = None _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: def _rtsp_url() -> str:
if CAMERA_RTSP: 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 from lpr import call_platerecognizer
for _, frame, _ in scored[:3]: for _, frame, _ in scored[:3]:
p, c = call_platerecognizer(frame, PLATERECOGNIZER_KEY) p, c = call_platerecognizer(frame, PLATERECOGNIZER_KEY)
p = _normalize_plate(p)
if p and c > conf: if p and c > conf:
plate, conf = p, c plate, conf = p, c
if conf >= 0.7: if conf >= 0.7:
@@ -225,9 +240,13 @@ def _process_clip(event_id: str, event_dir: str, clip_path: str, camera_name: st
else: else:
log.info("PlateRecognizer returned no result, falling back to local LPR") log.info("PlateRecognizer returned no result, falling back to local LPR")
if _analyzer: 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: 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}") log.info(f"LPR: plate={plate!r} conf={conf:.2f} bbox={plate_bbox}")
+2 -2
View File
@@ -16,8 +16,8 @@ services:
- SNAPSHOTS_DIR=/data/snapshots - SNAPSHOTS_DIR=/data/snapshots
- EVENTS_DIR=/data/events - EVENTS_DIR=/data/events
- POLL_INTERVAL=2 - POLL_INTERVAL=2
- CAPTURE_DURATION=15 - CAPTURE_DURATION=20
- CAPTURE_FPS=5 - CAPTURE_FPS=2
- COOLDOWN=60 - COOLDOWN=60
- PLATERECOGNIZER_API_KEY=c1127284b5ef06b49ade33f1dfc0f50169b88c1d - PLATERECOGNIZER_API_KEY=c1127284b5ef06b49ade33f1dfc0f50169b88c1d
labels: labels: