Codebase
Codebase
frontend) that supports both the four-zone intersection mode and a two-point (front/back) mode.
We’ll show:
1. Folder structure
2. Pipeline script (standalone Python) with modular direction logic
3. [Link] (defines both modes)
4. Django project
o [Link] (with DRF/JWT, PostgreSQL)
o traffic/[Link]
o traffic/[Link]
o traffic/[Link]
o traffic/[Link]
o backend/[Link]
o traffic/management/commands/ingest_to_pg.py
o [Link]
5. React frontend (created via create-react-app)
o src/[Link] (Axios + JWT)
o src/contexts/[Link] (login state)
o src/components/[Link]
o src/components/[Link] (per-minute counts)
o src/components/[Link] (directional flows)
o src/[Link] (routing, protected routes)
o src/[Link]
o [Link] (dependencies)
You can clone, drop into each subfolder, install dependencies, and run each piece independently.
1. Folder Structure
markdown
CopyEdit
smart_traffic/
├── pipeline/ # → Standalone ingestion pipeline
│ ├── ingest_to_pg.py
│ ├── traffic_pipeline/
│ │ ├── __init__.py
│ │ └── [Link]
│ └── config/
│ └── [Link]
│
├── backend/ # → Django project
│ ├── backend/
│ │ ├── __init__.py
│ │ ├── [Link]
│ │ ├── [Link]
│ │ ├── [Link]
│ │ └── [Link]
│ │
│ ├── traffic/
│ │ ├── __init__.py
│ │ ├── [Link]
│ │ ├── [Link]
│ │ ├── management/
│ │ │ └── commands/
│ │ │ └── ingest_to_pg.py
│ │ ├── migrations/
│ │ │ └── __init__.py
│ │ ├── [Link]
│ │ ├── [Link]
│ │ ├── [Link]
│ │ ├── [Link]
│ │ └── [Link]
│ │
│ ├── [Link]
│ └── [Link]
│
└── frontend/ # → React app (create-react-app)
├── public/
│ ├── [Link]
│ └── ...
├── src/
│ ├── [Link]
│ ├── contexts/
│ │ └── [Link]
│ ├── components/
│ │ ├── [Link]
│ │ ├── [Link]
│ │ ├── [Link]
│ │ └── [Link]
│ ├── [Link]
│ ├── [Link]
│ └── ...
└── [Link]
point2:
type: points
front:
x1_frac: 0.45; y1_frac: 0.00; x2_frac: 0.55; y2_frac: 0.05
back:
x1_frac: 0.45; y1_frac: 0.95; x2_frac: 0.55; y2_frac: 1.00
2.2 traffic_pipeline/[Link]
python
CopyEdit
# pipeline/traffic_pipeline/[Link]
import cv2
import yaml
from ultralytics import YOLO
from collections import defaultdict
class TrafficPipeline:
"""
Unified pipeline that supports both:
- 4-way intersection mode ("intersection4")
- 2-point front/back mode ("point2")
Load scenario definitions from YAML, then run YOLOv8 + ByteTrack,
draw boxes, and count when centroid hits a zone.
"""
# 5) YOLO thresholds
self.min_conf = min_conf
[Link] = iou
self.frame_shape = (H, W)
return frame
def reset_minute(self):
"""
Snapshot per-minute counts and reset counting state.
Returns: {cls→{direction→count}}.
"""
snapshot = dict([Link])
[Link]()
[Link]()
return snapshot
__init__ takes:
o model_path & data_yaml for YOLO
o scenarios_yaml (path to [Link])
o mode = "intersection4" or "point2"
o thresholds min_conf & iou
_init_zones builds pixel rectangles from fractional definitions.
process_frame: draws zones, runs detection+tracking, draws green boxes, counts when
centroid enters a zone/point, recolors counted boxes.
reset_minute returns the aggregated dictionary and clears counters.
2.3 ingest_to_pg.py
python
CopyEdit
# pipeline/ingest_to_pg.py
import os
import time
import cv2
import yaml
import argparse
import psycopg2
from [Link] import execute_values
from collections import defaultdict
from datetime import datetime, timedelta
#
─────────────────────────────────────────────────────────────────────────────
# 1) CONFIGURATION
#
─────────────────────────────────────────────────────────────────────────────
VIDEO_FOLDER = args.video_folder
MODEL_PATH = [Link]
DATA_YAML = args.data_yaml
SCENARIOS_YAML= [Link]
MIN_CONF = args.min_conf
IOU = [Link]
PG_HOST = args.pg_host
PG_PORT = args.pg_port
PG_DB = args.pg_db
PG_USER = args.pg_user
PG_PASSWORD = args.pg_pass
#
─────────────────────────────────────────────────────────────────────────────
# 2) Database Helper
#
─────────────────────────────────────────────────────────────────────────────
def connect_db():
return [Link](
host = PG_HOST,
port = PG_PORT,
dbname = PG_DB,
user = PG_USER,
password = PG_PASSWORD
)
#
─────────────────────────────────────────────────────────────────────────────
# 3) MAIN: Process All MP4 Files
#
─────────────────────────────────────────────────────────────────────────────
def main():
conn = connect_db()
pipeline = TrafficPipeline(MODEL_PATH, DATA_YAML, SCENARIOS_YAML,
[Link], MIN_CONF, IOU)
# Per-minute scheduling
next_min = [Link]().replace(second=0, microsecond=0) +
timedelta(minutes=1)
buffer = [] # collect (cls, direction, count) every frame
while True:
ret, frame = [Link]()
if not ret:
print("☑️ End of this video.")
break
[Link]()
[Link]()
print("✅ All videos processed. Pipeline complete.")
if __name__ == "__main__":
main()
1. Put all your MP4 files into a local folder named videos/ (same level as
ingest_to_pg.py).
2. Place your [Link] (YOLOv8 weights) and [Link] (with class names) in the
same directory (or adjust paths).
3. Ensure you have a PostgreSQL database called smart_traffic_db, user traffic_user
with password traffic_pass, and tables will be created automatically by Django (see
next section).
4. From pipeline/, run:
bash
CopyEdit
python ingest_to_pg.py --mode intersection4
or:
bash
CopyEdit
python ingest_to_pg.py --mode point2
The script will loop through every .mp4 in videos/, process frames, and bulk‐insert
counts per minute into the traffic_vehiclecount table.
3. Django DRF Backend
Create a Django project in smart_traffic/backend/. Below are all the necessary files.
3.1 backend/[Link]
php
CopyEdit
Django>=4.2
djangorestframework
djangorestframework-simplejwt
psycopg2-binary
celery
redis
(You may install extra packages if you use Celery for ingestion.)
3.2 backend/backend/[Link]
python
CopyEdit
# backend/backend/[Link]
BASE_DIR = Path(__file__).resolve().[Link]
SECRET_KEY = 'replace-with-your-secret-key'
DEBUG = True
ALLOWED_HOSTS = []
INSTALLED_APPS = [
'[Link]',
'[Link]',
'[Link]',
'[Link]',
'[Link]',
'[Link]',
'rest_framework',
'traffic',
]
MIDDLEWARE = [
'[Link]',
'[Link]',
'[Link]',
'[Link]',
'[Link]',
'[Link]',
'[Link]',
]
ROOT_URLCONF = '[Link]'
TEMPLATES = [
{
'BACKEND': '[Link]',
'DIRS': [], # no templates needed
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'[Link].context_processors.debug',
'[Link].context_processors.request',
'[Link].context_processors.auth',
'[Link].context_processors.messages',
],
},
},
]
WSGI_APPLICATION = '[Link]'
# PostgreSQL settings
DATABASES = {
'default': {
'ENGINE': '[Link]',
'NAME': 'smart_traffic_db',
'USER': 'traffic_user',
'PASSWORD': 'traffic_pass',
'HOST': 'localhost',
'PORT': '5432',
}
}
AUTH_PASSWORD_VALIDATORS = [
{
'NAME':
'[Link].password_validation.UserAttributeSimilarityValidator',
},
# (Add other validators as desired)
]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
STATIC_URL = 'static/'
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
}
3.3 backend/backend/[Link]
python
CopyEdit
# backend/backend/[Link]
router = DefaultRouter()
[Link](r'traffic/counts', VehicleCountViewSet, basename='counts')
urlpatterns = [
path('admin/', [Link]),
path('api/', include([Link])),
path('api/auth/token/', TokenObtainPairView.as_view(),
name='token_obtain_pair'),
path('api/auth/refresh/', TokenRefreshView.as_view(),
name='token_refresh'),
]
3.4 backend/traffic/[Link]
python
CopyEdit
# backend/traffic/[Link]
class Intersection([Link]):
name = [Link](max_length=100, unique=True)
def __str__(self):
return [Link]
class VehicleClass([Link]):
name = [Link](max_length=50, unique=True)
def __str__(self):
return [Link]
class VehicleCount([Link]):
intersection = [Link](Intersection, on_delete=[Link])
vehicle_class = [Link](VehicleClass, on_delete=[Link])
direction = [Link](max_length=50)
timestamp = [Link]()
count = [Link]()
scenario = [Link](max_length=50, default='intersection4')
class Meta:
unique_together =
('intersection','vehicle_class','direction','timestamp','scenario')
indexes = [
[Link](fields=['intersection','timestamp']),
[Link](fields=['vehicle_class','timestamp']),
[Link](fields=['scenario','timestamp']),
]
3.5 backend/traffic/[Link]
python
CopyEdit
# backend/traffic/[Link]
class VehicleCountSerializer([Link]):
class Meta:
model = VehicleCount
fields = '__all__'
3.6 backend/traffic/[Link]
python
CopyEdit
# backend/traffic/[Link]
class VehicleCountViewSet([Link]):
"""
List / retrieve VehicleCount records.
Supports filters: ?
intersection=<id>&start=<ISO>&end=<ISO>&class=<name>&direction=<name>&scenario
=<name>
"""
queryset = [Link]().order_by('-timestamp')
serializer_class = VehicleCountSerializer
def get_queryset(self):
qs = super().get_queryset()
f = [Link].query_params
# Filter by intersection id
if 'intersection' in f:
qs = [Link](intersection__id=f['intersection'])
# Filter by scenario
if 'scenario' in f:
qs = [Link](scenario=f['scenario'])
return qs
3.7 backend/traffic/[Link]
python
CopyEdit
# backend/traffic/[Link]
3.8 backend/traffic/management/commands/ingest_to_pg.py
We’re reusing the same ingestion script but as a Django command. This allows python
[Link] ingest_to_pg --mode intersection4. Create:
python
CopyEdit
# backend/traffic/management/commands/ingest_to_pg.py
import os
import cv2
import yaml
from [Link] import BaseCommand
from [Link] import timezone
from collections import defaultdict
from datetime import datetime, timedelta
from traffic_pipeline.core import TrafficPipeline
from [Link] import Intersection, VehicleClass, VehicleCount
from [Link] import execute_values
from [Link] import connection
class Command(BaseCommand):
help = "Run TrafficPipeline on MP4s in 'videos/' folder and insert counts
into Postgres."
# 1) Set up pipeline
model_path = [Link]([Link](), '[Link]')
data_yaml = [Link]([Link](), '[Link]')
scenarios = [Link]([Link](), 'config/[Link]')
# 2) List MP4s
mp4s = sorted([f for f in [Link](video_folder) if
[Link]().endswith('.mp4')])
while True:
ret, frame = [Link]()
if not ret:
break
_ = pipeline.process_frame(frame)
# Collect current minute’s counts
for cls_nm, dirs in [Link]():
for dir_nm, cnt in [Link]():
[Link]((cls_nm, dir_nm, cnt))
[Link]()
[Link]()
[Link]()
next_min += timedelta(minutes=1)
[Link]()
[Link]([Link](f"Finished {vpath}"))
# 2) VehicleClass
vc_ids = {}
for cls_nm in minute_counts:
[Link]("SELECT id FROM traffic_vehicleclass WHERE name=
%s;", (cls_nm,))
r = [Link]()
if r:
vc_ids[cls_nm] = r[0]
else:
[Link]("INSERT INTO traffic_vehicleclass(name)
VALUES(%s) RETURNING id;", (cls_nm,))
vc_ids[cls_nm] = [Link]()[0]
# 3) Build rows
rows = []
for cls_nm, dirs in minute_counts.items():
for dir_nm, cnt in [Link]():
[Link]((
inter_id,
vc_ids[cls_nm],
dir_nm,
minute_dt,
cnt,
scenario
))
# 4) Bulk insert
sql = """
INSERT INTO traffic_vehiclecount
(intersection_id, vehicle_class_id, direction, timestamp, count,
scenario)
VALUES %s
ON CONFLICT DO NOTHING;
"""
execute_values(cur, sql, rows)
[Link]()
This is effectively the same as our standalone script but integrated into Django’s
management command system.
Run it via:
bash
CopyEdit
python [Link] ingest_to_pg --mode intersection4
or:
bash
CopyEdit
python [Link] ingest_to_pg --mode point2
4. React Frontend
Below is a create-react-app–style frontend that:
4.1 frontend/[Link]
json
CopyEdit
{
"name": "smart-traffic-frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.4.0",
"[Link]": "^4.3.0",
"react": "^18.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.4.0",
"react-scripts": "5.0.1"
},
"scripts": {
"start": "PORT=3000 react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test"
}
}
4.2 frontend/src/[Link]
js
CopyEdit
// frontend/src/[Link]
4.3 frontend/src/contexts/[Link]
jsx
CopyEdit
// frontend/src/contexts/[Link]
return (
<[Link] value={{ token, user, login, logout }}>
{children}
</[Link]>
);
}
4.4 frontend/src/components/[Link]
jsx
CopyEdit
// frontend/src/components/[Link]
return (
<div style={{ maxWidth: 400, margin: '50px auto' }}>
<h2>Login</h2>
<form onSubmit={handleSubmit}>
<div>
<label>Username:</label><br/>
<input
type="text"
value={username}
onChange={e => setUsername([Link])}
required
/>
</div>
<div style={{ marginTop: 10 }}>
<label>Password:</label><br/>
<input
type="password"
value={password}
onChange={e => setPassword([Link])}
required
/>
</div>
{error && <p style={{ color: 'red' }}>{error}</p>}
<button type="submit" style={{ marginTop: 15 }}>Log In</button>
</form>
</div>
);
}
4.5 frontend/src/components/[Link]
jsx
CopyEdit
// frontend/src/components/[Link]
[Link](
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
);
const options = {
responsive: true,
plugins: {
title: { display: true, text: title },
legend: { position: 'bottom' }
}
};
Expects:
o labels: e.g. ['15:00','15:01','15:02',...]
o series: e.g.
js
CopyEdit
[
{ label:'SUV', data:[12,15,9,...], borderColor:'blue',
backgroundColor:'rgba(0,0,255,0.2)' },
{ label:'bus', data:[3,4,2,...], borderColor:'red',
backgroundColor:'rgba(255,0,0,0.2)' }
]
4.6 frontend/src/components/[Link]
jsx
CopyEdit
// frontend/src/components/[Link]
[Link](
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend
);
const options = {
responsive: true,
plugins: {
title: { display: true, text: title }
},
scales: {
x: { stacked: true },
y: { stacked: true }
}
};
4.7 frontend/src/components/[Link]
jsx
CopyEdit
// frontend/src/components/[Link]
[Link](item => {
const ts = [Link]; // e.g. "2025-05-10T15:07:00Z"
if (!byTimestamp[ts]) byTimestamp[ts] = {};
const key = `${item.vehicle_class}:${[Link]}`;
byTimestamp[ts][key] = [Link];
[Link](item.vehicle_class);
[Link]([Link]);
});
return {
labels: [Link](ts => [Link](11,19)), // HH:MM:SS
classSeries,
dirSeries
};
};
4.9 frontend/src/[Link]
jsx
CopyEdit
// frontend/src/[Link]
sql
CopyEdit
CREATE DATABASE smart_traffic_db;
CREATE USER traffic_user WITH ENCRYPTED PASSWORD 'traffic_pass';
GRANT ALL PRIVILEGES ON DATABASE smart_traffic_db TO traffic_user;
bash
CopyEdit
cd smart_traffic/backend
python3 -m venv .venv
source .venv/bin/activate # (Windows: .venv\Scripts\Activate.ps1)
pip install -r [Link]
4. Run migrations:
bash
CopyEdit
python [Link] makemigrations traffic
python [Link] migrate
5. Create superuser:
bash
CopyEdit
python [Link] createsuperuser
bash
CopyEdit
cd ../pipeline
python3 -m venv .venv
source .venv/bin/activate
pip install opencv-python ultralytics pyyaml psycopg2-binary
2. Place:
o [Link] (YOLOv8 weights)
o [Link] (class names YAML)
o config/[Link] (with scenarios)
o MP4 files into pipeline/videos/
3. Run:
bash
CopyEdit
python ingest_to_pg.py --mode intersection4
Or:
bash
CopyEdit
python ingest_to_pg.py --mode point2
arduino
CopyEdit
POST [Link]
Body: { "username": "...", "password": "..." }
o Refresh token:
arduino
CopyEdit
POST [Link]
Body: { "refresh": "<refresh_token>" }
Opens at [Link]
Login page → enter superuser credentials → redirects to /dashboard.
In Dashboard:
1. Choose Mode (intersection4 or point2).
2. Pick Start & End via datetime selector.
3. Click Fetch → see two charts:
LineChart: per-minute total counts by vehicle class.
StackedBar: stacks counts by direction.
The charts automatically adapt to whichever direction strings the API returns.
6. Summary
1. Pipeline (pipeline/ingest_to_pg.py) runs YOLOv8+ByteTrack, counts vehicles by
direction (4 zones or 2 points), and bulk-inserts per-minute counts (with scenario) into
PostgreSQL.
2. Django DRF (backend/) models reflect the same tables; serializers/viewsets expose
/api/traffic/counts/ with filtering on intersection, timestamp range, class,
direction, and scenario. JWT auth protects the endpoints.
3. React (frontend/) provides a clean login form, a “Dashboard” that:
o Lets users select mode, start, and end.
o Fetches the data and draws a LineChart (by vehicle class) and a StackedBar (by
direction).
o Maintains JWT in AuthContext, attaches it to all API calls.
Everything is integrated:
This codebase fulfills your requirement for a fully modular, multi-mode traffic monitoring
pipeline with end-to-end integration. Enjoy building and iterating on it!