import streamlit as st
import pandas as pd
from datetime import datetime
import plotly.express as px
import plotly.graph_objects as go
# Set page config
st.set_page_config(
page_title="License Plate Detection Results",
page_icon="🚗",
layout="wide"
)
# Custom CSS
st.markdown("""
""", unsafe_allow_html=True)
# Title and description
st.title("📊 License Plate Detection Dashboard")
st.markdown("""
This dashboard shows the results of license plate detections from video surveillance.
""")
# Load and process data
@st.cache_data
def load_data():
try:
df = pd.read_csv("car_plate_data_stored.csv")
# Handle different column names
if 'NumberPlate' in df.columns:
df = df.rename(columns={'NumberPlate': 'ID'})
elif 'ImageFile' in df.columns:
df = df.rename(columns={'ImageFile': 'ID'})
# Ensure we have all required columns
if 'Confidence' not in df.columns:
df['Confidence'] = 'N/A'
# Convert dates
df['DateTime'] = pd.to_datetime(df['Date'] + ' ' + df['Time'],
format='%d-%m-%Y %H:%M:%S',
dayfirst=True)
return df
except Exception as e:
st.error(f"Error loading data: {str(e)}")
return pd.DataFrame(columns=['ID', 'Date', 'Time', 'Confidence', 'DateTime'])
# Load data
df = load_data()
# Dashboard layout
col1, col2 = st.columns([2, 1])
with col1:
# Statistics cards in a grid
st.markdown('
', unsafe_allow_html=True)
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)
st.markdown('
', unsafe_allow_html=True)
# Timeline chart
if not df.empty:
st.subheader("Detection Timeline")
detections_by_time = df.groupby(df['DateTime'].dt.floor('H')).size().reset_index(name='count')
fig = go.Figure()
fig.add_trace(go.Scatter(
x=detections_by_time['DateTime'],
y=detections_by_time['count'],
mode='lines+markers',
line=dict(color='#1f77b4', width=2),
marker=dict(size=6),
name='Detections'
))
fig.update_layout(
title="Detections Over Time",
xaxis_title="Time",
yaxis_title="Number of Detections",
height=400,
hovermode='x unified',
plot_bgcolor='white',
paper_bgcolor='white',
xaxis=dict(
showgrid=True,
gridcolor='#f0f0f0',
),
yaxis=dict(
showgrid=True,
gridcolor='#f0f0f0',
)
)
st.plotly_chart(fig, use_container_width=True)
with col2:
st.subheader("Recent Detections")
if not df.empty:
recent = df.tail(5)
for _, row in recent.iterrows():
with st.container():
st.markdown(f"""
ID: {row['ID']}
Time: {row['Time']}
Confidence: {row['Confidence'] if row['Confidence'] != 'N/A' else 'N/A'}
""", unsafe_allow_html=True)
# Data table with filters
st.subheader("Detection Records")
if not df.empty:
col1, col2 = st.columns([1, 2])
with col1:
date_filter = st.date_input(
"Filter by date",
pd.to_datetime(df['Date']).min()
)
with col2:
confidence_filter = st.slider(
"Minimum confidence",
0.0, 100.0, 0.0,
help="Filter detections by minimum confidence score"
)
# Apply filters
filtered_df = df[df['DateTime'].dt.date == date_filter]
if confidence_filter > 0:
numeric_conf = pd.to_numeric(filtered_df['Confidence'].replace('N/A', -1), errors='coerce')
filtered_df = filtered_df[numeric_conf >= confidence_filter]
# Display the filtered dataframe
st.dataframe(
filtered_df[['ID', 'Date', 'Time', 'Confidence']].style.format({
'Confidence': lambda x: f"{x:.2f}%" if isinstance(x, (int, float)) else x
}),
use_container_width=True
)
# Add summary statistics
if not df.empty:
st.subheader("Detection Statistics")
col1, col2 = st.columns(2)
with col1:
# Detections by hour
hourly_stats = df.groupby(df['DateTime'].dt.hour).size()
fig = px.bar(
x=hourly_stats.index,
y=hourly_stats.values,
labels={'x': 'Hour of Day', 'y': 'Number of Detections'},
title='Detections by Hour of Day'
)
fig.update_layout(bargap=0.2)
st.plotly_chart(fig, use_container_width=True)
with col2:
# Confidence distribution
confidence_values = pd.to_numeric(df['Confidence'].replace('N/A', float('nan')), errors='coerce')
confidence_values = confidence_values.dropna()
if not confidence_values.empty:
fig = px.histogram(
confidence_values,
nbins=20,
labels={'value': 'Confidence Score', 'count': 'Number of Detections'},
title='Distribution of Confidence Scores'
)
fig.update_layout(bargap=0.2)
st.plotly_chart(fig, use_container_width=True)