Technical report
We built a detector-plus-rules system that runs fully offline and produces valid, deterministic output for every video, inside the 3x time budget on a 4 GB laptop GPU. On the four organizer samples it finds red-light runs, stop-line violations, stopped vehicles and vehicles not yielding at the crossings; we checked every class by eye. Part B never raises a false alarm on the samples, but we had no accident footage to calibrate its early warning against.
What we built
A YOLO11m detector and ByteTrack produce tracks; kinematics turn them into speeds normalised by vehicle size;
fourteen explicit rules turn tracks into segments; post-processing enforces the output contract. Part B runs its
own online copy of detector and tracker on every third frame and combines time-to-collision, braking, swerving,
wrong-way motion and pedestrian conflicts in a logistic score. The scene (lanes, stop lines, crosswalks, zones)
is drawn once in scene.json; where it is missing, the road surface, lane flow and busy crossing points are
learned from each video's own tracks.
On the organizer samples
The samples show one signalised Tashkent intersection at noon and at dusk. We drew the scene once (carriageway, stop line, three crossings, two signal heads, the junction box) on one frame; every video is aligned to that drawing by SIFT and a RANSAC homography, so a slightly moved camera does not move the lines. There are no labels, so we reviewed our own predictions frame by frame: start, middle and end frames with the involved tracks highlighted.
| Class | Reviewed | Correct | Unclear | Wrong | What we changed |
|---|---|---|---|---|---|
| red light | 3 | 3 | 0 | 0 | nothing |
| stop line | 3 | 2 | 1 | 0 | nothing |
| stopped vehicle | 2 | 2 | 0 | 0 | nothing |
| failure to yield | 4 | 3 | 1 | 0 | segments now run from "vehicle enters the crossing" to "leaves it" (were 0.3 to 1 s, now 0.7 to 4.5 s) |
| near miss | 2 | 0 | 1 | 1 | a pair now needs a motor vehicle (two pedestrians had been flagged) |
| jaywalking | 1 | 0 | 0 | 1 | a jaywalker must walk 1.5 body lengths on the road (a person waiting at the kerb had been flagged) |
This measures precision only. Nobody watched the full 18 minutes for missed events, so recall
is unknown; data/review_samples.json in the repository lists every verdict.
Real crash clips
The samples contain no accidents, so we tested the accident rule on four public CCTV clips from other intersections: three real crashes and one dense-traffic clip without events. We labelled the crashes with the task's conventions and scored them, together with our two development clips, with the official evaluator.
| Clip | Ground truth | RoadSight |
|---|---|---|
| Rollover, downtown junction, day | 5.85-8.50 s | accident 5.95-8.43 s (matched even at tIoU 0.7) |
| T-bone, junction, day (6 s clip) | 0.70-5.00 s | missed |
| Head-on, junction, night | 2.00-4.00 s | missed |
| Three normal-traffic clips | no events | no events |
Before this test the rollover was reported as a near miss and no clip produced an accident. A vehicle that spins or rolls breaks its track, so a track vanishing mid-junction at the moment of contact now confirms the impact, the new IDs of the same wreck extend the crash until it stops, and a near miss is dropped when an accident is confirmed for the same pair. Accepting any speed jolt at contact would also have caught the T-bone, but it produced three false accidents in dense stop-and-go traffic, so the rule stays conservative. The night head-on is lost in headlight glare. Part B does not anticipate these crashes. Replaying its recorded tracks showed why: before the rollover, time to collision only becomes finite 0.2 s before impact, and nothing rises before the night head-on, while on the organizer's camera a finite time to collision appears in 47% of normal frames (queues and perspective make "about to touch" routine). No setting of our hand-made features separates the seconds before these crashes from everyday traffic at the test camera, so we did not tune Part B on three clips: that would raise false alarms on the camera that matters. A real improvement needs a learned anticipation model trained on a crash dataset.
What worked
- Box-top velocity. Taking velocity from the top edge of each box instead of the bottom, and ignoring boxes cut by the frame border, removed most false braking.
- Noise-relative thresholds. Scaling braking and swerving by each video's own noise made the same rule work on a quiet highway and a dense city underpass.
- Learned lane flow. One vote per track per grid cell, with the track's own vote removed when it is tested, gives wrong-way detection without drawing lanes.
- A conjunction feature for risk. Time to collision alone fires in every queue; multiplying it by braking or swerving keeps alarms for evasive manoeuvres.
- Tests as the contract. Interface, format, non-overlap, determinism, causality, offline and one scenario per rule run on every change: 46 tests.
Ablations
Measured during development on two public traffic clips with no events (a 4K highway clip and a 1080p city underpass), so every event or alarm there is a false positive.
Kinematic noise
| Change | Measure | Highway | City |
|---|---|---|---|
| Foot-point kinematics | Acceleration, 1-in-1000 low tail, BL/s² | -4.08 | -18.1 |
| + track splitting, border rows, box-top velocity | same | -1.59 | -10.3 |
| Foot-point kinematics | Heading change in 1 s, 99.9th percentile | 158° | 180° |
| + same fixes | same | 55° | 180° |
Detection coverage
Detecting at 960 px instead of 640, feeding low-score boxes to ByteTrack and starting tracks at 0.3 instead of 0.6 took the city clip from 95 to 419 tracks, and from 4.5 to 23.8 tracked objects per processed frame. The new tracks are mostly small and faint, so the rules only use the 308 tracks with mean confidence of at least 0.4 and a median size of at least 2.5% of the frame height.
False events and alarms
| Change | Measure | Highway | City |
|---|---|---|---|
| Near-miss rule with fixed thresholds (640 px) | False events | 0 | 2 |
| + size filter, closing speed, noise-relative evasion | same | 0 | 0 |
| 960 px detection, lower track thresholds | same | 0 | 9 |
| + reliable tracks, ID-switch checks, displacement before a stop | same | 0 | 1 |
| + wider border margin, braking must cut speed by 40% | same | 0 | 0 |
| Risk v0 (moving-average velocity) | Frames above the 0.5 alarm | 6.7% | 80.2% |
| + least-squares velocity, reliability filters, noise floor | same | 0.0% | 5.6% |
| + conjunction feature | same | 0.0% | 2.3% |
| Final detector, track-confidence filter, bias -5.0 | same | 0.0% | 1.2% (one alarm) |
Runtime
| Clip | Length | Part A | Part B | Both / length |
|---|---|---|---|---|
| Loading. | ||||
The organizer's harness on an RTX 3050 laptop GPU (4 GB). YOLO11m FP16 at 960 px for events (~12.5 frames per second of video) and 640 px for risk (~8 per second). Most of Part B is the harness decoding every 4K 10-bit frame. The limit is 3x the video length.
What did not work
- Per-frame braking from an exponential moving average. Differences of smoothed positions were too noisy at 8 Hz; the brake feature sat at its maximum in 89% of city frames. Least-squares slopes over 0.8 s fixed it.
- Dense shallow-angle traffic is still hard. Heading noise stays high for mid-distance vehicles in the city clip, near-miss candidates reach 0.63 against the 0.70 gate, and the risk score raises one false alarm in 42 seconds of stop-and-go traffic. More margin needs a CCTV-tuned detector or labelled data to fit on.
- Fire and smoke. A colour-and-flicker heuristic fires on tail lights and signs; with no trained detector that fits the budget, the class ships disabled.
Next steps
- Label the organizer samples end to end (recall, not just precision) and run
tools/tune.pyto set per-class thresholds and boundary offsets. - Congestion: the samples show queues spilling into the junction, which the congestion rule (a whole direction at a standstill for 15 s through a green phase) never reported. It needs labelled examples to calibrate.
- Part B: train a learned anticipation model on a public crash dataset (DoTA, CCD or the ACCIDENT benchmark) on top of
the tracks, and evaluate it on recorded tracks with
tools/tune_risk.py, which counts every score of 0.5 or more on the organizer samples as a false alarm. - Fine-tune the detector on CCTV viewpoints (UA-DETRAC) if small or night vehicles are missed.