Add delete event, perspective correction OCR, and OCR crop display

- 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>
This commit is contained in:
perco
2026-06-02 18:05:10 +02:00
co-authored by Claude Sonnet 4.6
parent 13e6038069
commit accbae41ce
5 changed files with 157 additions and 46 deletions
+18
View File
@@ -1,5 +1,6 @@
import os
import glob
import shutil
import logging
import threading
import tempfile
@@ -105,6 +106,8 @@ async def event_detail(request: Request, event_id: str):
plate_crop_abs = os.path.join(event_dir, "plate_crop.jpg")
plate_crop = f"events/{event_id}/plate_crop.jpg" if os.path.exists(plate_crop_abs) else None
plate_ocr_abs = os.path.join(event_dir, "plate_ocr.jpg")
plate_ocr = f"events/{event_id}/plate_ocr.jpg" if os.path.exists(plate_ocr_abs) else None
return templates.TemplateResponse("event_detail.html", {
"request": request,
@@ -113,6 +116,7 @@ async def event_detail(request: Request, event_id: str):
"has_clip": has_clip,
"clip_size": clip_size,
"plate_crop": plate_crop,
"plate_ocr": plate_ocr,
"capture_duration": CAPTURE_DURATION,
"capture_fps": CAPTURE_FPS,
"capture_total": CAPTURE_DURATION * CAPTURE_FPS,
@@ -140,6 +144,20 @@ async def api_events(
return {"events": events, "total": total}
@app.post("/event/{event_id}/delete")
async def delete_event(event_id: str):
ev = database.get_event(event_id)
if not ev:
raise HTTPException(status_code=404, detail="Événement introuvable")
database.delete_event(event_id)
event_dir = os.path.join(EVENTS_DIR, event_id)
shutil.rmtree(event_dir, ignore_errors=True)
snapshot = os.path.join(SNAPSHOTS_DIR, f"{event_id}.jpg")
if os.path.exists(snapshot):
os.unlink(snapshot)
return RedirectResponse("/", status_code=303)
@app.post("/event/{event_id}/plate")
async def update_plate(event_id: str, plate: str = Form("")):
ev = database.get_event(event_id)