File size: 5,477 Bytes
c3c6f00 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | import streamlit as st
import cv2
import tempfile
import os
import pandas as pd
import numpy as np
import plotly.express as px
from main import process_video
from src.visualization import generate_density_plot, generate_direction_chart, overlay_heatmap
# Page Configuration
st.set_page_config(
page_title="AI Pedestrian Analytics",
page_icon="πΆββοΈ",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom Styling
st.markdown("""
<style>
.main {
background-color: #0e1117;
}
.stMetric {
background-color: #1a1c24;
padding: 15px;
border-radius: 10px;
border: 1px solid #30363d;
}
.metric-container {
display: flex;
justify-content: space-between;
}
</style>
""", unsafe_allow_html=True)
# Sidebar
st.sidebar.title("πΆββοΈ Crowd Analysis Engine")
st.sidebar.markdown("---")
uploaded_file = st.sidebar.file_uploader("Upload Video (MP4)", type=["mp4", "mov", "avi"])
conf_threshold = st.sidebar.slider("Confidence Threshold", 0.1, 1.0, 0.25)
model_type = st.sidebar.selectbox("Model Size", ["yolov8n.pt", "yolov8m.pt", "yolov8l.pt"], index=1)
# Main Header
st.title("ποΈ Shibuya Scramble Analytics")
st.markdown("Automated pedestrian tracking, dwell-time analysis, and crowd density visualization.")
if uploaded_file is not None:
# Save uploaded file to temp
tfile = tempfile.NamedTemporaryFile(delete=False)
tfile.write(uploaded_file.read())
video_path = tfile.name
col1, col2 = st.columns([2, 1])
with col1:
st.subheader("Source Video")
st.video(uploaded_file)
with col2:
st.subheader("Process Settings")
run_btn = st.button("π Run Analysis", use_container_width=True)
if run_btn:
with st.status("Analyzing footage...", expanded=True) as status:
progress_bar = st.progress(0)
output_video_path = os.path.join(tempfile.gettempdir(), "annotated_output.mp4")
results = process_video(
video_path,
output_path=output_video_path,
model_path=model_type,
progress_callback=lambda p: progress_bar.progress(p)
)
status.update(label="Analysis Complete!", state="complete")
# --- RESULTS DISPLAY ---
analytics = results['analytics']
st.markdown("---")
st.subheader("π Key Performance Metrics")
m_col1, m_col2, m_col3, m_col4 = st.columns(4)
dwell_times = analytics.calculate_dwell_times()
avg_dwell = np.mean(list(dwell_times.values())) if dwell_times else 0
m_col1.metric("Unique Pedestrians", analytics.get_unique_count())
m_col2.metric("Avg Dwell Time", f"{avg_dwell:.2f}s")
m_col3.metric("System Efficiency", f"{results['fps']:.1f} FPS")
m_col4.metric("Processing Time", f"{results['processing_time']:.1f}s")
tab1, tab2, tab3 = st.tabs(["π₯ Annotated Result", "π₯ Density Heatmap", "π Behavioral Insights"])
with tab1:
st.subheader("Object Tracking & IDs")
# Convert video to web-friendly format if needed (opencv mp4v often needs conversion to libx264 for browser)
# For simplicity, we'll try to display directly or inform user
st.video(output_video_path)
st.info("Output video shows consistent track IDs and movement trails.")
with tab2:
st.subheader("Crowd Density Heatmap")
# Get original first frame for background
cap = cv2.VideoCapture(video_path)
ret, first_frame = cap.read()
cap.release()
if ret:
heatmap = analytics.get_heatmap()
overlay = overlay_heatmap(first_frame, heatmap)
st.image(cv2.cvtColor(overlay, cv2.COLOR_BGR2RGB), use_column_width=True)
else:
st.warning("Could not generate heatmap overlay.")
with tab3:
col_a, col_b = st.columns(2)
with col_a:
st.plotly_chart(generate_density_plot(analytics.get_density_df()), use_container_width=True)
with col_b:
directions = analytics.get_direction_distribution()
st.plotly_chart(generate_direction_chart(directions), use_container_width=True)
# JSON Export
st.markdown("---")
st.subheader("πΎ Export Data")
json_data = {
"total_count": analytics.get_unique_count(),
"avg_dwell_time": avg_dwell,
"directions": directions,
"processing_metadata": {
"fps": results['fps'],
"frames": len(analytics.density_over_time)
}
}
st.download_button(
label="Download JSON Report",
data=str(json_data),
file_name="analytics_report.json",
mime="application/json"
)
else:
# Landing State
st.info("Please upload a video file to begin analysis.")
st.image("https://images.unsplash.com/photo-1542011681-9988549d2c5d?q=80&w=2000&auto=format&fit=crop",
caption="Crowded Crossing Analysis Ready")
|