Whitelist: plates added to /whitelist are silently ignored on
detection — no clip, no frames, no DB entry. Manageable via
/whitelist page or from the event detail page per-event.
Stats: /stats shows all known plates ranked by passage count,
with first/last seen dates and one-click whitelist toggle.
Navigation links added to the index header.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
'if quad else None' raises ValueError on a numpy array with more
than one element. Replace with 'if quad is not None else None'.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pure sharpness ranking fails when a moving car causes motion blur —
blurry car frames score lower than the sharp static background, so
YOLO never sees the vehicle. Now compute inter-frame motion diff
(downscaled to 320px, fast) alongside sharpness, then combine
(65% motion + 35% sharpness) to select the top 15 frames for YOLO.
This ensures the vehicle-present frames reach YOLO and PlateRecognizer
even when they are slightly blurred.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds call_platerecognizer() to lpr.py which sends frames to the
PlateRecognizer cloud API (regions=fr) with a 1920px cap to stay
within API limits. In watcher.py, switches to a two-pass frame
scoring strategy: Laplacian sharpness on all frames first, then
YOLO only on the top-10 sharpest frames, then PlateRecognizer on
the top-3 by score. Falls back to local YOLO+Tesseract/PaddleOCR
if the API returns no result.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Delete event: POST /event/{id}/delete removes DB row + files
- Perspective correction: minAreaRect on white plate region → getPerspectiveTransform
gives a flat frontal view of the plate (e.g. 'GR B38 WR' instead of trapezoid)
- Tesseract now scales image 3x before OCR and skips EU blue strip (left 11%)
- Saves plate_ocr.jpg (perspective-corrected + enhanced crop actually fed to OCR)
- Event detail shows both raw detection crop and OCR crop side by side
- Manual plate edit form in event detail
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Tiled YOLO (3x2, 20% overlap): plate confidence 0.307 -> 0.838 on test frame
- Aspect ratio filter (2.0-6.5:1): rejects non-plate shapes
- Confidence threshold 0.03 -> 0.04: removes fence/noise false positives
- Exclude top 15% (sky) and bottom 8% (timestamp overlay) from detection zone
- Add Tesseract as primary OCR (better for Latin plates), PaddleOCR as fallback
- Enhance plate crop before OCR: CLAHE + sharpening + min 80px upscale
- Save plate_crop.jpg (4x upscaled) to event dir for manual review
- Show plate crop in event detail page
- Add manual plate edit form in event detail (POST /event/{id}/plate)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously frames were extracted after the 720p transcode, resulting in 1280x720
images even when the source was 4K. Now frames are extracted from the original
clip first, then the clip is transcoded to 720p for web playback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
POST /upload saves the file, runs full processing (transcode, frame extraction,
LPR, color detection) and redirects to the resulting event page.
UI: "Tester un clip" button in header reveals a file picker form.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Transcode clip en H.264 baseline level 3.1 (compatible tous navigateurs)
- Downsample à 720p pour réduire la taille (17MB raw → ~2.5MB encodé)
- CRF 28 + preset fast = bon compromis qualité/vitesse
- Sans audio (inutile pour surveillance)
- -movflags +faststart pour lecture streaming sans téléchargement complet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Garde toutes les frames (plus de limite TOP_FRAMES), triées score LPR desc
- Clip remuxé avec -movflags +faststart pour lecture directe navigateur + lien téléchargement
- Lightbox : double-clic sur frame → plein écran, navigation ←/→, Échap pour fermer
- Grille 8 colonnes pour voir toutes les frames
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Couleur : crop autour de la plaque (zone carrosserie au-dessus) au lieu du frame entier ; fallback center 50% si pas de plaque
- lpr.read_plate() retourne maintenant (text, conf, bbox) pour exposer la position de la plaque
- Index : supprime filtre caméra et badge caméra (une seule caméra)
- Carte index : badge ▶ clip si clip disponible
- Page détail : section debug (nb frames, taille clip, id), gestion propre des anciens événements sans clip/frames
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Sauvegarde le clip MP4 et les top 10 frames par événement dans /data/events/{id}/
- Nouvelle route GET /event/{id} avec page détail : info, vignette interactive, lecteur vidéo, galerie frames
- Les cartes de l'index sont maintenant cliquables
- Migration DB : ajout colonne clip_path sur les BDD existantes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remplace OpenCV VideoCapture par ffmpeg pour la capture RTSP (plus fiable)
- Capture 15s → extrait ~75 frames à 5fps via ffmpeg
- Le LPR analyse toutes les frames et garde la meilleure (plaque la plus grande/confiante)
- Ajoute CAPTURE_FPS env var
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remplace la source Frigate par l'API GetAiState de la caméra Reolink
- Capture RTSP en temps réel (~20s) quand véhicule détecté, garde la meilleure frame
- LPR avec YOLOv9 (détection plaque) + PaddleOCR v4 (lecture texte) via ONNX
- Modèles partagés avec Frigate (volume local ./models/)
- Cooldown 60s entre événements pour éviter les doublons
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Polls Frigate events API, extracts dominant vehicle color (KMeans),
reads LPR plate from Frigate sub_label. Responsive dark UI with
filter by plate/camera/date and auto-refresh. FastAPI + SQLite.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>