import streamlit as st import cv2 import numpy as np import requests import base64 import time import os API_URL = os.getenv("API_URL", "http://localhost:8000") st.set_page_config(page_title="LPR Client", layout="wide") st.title("License Plate Recognition - API Client") st.sidebar.header("Mode") mode = st.sidebar.radio("Choose mode", ("Image Upload", "Video Upload")) max_boxes = st.sidebar.slider("Max plates to display", 1, 10, 1) if mode == "Image Upload": uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"]) if uploaded_file is not None: file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8) image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR) col1, col2 = st.columns([1, 1]) with st.spinner("Processing image on server..."): try: # Reset file pointer uploaded_file.seek(0) files = {"file": (uploaded_file.name, uploaded_file.getvalue(), uploaded_file.type)} data = {"max_boxes": max_boxes} response = requests.post(f"{API_URL}/upload/image", files=files, data=data) if response.status_code == 200: result = response.json() plates = result.get("plates", []) process_time = result.get("process_time", 0.0) if not plates: with col1: st.image(cv2.cvtColor(image, cv2.COLOR_BGR2RGB), caption="Original image", use_column_width=True) with col2: st.warning("No plates detected.") else: annotated_image = image.copy() for p in plates: text_clean = p["plate_text"] x1, y1, x2, y2 = p["bbox"] # Draw box and label on annotated_image cv2.rectangle(annotated_image, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(annotated_image, text_clean, (x1, max(25, y1 - 10)), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 2) with col1: st.image(cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB), caption="Processed image", use_column_width=True) with col2: for i, p in enumerate(plates): plate_bytes = base64.b64decode(p["plate_image_base64"]) plate_np = np.frombuffer(plate_bytes, np.uint8) plate_img = cv2.imdecode(plate_np, cv2.IMREAD_COLOR) st.image(cv2.cvtColor(plate_img, cv2.COLOR_BGR2RGB)) st.markdown( f"