| import streamlit as st
|
| import pandas as pd
|
| import cv2
|
| import os
|
| from datetime import datetime
|
| import plotly.express as px
|
| from PIL import Image
|
|
|
|
|
| st.set_page_config(
|
| page_title="License Plate Detection Dashboard",
|
| page_icon="🚗",
|
| layout="wide"
|
| )
|
|
|
|
|
| st.title("License Plate Detection Dashboard")
|
|
|
|
|
| st.sidebar.header("Dashboard Controls")
|
|
|
|
|
| @st.cache_data
|
| def load_data():
|
| try:
|
|
|
| try:
|
| df = pd.read_csv("car_plate_data_stored.csv")
|
| except:
|
|
|
| df = pd.read_csv("car_plate_data_new.csv")
|
|
|
|
|
| if 'NumberPlate' in df.columns:
|
| df = df.rename(columns={'NumberPlate': 'ID'})
|
| elif 'ImageFile' in df.columns:
|
| df = df.rename(columns={'ImageFile': 'ID'})
|
|
|
|
|
| if 'NumberPlate' in df.columns:
|
| df = df.rename(columns={'NumberPlate': 'ID'})
|
|
|
|
|
| if 'Confidence' not in df.columns:
|
| df['Confidence'] = 'N/A'
|
|
|
|
|
| df['Confidence'] = df['Confidence'].fillna('N/A')
|
|
|
|
|
| df['DateTime'] = pd.to_datetime(df['Date'] + ' ' + df['Time'],
|
| format='%d-%m-%Y %H:%M:%S',
|
| dayfirst=True)
|
|
|
|
|
| df['Confidence'] = pd.to_numeric(df['Confidence'].replace('N/A', float('nan')), errors='coerce')
|
|
|
|
|
| df['DateTime'] = pd.to_datetime(df['Date'] + ' ' + df['Time'])
|
|
|
|
|
| if 'Confidence' in df.columns:
|
| df['Confidence'] = df['Confidence'].fillna('N/A')
|
| else:
|
| df['Confidence'] = 'N/A'
|
|
|
| return df
|
| except FileNotFoundError:
|
| return pd.DataFrame(columns=['ID', 'Date', 'Time', 'Confidence', 'DateTime'])
|
|
|
| df = load_data()
|
|
|
|
|
| col1, col2 = st.columns([2, 1])
|
|
|
| with col1:
|
| st.header("Detection Statistics")
|
|
|
|
|
| stat_col1, stat_col2, stat_col3 = st.columns(3)
|
|
|
| with stat_col1:
|
| st.metric("Total Detections", len(df))
|
|
|
| with stat_col2:
|
| if not df.empty:
|
| numeric_conf = pd.to_numeric(df['Confidence'].replace('N/A', float('nan')), errors='coerce')
|
| avg_confidence = numeric_conf.mean()
|
| if pd.notnull(avg_confidence):
|
| st.metric("Average Confidence", f"{avg_confidence:.2f}%")
|
| else:
|
| st.metric("Average Confidence", "N/A")
|
|
|
| with stat_col3:
|
| if not df.empty:
|
| today = datetime.now().date()
|
| today_detections = df[pd.to_datetime(df['Date']).dt.date == today].shape[0]
|
| st.metric("Today's Detections", today_detections)
|
|
|
|
|
| if not df.empty:
|
| st.subheader("Detection Timeline")
|
| timeline_fig = px.line(
|
| df.groupby('DateTime').size().reset_index(name='count'),
|
| x='DateTime',
|
| y='count',
|
| title="Detections Over Time"
|
| )
|
| st.plotly_chart(timeline_fig, use_container_width=True)
|
|
|
| with col2:
|
| st.header("Recent Detections")
|
| if not df.empty:
|
| recent = df.tail(5)
|
| for _, row in recent.iterrows():
|
|
|
| if row['ID'].endswith('.jpg'):
|
| img_path = os.path.join("detected_plates", row['ID'])
|
| conf_text = f" ({row['Confidence']}% confidence)" if row['Confidence'] != 'N/A' else ""
|
| else:
|
|
|
| img_path = None
|
| conf_text = ""
|
|
|
| if img_path and os.path.exists(img_path):
|
| st.image(img_path, caption=f"Detected at {row['Time']}{conf_text}")
|
| else:
|
| st.write(f"License Plate: {row['ID']} detected at {row['Time']}{conf_text}")
|
|
|
|
|
| st.header("Detection Records")
|
| if not df.empty:
|
|
|
| date_filter = st.date_input("Filter by date", pd.to_datetime(df['Date']).min())
|
| confidence_filter = st.slider("Minimum confidence", 0.0, 100.0, 0.0)
|
|
|
|
|
| filtered_df = df[df['DateTime'].dt.date == date_filter]
|
|
|
|
|
| if confidence_filter > 0:
|
|
|
| numeric_conf = pd.to_numeric(df['Confidence'], errors='coerce').fillna(-1)
|
| filtered_df = filtered_df[numeric_conf >= confidence_filter]
|
|
|
| st.dataframe(
|
| filtered_df[['ID', 'Date', 'Time', 'Confidence']],
|
| use_container_width=True
|
| )
|
| else:
|
| st.info("No detections recorded yet. Start the detection system to collect data.")
|
|
|
|
|
| st.header("Image Gallery")
|
| if not df.empty:
|
|
|
| image_df = df[df['ID'].str.endswith('.jpg', na=False)]
|
| if not image_df.empty:
|
|
|
| gallery = st.columns(4)
|
| for idx, row in image_df.iterrows():
|
| img_path = os.path.join("detected_plates", row['ID'])
|
| if os.path.exists(img_path):
|
| with gallery[idx % 4]:
|
| conf_text = f" ({row['Confidence']}% conf.)" if row['Confidence'] != 'N/A' else ""
|
| st.image(img_path, caption=f"{row['Time']}{conf_text}", use_column_width=True)
|
| else:
|
| st.info("No images available in the gallery. Only text detections are present.") |