Home / Projects / TrafficStream2026
Project Software Apache-2.0

TrafficStream2026

Details

Architecture Python
License Apache-2.0

TrafficStream

Real-time vehicle detection on the City of Lexington, KY public traffic cameras
using the latest Ultralytics YOLO model. It
identifies and counts bicycles, cars, motorcycles, and buses.

How it works

TrafficStream pulls the live camera map from Lexington’s public traffic site and
runs YOLO object detection in one of two modes:

Script Mode What it does
stream_camera.py Live Streams a single camera through YOLO in real time, showing an annotated video window with live per-class vehicle counts.
download_cams.py Batch Grabs one frame from every online camera, runs YOLO on the set, and prints the current vehicle density per camera.

Requirements

  • Python 3.8+
  • Dependencies in requirements.txtultralytics,
    opencv-python, requests, torch, torchvision
  • A CUDA GPU is optional. Inference auto-detects the device and runs on CPU if no
    GPU is available.
  • YOLO model weights download automatically on first run.

Setup

python -m venv .venv
.venvScriptsActivate.ps1        # Windows PowerShell
pip install -r requirements.txt

(On macOS/Linux use source .venv/bin/activate.)

Usage

Live: stream one camera

python stream_camera.py --list              # list available cameras
python stream_camera.py "Main St"           # stream the first camera matching "Main St"
python stream_camera.py --url <hls-or-rtsp> # stream any direct stream URL

Press q (or close the window) to quit.

The live viewer is built to play at real time and never freeze the machine. The
City’s live HLS feeds are delivered in bursts — OpenCV/FFmpeg decodes a couple of
seconds of video almost instantly, then stalls until the next segment — so a naive
"show the newest decoded frame" viewer fast-forwards through each burst and then
freezes. Instead, the viewer:

  • tags every decoded frame with its presentation timestamp and holds it in a small,
    real-time playout buffer (JPEG-encoded so memory stays bounded at any
    resolution), then displays each frame on a wall-clock schedule — so video
    advances at 1× regardless of bursty delivery;
  • absorbs short network hiccups with the buffer, and on a genuine outage resyncs to
    the live edge with a forward skip
    instead of fast-forwarding through stale backlog;
  • reserves a CPU core for the OS/UI and decouples detection from display (cached
    boxes re-drawn every frame), so the window stays fluid even while the model runs.

A live FPS / inference-latency overlay shows headroom, and the resolved GPU name is
printed at startup so you can confirm inference is on your GPU.

Startup: these feeds open behind the live edge with ~20 s of buffered backlog,
so for the first ~20–30 s the viewer skips forward a few times to catch up to live;
after that it plays smoothly ~--latency seconds behind live. Raise
--resync-threshold for fewer, larger skips.

Performance tuning (knobs, with defaults):

  • --model (yolo26x.pt) — YOLO weights; extra-large by default (most accurate, ideal on a GPU). On a CPU-only machine pass --model yolo26n.pt (nano) to stay smooth. yolo26m.pt is a middle ground; yolo11n.pt is a fallback if your ultralytics predates YOLO26.
  • --imgsz (480) — inference resolution; lower to 320 for a big CPU win
  • --vid-stride (2) — run detection on every Nth frame (display stays fresh)
  • --max-det (50) — cap on detections per frame
  • --max-fps (15) — throttle the whole pipeline; lower to 10 for more OS headroom (0 = uncapped)
  • --device (auto) — auto (GPU if available else CPU), cpu, or a GPU index like 0. Explicitly requesting a GPU that has no CUDA now errors instead of silently using the CPU.

Real-time pacing (knobs, with defaults):

  • --latency (3.0) — seconds to sit behind the live edge (the playout-buffer depth). Larger rides through choppier networks more smoothly; smaller stays closer to live.
  • --resync-threshold (--latency + 4.0) — jump to live if playback drifts this far behind the live edge.
  • --buffer-cap (--latency + 8.0) — hard cap on buffered seconds (memory bound).
  • --clock (auto) — pacing clock source: auto/pts (timestamp-driven), fps (nominal frame rate), or legacy (no pacing, old newest-frame behavior).

Batch: vehicle density across all cameras

python download_cams.py

Saves a frame from each online camera into images/, runs YOLO, and prints a line
like:

Traffic Density @ Main St & Broadway: 7 vehicle(s) [5 car, 1 bus, 1 bicycle]

Batch: classify saved images with the largest model

Run the heaviest, most accurate model (yolo26x.pt) over everything already in
images/ and get a per-image report plus a grand total. Annotated copies are saved
to runs/detect/ (gitignored).

python classify_images.py                 # largest model, vehicles only
python classify_images.py --all-classes   # detect every COCO class
python classify_images.py --imgsz 1280    # better on small/distant vehicles
python classify_images.py --no-save       # skip writing annotated images

(The large model is fine here because it’s a one-shot batch, not a live loop — it
still reserves a CPU core for the OS/UI while it runs.)

Vehicle classes

Detection is restricted to four COCO classes:

Index Class
1 bicycle
2 car
3 motorcycle
5 bus

Project layout

stream_camera.py     Live single-camera detection
download_cams.py     Batch snapshot + density report
classify_images.py   Batch-classify images/ with the largest model
check_cam_online.py  Fetches and caches the camera map (CheckCamOnline)
threaded_camera.py   Latest-frame threaded capture helper
requirements.txt     Python dependencies
data/                Cached camera map JSON   (generated, gitignored)
images/              Captured camera frames   (generated, gitignored)

Model

Uses the latest Ultralytics YOLO model (YOLO26), which auto-downloads on first
run. If your installed ultralytics predates YOLO26, set the model to a yolo11
variant (e.g. yolo11n.pt) via --model or the MODEL_WEIGHTS constant.

Data source

Camera feeds come from the City of Lexington, KY public traffic map:
https://trafficvid.lexingtonky.gov/publicmap/. Intended for personal and
educational use — please respect the city’s terms of service.

License

Licensed under the Apache License, Version 2.0 — Copyright 2026 Samuel Armstrong.
See LICENSE for the full text.


Imported from gh:Kentucky-Open-Science/TrafficStream2026. Source last updated 2026-06-18. Synced 2026-07-27.