Adoption commited on
Commit
1b3baae
·
verified ·
1 Parent(s): 2897b3e

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +131 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,133 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ import cv2
3
+ from ultralytics import YOLO
4
+ import tempfile
5
+ import time
6
+ from crewai import Agent, Task, Crew
7
+ from langchain_groq import ChatGroq
8
 
9
+ # --- CONFIG ---
10
+ st.set_page_config(page_title="CityFlow AI", page_icon="🚦", layout="wide")
11
+
12
+ # --- SIDEBAR ---
13
+ with st.sidebar:
14
+ st.header("🚦 CityFlow Control")
15
+ groq_api_key = st.text_input("Groq API Key", type="password")
16
+ uploaded_file = st.file_uploader("Upload CCTV Footage", type=['mp4', 'mov'])
17
+ confidence = st.slider("Detection Confidence", 0.0, 1.0, 0.3)
18
+
19
+ # --- MAIN APP ---
20
+ st.title("🚦 CityFlow: Autonomous Traffic Management")
21
+ st.markdown("Real-time computer vision + Multi-Agent reasoning to optimize traffic flow.")
22
+
23
+ # Initialize Model (YOLOv8n is small and fast)
24
+ @st.cache_resource
25
+ def load_model():
26
+ return YOLO('yolov8n.pt')
27
+
28
+ model = load_model()
29
+
30
+ # --- THE AGENTS ---
31
+ if groq_api_key:
32
+ llm = ChatGroq(temperature=0, model_name="llama-3.3-70b-versatile", groq_api_key=groq_api_key)
33
+
34
+ # Agent 1: The Traffic Analyst (Reads the data)
35
+ analyst = Agent(
36
+ role='Traffic Data Analyst',
37
+ goal='Analyze vehicle counts and congestion levels to determine traffic severity.',
38
+ backstory="You are an expert in urban flow. You look at raw numbers (car counts) and decide if it's 'Light', 'Heavy', or 'Gridlock'.",
39
+ llm=llm,
40
+ verbose=False
41
+ )
42
+
43
+ # Agent 2: The Signal Controller (Makes the decision)
44
+ controller = Agent(
45
+ role='Signal Control Officer',
46
+ goal='Decide the optimal traffic light duration based on severity.',
47
+ backstory="You control the city lights. If an ambulance is seen, you MUST open the lane. If traffic is heavy, extend Green light duration.",
48
+ llm=llm,
49
+ verbose=False
50
+ )
51
+
52
+ # --- VIDEO PROCESSING LOOP ---
53
+ if uploaded_file and groq_api_key:
54
+ # Save temp file
55
+ tfile = tempfile.NamedTemporaryFile(delete=False)
56
+ tfile.write(uploaded_file.read())
57
+ cap = cv2.VideoCapture(tfile.name)
58
+
59
+ col1, col2 = st.columns([2, 1])
60
+
61
+ with col1:
62
+ st_frame = st.empty()
63
+
64
+ with col2:
65
+ st_metrics = st.empty()
66
+ st_decision = st.empty()
67
+
68
+ frame_count = 0
69
+
70
+ # Process Video
71
+ while cap.isOpened():
72
+ ret, frame = cap.read()
73
+ if not ret:
74
+ break
75
+
76
+ frame_count += 1
77
+
78
+ # Only run AI every 10 frames to keep it fast
79
+ if frame_count % 10 == 0:
80
+
81
+ # 1. PERCEPTION (YOLO)
82
+ results = model.track(frame, persist=True, conf=confidence)
83
+
84
+ # Count Vehicles
85
+ car_count = 0
86
+ emergency_count = 0
87
+
88
+ # Classes: 2=Car, 3=Motorcycle, 5=Bus, 7=Truck
89
+ # We assume class 0 is person, so we filter for vehicles.
90
+ # Note: Standard COCO dataset doesn't distinguish "ambulance",
91
+ # so we'll simulate emergency logic if we see a Truck (class 7) for this demo.
92
+
93
+ for result in results:
94
+ boxes = result.boxes
95
+ for box in boxes:
96
+ cls = int(box.cls[0])
97
+ if cls in [2, 3, 5, 7]:
98
+ car_count += 1
99
+ if cls == 7: # Simulating "Truck/Emergency" for demo logic
100
+ emergency_count += 1
101
+
102
+ # Draw Boxes on Frame
103
+ res_plotted = results[0].plot()
104
+
105
+ # 2. REASONING (CrewAI)
106
+ # We pass the real-time data to the agents
107
+
108
+ task_analyze = Task(
109
+ description=f"Current Status: {car_count} vehicles detected. {emergency_count} heavy/emergency vehicles. Analyze congestion level.",
110
+ agent=analyst,
111
+ expected_output="A short status: 'Light', 'Moderate', 'Critical'."
112
+ )
113
+
114
+ task_control = Task(
115
+ description="Based on the analysis, decide the Green Light duration (in seconds). If Status is Critical or Emergency detected, set to MAX (60s).",
116
+ agent=controller,
117
+ expected_output="JSON: {'status': '...', 'green_light_duration': 45, 'reason': '...'}"
118
+ )
119
+
120
+ # Creating a mini-crew for this single frame decision
121
+ # (In production, you'd run this async, not blocking the video)
122
+ crew = Crew(agents=[analyst, controller], tasks=[task_analyze, task_control])
123
+ decision = crew.kickoff()
124
+
125
+ # 3. VISUALIZATION
126
+ st_frame.image(res_plotted, channels="BGR")
127
+
128
+ st_metrics.metric(label="Vehicles Detected", value=car_count)
129
+ st_metrics.metric(label="Emergency/Heavy", value=emergency_count)
130
+
131
+ st_decision.info(f"🤖 AI Decision: \n\n{decision}")
132
+
133
+ cap.release()