Every traffic event, as a time segment โ€” and an alarm before the crash.

TrafficWatch watches one fixed CCTV view of a signalised junction, reports 14 kinds of traffic events as [start, end, label] segments, and streams a causal accident-risk score frame by frame.

Try the live demo Sample results Source code

Team

Built by team IntDev.

Problem and approach

One camera, one angle, no labels. Instead of training a video classifier on footage we do not have, we turn the video into trajectories on a map of this junction and express every class as a rule over them โ€” the same definitions the annotators use (start/end conventions included).

video10โ€“12 fps YOLO11sroad users ยท COCO trackerByteTrack-style kinematics on mapspeed in body-lengths/s 14 class rulesstart/end conventions segmentsmerge ยท clip scene layoutSIFT-registered signal headsred / amber / green pixel cues @2 Hzobstacle ยท fire Part B: causal CPArisk per frame Part A (offline, whole video) Dashed: fixed configuration drawn once on a reference frame and mapped onto each video.

What is learned, what is rule-based

learned Road-user detection only: YOLO11s pre-trained on COCO (Ultralytics weights, no fine-tuning โ€” we have no labels for this camera).

rule-based Everything after detection: tracking, the scene map, signal reading, all 14 event classes and the Part B risk score. Rules are deterministic, explainable and unit-tested on synthetic trajectories drawn on the real map.

Why: the hidden test set contains events that are not in the samples, so any classifier trained on the samples would not have seen them. Rules written from the class definitions do not need examples.

Key design decisions

  • Speeds in body lengths per second (image speed / โˆš(box area)): removes most of the perspective, so one threshold works near and far.
  • Scene registration. The framing moves between clips (up to 60 px and ~1ยฐ in our stills), so the map is re-registered on every video with SIFT + RANSAC.
  • Only trust what is visible. The queue approaching the camera has its signal facing away, and the head we can see on that side is a pedestrian signal (it showed WALK while that queue was flowing), so red-light is judged only where the vehicle head faces the camera.
  • Stopped vs queued: a stopped vehicle is one that other traffic keeps passing.

How each class is detected

ClassRuleStart โ†’ end

EDA of the camera

Stills first (they shaped the scene map), then the sample videos.

Results on the sample videos

Annotated playback rendered with our own tooling. Click an event on the timeline to jump to it.

Sample-video results appear here once tools/build_site_data.py has been run on the samples.

Operator dashboard

All sample videos together, as a traffic centre would read them.

Waiting for sample-video data.

Live demo

Run the full model on a free Google Colab T4 GPU: open the notebook, choose Runtime โ†’ Run all, and use the app at the gradio.live link it prints (about 3 minutes to start).

Open the demo in Colab

When a demo server is running, you can also upload an .mp4 up to 2 minutes and 200 MB from this camera right here; progress is shown below.

Drop an .mp4 here or

Technical report

What we built

A detector โ†’ tracker โ†’ map โ†’ rules pipeline (Part A), a causal closest-point-of-approach risk model (Part B), and the tooling around it: scene registration, a labeling page for dev sets, annotated renders, EDA, a Gradio demo that runs on a free Colab GPU and 26 unit tests with synthetic trajectories on the real layout.

What worked

  • SIFT registration fits the layout on every still, including dusk frames shifted by 60 px.
  • COCO YOLO11s finds cars, buses, pedestrians and cyclists reliably in day and dusk frames.
  • Calibrating on a labelled sample clip raised Score A from 0.265 to 0.705 (one clip, one annotator).
  • Part B false alarms dropped from ~5 to ~1 per minute on the sample videos once overlapping (occluding) boxes and cars passing a queue in the next lane stopped counting as collision courses.
  • All four sample videos run in about half the 3ร— time budget on a laptop CPU.
  • Body-length-normalised speed made one set of thresholds work across the depth of the scene.

What did not (or is not proven)

  • The thresholds come from one labelled 67 s clip and a detection-by-detection review of a second video โ€” a first calibration, not a validated result.
  • Reading the pedestrian head as the queue's signal was wrong (it showed WALK while that queue flowed); red-light for the queue towards the camera is therefore not judged.
  • Top-down footage breaks COCO detection (cars read as "cell phones").
  • Pixel cues (obstacle, fire) needed camera-drift compensation and shape filters to stop firing on lane markings; smoke without flames is not detected.
  • illegal_turn needs the junction's prohibited movements; until confirmed it is never predicted, because a predicted class that never occurs costs a whole class in the macro-F1.
  • Near-miss vs normal hard braking in a queue is the least certain boundary.

Next

  • Label all four sample videos with the labeling page and tune thresholds per class at IoU 0.7.
  • Fine-tune the detector on frames of this camera (dusk, occlusion in the queue).
  • Learned re-scoring of accident / near-miss candidates on public crash datasets (CCD, DoTA).
  • Calibrate the risk score on those datasets so 0.5 means "probably within 5 s".

Honest failure cases