diff --git a/app/lpr.py b/app/lpr.py index 8a871c9..53ce385 100644 --- a/app/lpr.py +++ b/app/lpr.py @@ -111,11 +111,12 @@ class PlateAnalyzer: avg_conf = float(np.mean(confs)) if confs else 0.0 return text, avg_conf - def read_plate(self, frame: np.ndarray) -> tuple[str, float]: - """Detect plate in frame, read text. Returns (plate_text, confidence).""" + def read_plate(self, frame: np.ndarray) -> tuple[str, float, tuple | None]: + """Detect plate, read text. Returns (plate_text, confidence, bbox_or_None). + bbox = (x1, y1, x2, y2) in pixel coords.""" plate_boxes = self.detect_plates(frame) if not plate_boxes: - return "", 0.0 + return "", 0.0, None x1, y1, x2, y2, plate_conf = plate_boxes[0] pad = 8 @@ -130,6 +131,6 @@ class PlateAnalyzer: # Filter noise: plate must have at least 4 alphanumeric chars alnum = "".join(c for c in text if c.isalnum()) if len(alnum) < 4: - return "", 0.0 + return "", 0.0, (int(x1), int(y1), int(x2), int(y2)) - return text, (plate_conf + ocr_conf) / 2.0 + return text, (plate_conf + ocr_conf) / 2.0, (int(x1), int(y1), int(x2), int(y2)) diff --git a/app/main.py b/app/main.py index 938b00f..53ce746 100644 --- a/app/main.py +++ b/app/main.py @@ -78,6 +78,11 @@ async def index( }) +CAPTURE_DURATION = int(os.environ.get("CAPTURE_DURATION", "15")) +CAPTURE_FPS = int(os.environ.get("CAPTURE_FPS", "5")) +TOP_FRAMES = int(os.environ.get("TOP_FRAMES", "10")) + + @app.get("/event/{event_id}", response_class=HTMLResponse) async def event_detail(request: Request, event_id: str): ev = database.get_event(event_id) @@ -86,18 +91,26 @@ async def event_detail(request: Request, event_id: str): ev["time_str"] = ts_to_str(ev["start_time"]) - # List frames for this event event_dir = os.path.join(EVENTS_DIR, event_id) frame_paths = sorted(glob.glob(os.path.join(event_dir, "frame_*.jpg"))) - frames = [f"events/{event_id}/frame_{i+1:04d}.jpg" for i in range(len(frame_paths))] + frames = [f"events/{event_id}/{os.path.basename(p)}" for p in frame_paths] - has_clip = ev.get("clip_path") and os.path.exists(os.path.join("/data", ev["clip_path"])) + clip_abs = os.path.join("/data", ev["clip_path"]) if ev.get("clip_path") else None + has_clip = bool(clip_abs and os.path.exists(clip_abs)) + clip_size = "" + if has_clip: + size = os.path.getsize(clip_abs) + clip_size = f"{size // 1024 // 1024}MB" if size > 1024 * 1024 else f"{size // 1024}KB" return templates.TemplateResponse("event_detail.html", { "request": request, "ev": ev, "frames": frames, "has_clip": has_clip, + "clip_size": clip_size, + "capture_duration": CAPTURE_DURATION, + "capture_total": CAPTURE_DURATION * CAPTURE_FPS, + "top_frames": TOP_FRAMES, }) diff --git a/app/templates/event_detail.html b/app/templates/event_detail.html index 669aac6..be86736 100644 --- a/app/templates/event_detail.html +++ b/app/templates/event_detail.html @@ -3,119 +3,115 @@
-