Update src/streamlit_app.py
Browse files- src/streamlit_app.py +123 -41
src/streamlit_app.py
CHANGED
|
@@ -3,6 +3,8 @@ from PIL import Image
|
|
| 3 |
import time
|
| 4 |
from ultralytics import YOLO
|
| 5 |
import io
|
|
|
|
|
|
|
| 6 |
|
| 7 |
# --- Page Config ---
|
| 8 |
st.set_page_config(page_title="Smart Traffic Light System", layout="wide")
|
|
@@ -27,7 +29,7 @@ uploaded_images = {}
|
|
| 27 |
for col, direction in zip(cols, directions):
|
| 28 |
with col:
|
| 29 |
uploaded_images[direction] = st.file_uploader(f"{direction}", type=["jpg", "png"], key=direction)
|
| 30 |
-
|
| 31 |
# --- Process Once All Images Are Uploaded ---
|
| 32 |
if all(uploaded_images.values()):
|
| 33 |
# Initialize session state attributes if not already initialized
|
|
@@ -64,6 +66,7 @@ if all(uploaded_images.values()):
|
|
| 64 |
yellow_time = 3 # Fixed yellow duration
|
| 65 |
|
| 66 |
# --- Enhanced Signal Status Visualization ---
|
|
|
|
| 67 |
st.markdown("### π₯ Current Signal Status")
|
| 68 |
|
| 69 |
signal_cols = st.columns(4)
|
|
@@ -102,10 +105,12 @@ if all(uploaded_images.values()):
|
|
| 102 |
st.markdown(f"### {status}\n**{direction}**\n**{count} Vehicles**")
|
| 103 |
|
| 104 |
# --- Timer UI ---
|
|
|
|
| 105 |
st.markdown("### β± Signal Timer")
|
| 106 |
timer_placeholder = st.empty()
|
| 107 |
|
| 108 |
# --- Display Annotated Images Below Timer ---
|
|
|
|
| 109 |
st.markdown("### πΌοΈ Detected Vehicles (Annotated Images)")
|
| 110 |
img_cols = st.columns(4)
|
| 111 |
for idx, direction in enumerate(directions):
|
|
@@ -138,59 +143,136 @@ if all(uploaded_images.values()):
|
|
| 138 |
else:
|
| 139 |
# Show completion message when all directions are done
|
| 140 |
st.success("### π¦ Simulation Complete! All directions have completed their green and yellow phases.")
|
| 141 |
-
|
|
|
|
|
|
|
|
|
|
| 142 |
st.markdown("<br>", unsafe_allow_html=True)
|
| 143 |
-
|
| 144 |
-
for key in [
|
| 145 |
-
"annotated_images", "counts", "sorted_directions",
|
| 146 |
-
"current_index", "phase", "finished"
|
| 147 |
-
]:
|
| 148 |
-
if key in st.session_state:
|
| 149 |
-
del st.session_state[key]
|
| 150 |
-
st.rerun()
|
| 151 |
-
|
| 152 |
-
# --- Dashboard ---
|
| 153 |
st.markdown("## π Traffic Analysis Dashboard")
|
| 154 |
|
| 155 |
# 1. Total vehicles
|
| 156 |
-
total_vehicles = sum(st.session_state.counts.values())
|
| 157 |
-
st.markdown(
|
| 158 |
-
|
|
|
|
|
|
|
|
|
|
| 159 |
# 2. Bar chart for vehicle count
|
| 160 |
-
st.markdown("<
|
| 161 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
|
| 163 |
# 3. Most congested direction
|
| 164 |
busiest = max(st.session_state.counts.items(), key=lambda x: x[1])
|
| 165 |
-
st.markdown(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
-
|
| 168 |
base_time = 5
|
| 169 |
time_per_vehicle = 1
|
| 170 |
-
max_time =
|
| 171 |
-
|
| 172 |
-
green_times =
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
st.table(green_times)
|
| 191 |
|
| 192 |
# 5. Pie chart (optional)
|
| 193 |
import pandas as pd
|
| 194 |
df = pd.DataFrame.from_dict(st.session_state.counts, orient='index', columns=['Vehicles'])
|
| 195 |
st.markdown("<h4 style='font-size: 20px; font-weight: bold;'>π Traffic Share by Direction</h4>", unsafe_allow_html=True)
|
| 196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
import time
|
| 4 |
from ultralytics import YOLO
|
| 5 |
import io
|
| 6 |
+
import matplotlib.pyplot as plt
|
| 7 |
+
import pandas as pd
|
| 8 |
|
| 9 |
# --- Page Config ---
|
| 10 |
st.set_page_config(page_title="Smart Traffic Light System", layout="wide")
|
|
|
|
| 29 |
for col, direction in zip(cols, directions):
|
| 30 |
with col:
|
| 31 |
uploaded_images[direction] = st.file_uploader(f"{direction}", type=["jpg", "png"], key=direction)
|
| 32 |
+
|
| 33 |
# --- Process Once All Images Are Uploaded ---
|
| 34 |
if all(uploaded_images.values()):
|
| 35 |
# Initialize session state attributes if not already initialized
|
|
|
|
| 66 |
yellow_time = 3 # Fixed yellow duration
|
| 67 |
|
| 68 |
# --- Enhanced Signal Status Visualization ---
|
| 69 |
+
st.markdown("<br>", unsafe_allow_html=True)
|
| 70 |
st.markdown("### π₯ Current Signal Status")
|
| 71 |
|
| 72 |
signal_cols = st.columns(4)
|
|
|
|
| 105 |
st.markdown(f"### {status}\n**{direction}**\n**{count} Vehicles**")
|
| 106 |
|
| 107 |
# --- Timer UI ---
|
| 108 |
+
st.markdown("<br>", unsafe_allow_html=True)
|
| 109 |
st.markdown("### β± Signal Timer")
|
| 110 |
timer_placeholder = st.empty()
|
| 111 |
|
| 112 |
# --- Display Annotated Images Below Timer ---
|
| 113 |
+
st.markdown("<br>", unsafe_allow_html=True)
|
| 114 |
st.markdown("### πΌοΈ Detected Vehicles (Annotated Images)")
|
| 115 |
img_cols = st.columns(4)
|
| 116 |
for idx, direction in enumerate(directions):
|
|
|
|
| 143 |
else:
|
| 144 |
# Show completion message when all directions are done
|
| 145 |
st.success("### π¦ Simulation Complete! All directions have completed their green and yellow phases.")
|
| 146 |
+
counts = st.session_state.counts
|
| 147 |
+
sorted_directions = st.session_state.sorted_directions
|
| 148 |
+
# st.session_state.clear()
|
| 149 |
+
|
| 150 |
st.markdown("<br>", unsafe_allow_html=True)
|
| 151 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
st.markdown("## π Traffic Analysis Dashboard")
|
| 153 |
|
| 154 |
# 1. Total vehicles
|
| 155 |
+
total_vehicles = sum(st.session_state.counts.values())
|
| 156 |
+
st.markdown(
|
| 157 |
+
f"""
|
| 158 |
+
<br>
|
| 159 |
+
<h3 style='font-size: 24px; font-weight: bold;'>π Total Vehicles Detected: <span style='color: #4da6ff;'>{total_vehicles}</span></h3>""",unsafe_allow_html=True)
|
| 160 |
+
|
| 161 |
# 2. Bar chart for vehicle count
|
| 162 |
+
st.markdown("<br><h3 style='font-size: 24px; font-weight: bold;'>π¦ Vehicle Count per Direction</h3>", unsafe_allow_html=True)
|
| 163 |
+
# Create the bar chart
|
| 164 |
+
vehicle_counts = st.session_state.counts
|
| 165 |
+
fig, ax = plt.subplots(figsize=(4,4))
|
| 166 |
+
|
| 167 |
+
# Plot the bar char
|
| 168 |
+
ax.bar(vehicle_counts.keys(), vehicle_counts.values(), color='teal')
|
| 169 |
+
|
| 170 |
+
# Add numbers on top of the bars
|
| 171 |
+
for i, count in enumerate(vehicle_counts.values()):
|
| 172 |
+
ax.text(i, count + 0.5, str(count), ha='center', va='bottom', fontweight='bold', fontsize=8)
|
| 173 |
+
|
| 174 |
+
# Customize the chart
|
| 175 |
+
ax.set_ylabel('Vehicle Count')
|
| 176 |
+
ax.set_xlabel('Directions')
|
| 177 |
+
ax.set_title('Vehicle Count per Direction')
|
| 178 |
+
# Display the chart in Streamlit
|
| 179 |
+
# Show in small column
|
| 180 |
+
col1, col2, _ = st.columns([.3, .4, .3])
|
| 181 |
+
with col2:
|
| 182 |
+
st.pyplot(fig)
|
| 183 |
|
| 184 |
# 3. Most congested direction
|
| 185 |
busiest = max(st.session_state.counts.items(), key=lambda x: x[1])
|
| 186 |
+
st.markdown(
|
| 187 |
+
f"""
|
| 188 |
+
<br>
|
| 189 |
+
<h3 style='font-size: 24px; font-weight: bold;'>
|
| 190 |
+
π₯ Busiest Direction: <span style='color: red;'>{busiest[0]}</span> with {busiest[1]} vehicles
|
| 191 |
+
</h3>
|
| 192 |
+
""",
|
| 193 |
+
unsafe_allow_html=True
|
| 194 |
+
)
|
| 195 |
|
| 196 |
+
# 4. Green time per direction
|
| 197 |
base_time = 5
|
| 198 |
time_per_vehicle = 1
|
| 199 |
+
max_time = 25
|
| 200 |
+
# Use the same formula applied earlier
|
| 201 |
+
green_times = [
|
| 202 |
+
min(base_time + int(st.session_state.counts[d] / 2) * time_per_vehicle, max_time)
|
| 203 |
+
for d, _ in st.session_state.sorted_directions
|
| 204 |
+
]
|
| 205 |
+
green_df = pd.DataFrame({
|
| 206 |
+
"Direction": [d for d, _ in sorted_directions],
|
| 207 |
+
"Assigned Green Time (sec)": green_times
|
| 208 |
+
})
|
| 209 |
+
st.markdown("<br><h3 style='font-size: 24px; font-weight: bold;'>β±οΈ Assigned Green Time</h3>" , unsafe_allow_html=True)
|
| 210 |
+
col1, col2, _ = st.columns([.3, .4, .3])
|
| 211 |
+
with col2:
|
| 212 |
+
st.dataframe(green_df.style.set_properties(**{
|
| 213 |
+
'background-color': '#e8f5e9',
|
| 214 |
+
'color': 'green',
|
| 215 |
+
'font-size': '12px',
|
| 216 |
+
'font-weight': 'bold',
|
| 217 |
+
'text-align' : 'left'
|
| 218 |
+
}), use_container_width=True)
|
|
|
|
| 219 |
|
| 220 |
# 5. Pie chart (optional)
|
| 221 |
import pandas as pd
|
| 222 |
df = pd.DataFrame.from_dict(st.session_state.counts, orient='index', columns=['Vehicles'])
|
| 223 |
st.markdown("<h4 style='font-size: 20px; font-weight: bold;'>π Traffic Share by Direction</h4>", unsafe_allow_html=True)
|
| 224 |
+
fig2, ax2 = plt.subplots(figsize=(4, 4)) # Smaller size
|
| 225 |
+
ax2.pie(counts.values(), labels=counts.keys(), autopct='%1.1f%%', textprops={'fontsize': 8})
|
| 226 |
+
ax2.set_title("Traffic Distribution", fontsize=10)
|
| 227 |
+
col1, col2, _ = st.columns([.2, .4, .2])
|
| 228 |
+
with col2:
|
| 229 |
+
st.pyplot(fig2)
|
| 230 |
+
|
| 231 |
+
# 6. Waiting Time Calculation ---
|
| 232 |
+
st.markdown("<br>", unsafe_allow_html=True)
|
| 233 |
+
st.markdown("### β±οΈ Waiting Time Analysis")
|
| 234 |
+
# Use the already computed busiest direction
|
| 235 |
+
busiest_direction = busiest[0]
|
| 236 |
+
|
| 237 |
+
# Define green time per vehicle
|
| 238 |
+
time_per_vehicle = 1
|
| 239 |
+
# Initialize dictionary to store waiting times
|
| 240 |
+
waiting_times = {}
|
| 241 |
+
|
| 242 |
+
# Calculate waiting times for all directions except the busiest one
|
| 243 |
+
for direction in directions:
|
| 244 |
+
if direction == busiest_direction:
|
| 245 |
+
waiting_times[direction] = 0 # No wait for the first green
|
| 246 |
+
else:
|
| 247 |
+
# Waiting time is the sum of green times of all directions before this one (excluding busiest and current)
|
| 248 |
+
preceding_directions = [d for d, _ in st.session_state.sorted_directions if d != direction and d != busiest_direction]
|
| 249 |
+
wait = sum(min(5 + st.session_state.counts[d] * time_per_vehicle, 30) + 3 # green + yellow
|
| 250 |
+
for d in preceding_directions)
|
| 251 |
+
waiting_times[direction] = wait
|
| 252 |
+
|
| 253 |
+
# Display waiting times for each direction
|
| 254 |
+
waiting_time_data = pd.DataFrame({
|
| 255 |
+
"Direction": directions,
|
| 256 |
+
"Waiting Time (sec)": [waiting_times[direction] for direction in directions]
|
| 257 |
+
})
|
| 258 |
+
|
| 259 |
+
# Display waiting times in a table
|
| 260 |
+
# Show in small column
|
| 261 |
+
col1, col2, _ = st.columns([.3, .4, .3])
|
| 262 |
+
with col2:
|
| 263 |
+
st.dataframe(waiting_time_data.style.set_properties(**{
|
| 264 |
+
'background-color': '#f3f4f6',
|
| 265 |
+
'color': 'black',
|
| 266 |
+
'font-size': '12px',
|
| 267 |
+
'font-weight': 'bold'
|
| 268 |
+
}))
|
| 269 |
+
|
| 270 |
+
# Optionally, add a message for the waiting times
|
| 271 |
+
st.markdown("<br>", unsafe_allow_html=True)
|
| 272 |
+
st.markdown(
|
| 273 |
+
"""
|
| 274 |
+
The waiting times represent the total waiting time for vehicles at each direction based on the vehicle counts in other directions.
|
| 275 |
+
The higher the vehicle count in other directions, the higher the waiting time for the current direction.
|
| 276 |
+
"""
|
| 277 |
+
)
|
| 278 |
+
st.session_state.clear()
|