RadarHub Documentation
Version 1.0 · AI speed radar and traffic vision engine
Overview
RadarHub turns any camera into a traffic analytics and speed measurement system. For every frame of video it:
- Detects vehicles (car, truck, bus, motorcycle) with a pretrained YOLO model.
- Tracks each vehicle with a persistent ID across frames.
- Measures speed in real km/h using a calibrated perspective transform.
- Counts vehicles by type as they cross a virtual line.
- Flags violations above your speed limit, with a photo snapshot of each speeder.
- Knows who is moving: every vehicle is classified as moving (green/red), stopped (amber, was moving), or parked (dim gray, never moved). Only moving vehicles are counted, speed-labelled and fined, so streets full of parked cars stay clean.
- Streams everything to a live web dashboard in your browser.
Everything runs on your own hardware. No footage ever leaves your machine.
Requirements
| Component | Minimum | Recommended |
|---|---|---|
| Python | 3.9 | 3.11+ |
| RAM | 4 GB | 8 GB |
| GPU | None (CPU works) | Any NVIDIA GPU for real-time HD |
| OS | Windows 10+, macOS 12+, Ubuntu 20.04+ | |
yolov8n nano model. With an NVIDIA GPU, set "device": "0" in the config and optionally step up to yolov8s or yolov8m for higher accuracy.Installation
# 1. Unzip RadarHub, then inside the folder:
python -m venv .venv
# 2. Activate the environment
# Windows:
.venv\Scripts\activate
# macOS / Linux:
source .venv/bin/activate
# 3. Install dependencies
pip install -r requirements.txt
The first detection run automatically downloads the YOLO model weights (about 6 MB for the nano model).
opencv-python with opencv-python-headless in requirements.txt before installing.Quick start
# Live dashboard on your webcam, then open http://localhost:8080
python main.py dashboard --source 0
# Live dashboard on an IP camera
python main.py dashboard --source "rtsp://user:pass@192.168.1.10:554/stream"
# Process a video file into an annotated MP4 + violations CSV
python main.py process --source road.mp4 --out annotated.mp4
Or use the one-command launcher, which creates the environment automatically on first run:
./run.sh road.mp4
Video inputs
RadarHub accepts three source types, all through the same --source flag or the dashboard's source field:
| Type | Value | Notes |
|---|---|---|
| Video file | road.mp4 | Timestamps come from the file's FPS, so speed math stays exact even if processing is slower than real time. |
| IP / CCTV camera | rtsp://user:pass@ip:554/stream | Any RTSP or HTTP(S) stream that OpenCV can open. This covers virtually every network camera. |
| Webcam / OBS | 0 (or 1, 2...) | Device index. OBS Virtual Camera appears as a normal webcam, so you can pipe anything through OBS. |
You can also upload a video file directly in the dashboard; RadarHub switches to it immediately.
The dashboard
Start it with python main.py dashboard --source ... and open http://localhost:8080. It shows:
- Live annotated video: boxes are green under the limit and red over it, each with the vehicle's ID, type and current km/h.
- Total and per-type counters from the counting line.
- Live speeds of every tracked vehicle.
- Violations feed with the photo snapshot of each speeder.
- Controls: switch source, change the speed limit, upload a file, export CSV.
- Use this device camera: streams your phone's or laptop's camera to the server for processing, turning any phone into a radar camera. Browsers require a secure context for camera access, so this works on
http://localhostor any https:// address.
--host 0.0.0.0 and browse to http://<machine-ip>:8080.Calibration
Calibration is what turns pixel movement into real km/h. You do it once per camera position. The camera must be fixed (mounted or on a tripod); a moving camera invalidates the pixel-to-road mapping.
Option A: in the dashboard (easiest)
Click Calibrate under the video, tap the 4 corners of a road rectangle you can measure (top-left, top-right, bottom-right, bottom-left), enter its real width and length in meters, and save. It activates immediately and persists to your config.
Option B: the desktop tool
- Find a rectangle on the road whose real size you know. A single lane (typically 3.5 m wide) over a measured stretch (for example 20 m between two road markings) is perfect.
- Run:
python main.py calibrate --source road.mp4 --width 3.5 --length 20 - Click the 4 corners in order: top-left, top-right, bottom-right, bottom-left.
- Press
sto save. The points and sizes are written toconfig.json.
Tips for accurate calibration
- Choose points on the road surface itself, never on objects with height.
- The bigger the rectangle, the smaller the error.
- Lane widths and lane markings have standardized sizes in most countries; check your local road standards for reliable reference measurements.
Violations and CSV export
Whenever a tracked vehicle's smoothed speed exceeds speed_limit_kmh, RadarHub records one violation for that vehicle:
- A cropped photo snapshot saved to
data/violations/. - The vehicle's ID, type, speed, the limit, and timestamp.
Export everything to CSV with the dashboard's Export button, or find it at data/violations.csv after a process run. Each vehicle is logged at most once, so one speeder does not flood your report.
Configuration reference (config.json)
{
"source": "0",
"model": "models/yolov8n.pt",
"conf": 0.35,
"imgsz": 640,
"device": "cpu",
"speed_limit_kmh": 50.0,
"count_line_y": 0.5,
"speed_window": 8,
"smooth": 5,
"data_dir": "data",
"calibration": {
"points": [[0,0],[1,0],[1,1],[0,1]],
"width_m": 10.0,
"length_m": 30.0
}
}
| Key | Meaning |
|---|---|
source | Default video source (file path, RTSP URL, or webcam index as a string). |
model | YOLO weights. yolov8n (fastest) to yolov8x (most accurate). Downloaded automatically. |
conf | Detection confidence threshold, 0 to 1. Raise it to cut false positives. |
imgsz | Inference resolution. 640 is the sweet spot; 320 doubles CPU speed at some accuracy cost. |
device | "cpu" or "0" for the first NVIDIA GPU. |
speed_limit_kmh | Vehicles above this smoothed speed are flagged. |
count_line_y | Counting line height as a fraction of frame height (0.0 top, 1.0 bottom). |
speed_window | Position samples kept per vehicle for the speed calculation. |
smooth | Median smoothing window applied to speed readings. |
stabilize | Camera-shake compensation for handheld or vibrating cameras: the shared apparent motion of non-moving vehicles is treated as camera motion and subtracted. Keep false for fixed CCTV/RTSP mounts (default). |
calibration | The 4 image points and the real-world width/length in meters. Set via the calibration tool. |
CLI commands
| Command | What it does |
|---|---|
python main.py dashboard --source X | Live web dashboard on any source. Flags: --host, --port, --limit, --config. |
python main.py process --source X --out Y | Process a file into an annotated MP4 and export the violations CSV. |
python main.py calibrate --source X --width W --length L | Point-and-click calibration; saves into config.json. |
./run.sh [source] | One-command launcher: creates the venv, installs dependencies, starts the dashboard on port 8080. |
HTTP API
The dashboard server exposes a small JSON API you can integrate with:
| Endpoint | Method | Returns |
|---|---|---|
/stream.mjpg | GET | Live annotated video as MJPEG (embeddable in any <img> tag). |
/stats | GET | Live JSON: counts by class, active tracks, live speeds, violation count, FPS. |
/violations | GET | All violation records as JSON. |
/violations.csv | GET | CSV download of all violations. |
/snap/{file} | GET | A violation snapshot image. |
/upload | POST | Multipart video upload; switches processing to the uploaded file. |
/ingest?limit=N | POST | Raw JPEG body: push frames from any source (the dashboard's "Use this device camera" button uses this). The server runs the full pipeline on each pushed frame. |
/control | POST | {"action":"start","source":"...","limit":60} or {"action":"stop"}. |
How speed is measured
A camera sees the road in perspective: a pixel near the camera covers centimeters, a pixel far away covers meters. Measuring speed in pixels is therefore meaningless. RadarHub does it properly:
- Your 4 calibration points define a quadrilateral in the image that corresponds to a real rectangle on the road with known width and length.
- From these, RadarHub computes a perspective transform (homography) that maps any image point on the road to metric coordinates.
- Each vehicle's ground point (the bottom-center of its box, where it touches the road) is transformed into meters every frame.
- Speed = distance travelled on the ground plane divided by elapsed time, converted to km/h.
- A median filter over recent readings removes jitter from detection noise.
This is the same principle used by professional video-based traffic measurement systems.
Architecture
radar/ core engine (importable, testable without a GPU)
config.py configuration dataclasses + JSON persistence
detector.py YOLO wrapper, vehicle-class filter
tracker.py persistent IDs across frames
speed.py homography speed estimator
counter.py line-crossing counts per class
violations.py violation log + snapshots + CSV
annotator.py overlay renderer (boxes, labels, stats panel)
pipeline.py frame in, annotated frame + stats out
source.py file / RTSP / webcam input
app/
server.py FastAPI dashboard server
static/ dashboard UI
main.py CLI entry point
calibrate.py calibration tool
tests/ pipeline test, YOLO smoke test, demo renderer
The detector is injected into the pipeline, so the whole engine can be tested with a fake detector, and the heavy ML dependency loads only when detection actually runs.
Performance tuning
| Goal | What to change |
|---|---|
| Faster on CPU | Keep yolov8n, set "imgsz": 320, process files instead of live streams. |
| Real-time live HD | Set "device": "0" with an NVIDIA GPU and installed CUDA drivers. |
| Higher accuracy | Step the model up: yolov8s.pt, yolov8m.pt. Each step is roughly 2x slower. |
| Fewer false detections | Raise "conf" to 0.45 or 0.5. |
| Smoother speeds | Raise "smooth" to 7 or 9 (slightly slower reaction to speed changes). |
Troubleshooting
"Could not open source"
The path, URL or device index is wrong, or the codec is unsupported. For RTSP, test the URL in VLC first. For webcams, try index 1 or 2 if 0 fails.
"operator torchvision::nms does not exist"
Your torch and torchvision versions do not match. Fix by installing both from the same index:
pip install --force-reinstall torchvision --index-url https://download.pytorch.org/whl/cpu
(Remove --index-url for GPU builds.)
Speeds look wrong
Re-check calibration. The 4 points must lie flat on the road, in the correct click order, and the width/length must be real measured values. A 10% measurement error produces a 10% speed error.
Dashboard shows "not calibrated"
Expected until you run the calibration tool. Counting and tracking still work.
Slow or laggy live stream
See Performance tuning. On CPU, prefer analyzing recorded files over live streams.
FAQ
Can I run multiple cameras?
Run one RadarHub instance per camera on different ports: --port 8080, --port 8081, and so on. Each instance keeps its own config and violation log.
Does it detect pedestrians or bikes?
The model can see them, but RadarHub filters to motor vehicles by default. The vehicle class list is one line in radar/config.py if you want to extend it.
Can I get license plates?
Plate recognition (OCR on violation snapshots) is on the roadmap as an add-on. The snapshot system was designed with this in mind.
Is my footage sent anywhere?
No. Everything, including model inference, runs locally on your machine.